image_resolution_test.dart 6.86 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// 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 {
15
  TestAssetBundle(this._assetBundleMap);
16

17
  final Map<String, List<String>> _assetBundleMap;
18 19 20 21 22 23 24 25 26 27

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

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

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

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

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

      assetBundleMap[mainAssetPath] = <String>[];

46
      final AssetImage assetImage = AssetImage(
47
          mainAssetPath,
48
          bundle: TestAssetBundle(assetBundleMap));
49
      const ImageConfiguration configuration = ImageConfiguration();
50 51

      assetImage.obtainKey(configuration)
52 53 54 55
        .then(expectAsync1((AssetBundleImageKey bundleKey) {
          expect(bundleKey.name, mainAssetPath);
          expect(bundleKey.scale, 1.0);
        }));
56 57 58 59 60 61
    }

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

62 63 64
    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');
    });
65

66 67 68
    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');
    });
69

70 71 72
    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');
    });
73

74 75 76
    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');
    });
77

78 79 80
    test('When asset path contains variant identifier in parent folder scale is 1.0', () {
      _buildAndTestWithOneAsset('assets/parentFolder/3.0x/leafFolder/normalFile.png');
    });
81 82 83 84 85 86 87 88 89 90 91 92 93
  });


  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];

94
      final TestAssetBundle testAssetBundle = TestAssetBundle(
95 96
          assetBundleMap);

97
      final AssetImage assetImage = AssetImage(
98 99 100 101 102
          mainAssetPath,
          bundle: testAssetBundle);

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

      // we also have the exact match for this scale, let's use it
109
      assetImage.obtainKey(ImageConfiguration(
110 111 112
        bundle: testAssetBundle,
        devicePixelRatio: 3.0,
      )).then(expectAsync1((AssetBundleImageKey bundleKey) {
113 114 115 116 117 118 119 120 121 122 123 124 125 126
        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];

127
      final TestAssetBundle testAssetBundle = TestAssetBundle(
128 129
          assetBundleMap);

130
      final AssetImage assetImage = AssetImage(
131
          mainAssetPath,
132
          bundle: TestAssetBundle(assetBundleMap));
133 134 135


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

141
      assetImage.obtainKey(ImageConfiguration(
142 143 144
        bundle: testAssetBundle,
        devicePixelRatio: 3.0)
      ).then(expectAsync1((AssetBundleImageKey bundleKey) {
145 146 147 148
        expect(bundleKey.name, mainAssetPath);
        expect(bundleKey.scale, 1.0);
      }));
    });
149
  }, skip: isBrowser);
150

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


156 157 158 159 160
    void _buildBundleAndTestVariantLogic(
      double deviceRatio,
      double chosenAssetRatio,
      String expectedAssetPath,
    ) {
161 162 163 164 165
      final Map<String, List<String>> assetBundleMap =
      <String, List<String>>{};

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

166
      final TestAssetBundle testAssetBundle = TestAssetBundle(
167 168
          assetBundleMap);

169
      final AssetImage assetImage = AssetImage(
170 171 172 173
          mainAssetPath,
          bundle: testAssetBundle);

      // we have 1.0 and 3.0, asking for 1.5 should give
174
      assetImage.obtainKey(ImageConfiguration(
175 176 177
        bundle: testAssetBundle,
        devicePixelRatio: deviceRatio)
      ).then(expectAsync1((AssetBundleImageKey bundleKey) {
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
        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);
    });
205
  }, skip: isBrowser);
206 207

}