image_resolution_test.dart 7.03 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';


class TestAssetBundle extends CachingAssetBundle {
16
  TestAssetBundle(this._assetBundleMap);
17 18 19 20 21 22 23 24 25 26 27 28

  Map<String, List<String>> _assetBundleMap;

  Map<String, int> loadCallCount = <String, int>{};

  String get _assetBundleContents {
    return json.encode(_assetBundleMap);
  }

  @override
  Future<ByteData> load(String key) async {
    if (key == 'AssetManifest.json')
29
      return ByteData.view(Uint8List.fromList(
30 31 32 33
          const Utf8Encoder().convert(_assetBundleContents)).buffer);

    loadCallCount[key] = loadCallCount[key] ?? 0 + 1;
    if (key == 'one')
34
      return ByteData(1)
35
        ..setInt8(0, 49);
36
    throw FlutterError('key not found');
37 38 39 40 41 42 43 44 45 46
  }
}

void main() {
  group('1.0 scale device tests', () {
    void _buildAndTestWithOneAsset(String mainAssetPath) {
      final Map<String, List<String>> assetBundleMap = <String, List<String>>{};

      assetBundleMap[mainAssetPath] = <String>[];

47
      final AssetImage assetImage = AssetImage(
48
          mainAssetPath,
49
          bundle: TestAssetBundle(assetBundleMap));
50
      const ImageConfiguration configuration = ImageConfiguration();
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

      assetImage.obtainKey(configuration)
          .then(expectAsync1((AssetBundleImageKey bundleKey) {
        expect(bundleKey.name, mainAssetPath);
        expect(bundleKey.scale, 1.0);
      }));
    }

    test('When asset is main variant check scale is 1.0', () {
      _buildAndTestWithOneAsset('assets/normalFolder/normalFile.png');
    });


    test(
        'When asset path and key are the same string even though it could be took as a 3.0x variant',
            () async {
          _buildAndTestWithOneAsset('assets/parentFolder/3.0x/normalFile.png');
        });


    test(
        'When asset path contains variant identifier as part of parent folder name scale is 1.0',
            () {
          _buildAndTestWithOneAsset(
              'assets/parentFolder/__3.0x__/leafFolder/normalFile.png');
        });


    test(
        'When asset path contains variant identifier as part of leaf folder name scale is 1.0',
            () {
          _buildAndTestWithOneAsset(
              'assets/parentFolder/__3.0x_leaf_folder_/normalFile.png');
        });


    test(
        'When asset path contains variant identifier as part of parent folder name scale is 1.0',
            () {
          _buildAndTestWithOneAsset(
              'assets/parentFolder/__3.0x__/leafFolder/normalFile.png');
        });

    test(
        'When asset path contains variant identifier in parent folder scale is 1.0',
            () {
          _buildAndTestWithOneAsset(
              'assets/parentFolder/3.0x/leafFolder/normalFile.png');
        });
  });


  group('High-res device behavior tests', () {
    test('When asset is not main variant check scale is not 1.0', () {
      const String mainAssetPath = 'assets/normalFolder/normalFile.png';
      const String variantPath = 'assets/normalFolder/3.0x/normalFile.png';

      final Map<String, List<String>> assetBundleMap =
      <String, List<String>>{};

      assetBundleMap[mainAssetPath] = <String>[mainAssetPath, variantPath];

113
      final TestAssetBundle testAssetBundle = TestAssetBundle(
114 115
          assetBundleMap);

116
      final AssetImage assetImage = AssetImage(
117 118 119 120 121 122 123 124 125 126 127
          mainAssetPath,
          bundle: testAssetBundle);

      // we have the exact match for this scale, let's use it
      assetImage.obtainKey(const ImageConfiguration())
          .then(expectAsync1((AssetBundleImageKey bundleKey) {
        expect(bundleKey.name, mainAssetPath);
        expect(bundleKey.scale, 1.0);
      }));

      // we also have the exact match for this scale, let's use it
128
      assetImage.obtainKey(ImageConfiguration(
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
          bundle: testAssetBundle,
          devicePixelRatio: 3.0))
          .then(expectAsync1((AssetBundleImageKey bundleKey) {
        expect(bundleKey.name, variantPath);
        expect(bundleKey.scale, 3.0);
      }));
    });

    test(
        'When high-res device and high-res asset not present in bundle then  return main variant', () {
      const String mainAssetPath = 'assets/normalFolder/normalFile.png';

      final Map<String, List<String>> assetBundleMap =
      <String, List<String>>{};

      assetBundleMap[mainAssetPath] = <String>[mainAssetPath];

146
      final TestAssetBundle testAssetBundle = TestAssetBundle(
147 148
          assetBundleMap);

149
      final AssetImage assetImage = AssetImage(
150
          mainAssetPath,
151
          bundle: TestAssetBundle(assetBundleMap));
152 153 154 155 156 157 158 159


      assetImage.obtainKey(const ImageConfiguration())
          .then(expectAsync1((AssetBundleImageKey bundleKey) {
        expect(bundleKey.name, mainAssetPath);
        expect(bundleKey.scale, 1.0);
      }));

160
      assetImage.obtainKey(ImageConfiguration(
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
          bundle: testAssetBundle,
          devicePixelRatio: 3.0))
          .then(expectAsync1((AssetBundleImageKey bundleKey) {
        expect(bundleKey.name, mainAssetPath);
        expect(bundleKey.scale, 1.0);
      }));
    });
  });

  group(
      'Regression - When assets available are 1.0 and 3.0 check devices with a range of scales', () {
    const String mainAssetPath = 'assets/normalFolder/normalFile.png';
    const String variantPath = 'assets/normalFolder/3.0x/normalFile.png';


    void _buildBundleAndTestVariantLogic(double deviceRatio, double chosenAssetRatio,
        String expectedAssetPath) {
      final Map<String, List<String>> assetBundleMap =
      <String, List<String>>{};

      assetBundleMap[mainAssetPath] = <String>[mainAssetPath, variantPath];

183
      final TestAssetBundle testAssetBundle = TestAssetBundle(
184 185
          assetBundleMap);

186
      final AssetImage assetImage = AssetImage(
187 188 189 190
          mainAssetPath,
          bundle: testAssetBundle);

      // we have 1.0 and 3.0, asking for 1.5 should give
191
      assetImage.obtainKey(ImageConfiguration(
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
          bundle: testAssetBundle,
          devicePixelRatio: deviceRatio))
          .then(expectAsync1((AssetBundleImageKey bundleKey) {
        expect(bundleKey.name, expectedAssetPath);
        expect(bundleKey.scale, chosenAssetRatio);
      }));
    }

    test('Obvious case 1.0 - we have exact asset', () {
      _buildBundleAndTestVariantLogic(1.0, 1.0, mainAssetPath);
    });

    test('Obvious case 3.0 - we have exact asset', () {
      _buildBundleAndTestVariantLogic(3.0, 3.0, variantPath);
    });

    test('Typical case 2.0', () {
      _buildBundleAndTestVariantLogic(2.0, 1.0, mainAssetPath);
    });

    test('Borderline case 2.01', () {
      _buildBundleAndTestVariantLogic(2.01, 3.0, variantPath);
    });
    test('Borderline case 2.9', () {
      _buildBundleAndTestVariantLogic(2.9, 3.0, variantPath);
    });

    test('Typical case 4.0', () {
      _buildBundleAndTestVariantLogic(4.0, 3.0, variantPath);
    });
  });

}