fade_in_image_test.dart 9.08 KB
Newer Older
1 2 3 4 5 6 7 8 9
// 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:ui' as ui;

import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
10
import '../painting/image_test_utils.dart';
11

12
Future<void> main() async {
13 14 15
  // These must run outside test zone to complete
  final ui.Image targetImage = await createTestImage();
  final ui.Image placeholderImage = await createTestImage();
16
  final ui.Image secondPlaceholderImage = await createTestImage();
17 18 19 20 21 22 23 24 25

  group('FadeInImage', () {
    testWidgets('animates uncached image and shows cached image immediately', (WidgetTester tester) async {
      // State type is private, hence using dynamic.
      dynamic state() => tester.state(find.byType(FadeInImage));

      RawImage displayedImage() => tester.widget(find.byType(RawImage));

      // The placeholder is expected to be already loaded
26
      final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage);
27 28

      // Test case: long loading image
29
      final TestImageProvider imageProvider = TestImageProvider(targetImage);
30

31
      await tester.pumpWidget(FadeInImage(
32 33 34 35 36 37
        placeholder: placeholderProvider,
        image: imageProvider,
        fadeOutDuration: const Duration(milliseconds: 50),
        fadeInDuration: const Duration(milliseconds: 50),
      ));

38
      expect(displayedImage().image, null); // image providers haven't completed yet
39 40 41
      placeholderProvider.complete();
      await tester.pump();

42
      expect(displayedImage().image, same(placeholderImage)); // placeholder completed
43 44
      expect(state().phase, FadeInImagePhase.waiting);

45 46
      imageProvider.complete(); // load the image
      expect(state().phase, FadeInImagePhase.fadeOut); // fade out placeholder
47 48 49 50 51
      for (int i = 0; i < 7; i += 1) {
        expect(displayedImage().image, same(placeholderImage));
        await tester.pump(const Duration(milliseconds: 10));
      }
      expect(displayedImage().image, same(targetImage));
52
      expect(state().phase, FadeInImagePhase.fadeIn); // fade in image
53 54 55 56
      for (int i = 0; i < 6; i += 1) {
        expect(displayedImage().image, same(targetImage));
        await tester.pump(const Duration(milliseconds: 10));
      }
57
      expect(state().phase, FadeInImagePhase.completed); // done
58 59 60 61
      expect(displayedImage().image, same(targetImage));

      // Test case: re-use state object (didUpdateWidget)
      final dynamic stateBeforeDidUpdateWidget = state();
62
      await tester.pumpWidget(FadeInImage(
63 64 65 66 67
        placeholder: placeholderProvider,
        image: imageProvider,
      ));
      final dynamic stateAfterDidUpdateWidget = state();
      expect(stateAfterDidUpdateWidget, same(stateBeforeDidUpdateWidget));
68
      expect(stateAfterDidUpdateWidget.phase, FadeInImagePhase.completed); // completes immediately
69 70 71 72
      expect(displayedImage().image, same(targetImage));

      // Test case: new state object but cached image
      final dynamic stateBeforeRecreate = state();
73 74
      await tester.pumpWidget(Container()); // clear widget tree to prevent state reuse
      await tester.pumpWidget(FadeInImage(
75 76 77 78 79 80
        placeholder: placeholderProvider,
        image: imageProvider,
      ));
      expect(displayedImage().image, same(targetImage));
      final dynamic stateAfterRecreate = state();
      expect(stateAfterRecreate, isNot(same(stateBeforeRecreate)));
81
      expect(stateAfterRecreate.phase, FadeInImagePhase.completed); // completes immediately
82 83
      expect(displayedImage().image, same(targetImage));
    });
84 85 86 87 88

    testWidgets('handles a updating the placeholder image', (WidgetTester tester) async {
      RawImage displayedImage() => tester.widget(find.byType(RawImage));

      // The placeholder is expected to be already loaded
89 90
      final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage);
      final TestImageProvider secondPlaceholderProvider = TestImageProvider(secondPlaceholderImage);
91 92

      // Test case: long loading image
93
      final TestImageProvider imageProvider = TestImageProvider(targetImage);
94

95
      await tester.pumpWidget(FadeInImage(
96 97 98 99 100 101 102 103 104 105 106
        placeholder: placeholderProvider,
        image: imageProvider,
        fadeOutDuration: const Duration(milliseconds: 50),
        fadeInDuration: const Duration(milliseconds: 50),
      ));
      placeholderProvider.complete();
      await tester.pump();

      expect(displayedImage().image, same(placeholderImage)); // placeholder completed
      expect(displayedImage().image, isNot(same(secondPlaceholderImage)));

107
      await tester.pumpWidget(FadeInImage(
108 109 110 111 112 113 114 115 116 117 118
        placeholder: secondPlaceholderProvider,
        image: imageProvider,
        fadeOutDuration: const Duration(milliseconds: 50),
        fadeInDuration: const Duration(milliseconds: 50),
      ));
      secondPlaceholderProvider.complete();
      await tester.pump();

      expect(displayedImage().image, isNot(same(placeholderImage))); // placeholder replaced
      expect(displayedImage().image, same(secondPlaceholderImage));
    });
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

    group('semanticLabel', () {

      const String placeholderSemanticText = 'Test placeholder semantic label';
      const String imageSemanticText = 'Test image semantic label';
      const Duration animationDuration = Duration(milliseconds: 50);

      testWidgets('assigned correctly according to placeholder or image', (WidgetTester tester) async {
        // The semantics widget that is created
        Semantics displayedWidget() => tester.widget(find.byType(Semantics));
        // The placeholder is expected to be already loaded
        final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage);
        // The image which takes long to load
        final TestImageProvider imageProvider = TestImageProvider(targetImage);
        // Test case: Image and Placeholder semantic texts are provided.
        await tester.pumpWidget(FadeInImage(
            placeholder: placeholderProvider,
            image: imageProvider,
            fadeOutDuration: animationDuration,
            fadeInDuration: animationDuration,
            imageSemanticLabel: imageSemanticText,
140
            placeholderSemanticLabel: placeholderSemanticText,
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
        ));

        placeholderProvider.complete(); // load the placeholder
        await tester.pump();
        expect(displayedWidget().properties.label, same(placeholderSemanticText));

        imageProvider.complete(); // load the image
        for (int i = 0; i < 10; i += 1) {
          await tester.pump(const Duration(milliseconds: 10)); // do the fadeout and fade in
        }
        expect(displayedWidget().properties.label, same(imageSemanticText));
      });

      testWidgets('assigned correctly with only one semantics text', (WidgetTester tester) async {
        // The semantics widget that is created
        Semantics displayedWidget() => tester.widget(find.byType(Semantics));
        // The placeholder is expected to be already loaded
        final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage);
        // The image which takes long to load
        final TestImageProvider imageProvider = TestImageProvider(targetImage);
        // Test case: Placeholder semantic text provided.
        await tester.pumpWidget(FadeInImage(
            placeholder: placeholderProvider,
            image: imageProvider,
            fadeOutDuration: animationDuration,
            fadeInDuration: animationDuration,
167
            placeholderSemanticLabel: placeholderSemanticText,
168 169 170 171 172 173 174 175 176 177 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 205 206
        ));

        placeholderProvider.complete(); // load the placeholder
        await tester.pump();
        expect(displayedWidget().properties.label, same(placeholderSemanticText));

        imageProvider.complete(); // load the image
        for (int i = 0; i < 10; i += 1) {
          await tester.pump(const Duration(milliseconds: 10)); // do the fadeout and fade in
        }
        expect(displayedWidget().properties.label, same(''));
      });

      testWidgets('assigned correctly without any semantics text', (WidgetTester tester) async {
        // The semantics widget that is created
        Semantics displayedWidget() => tester.widget(find.byType(Semantics));
        // The placeholder is expected to be already loaded
        final TestImageProvider placeholderProvider = TestImageProvider(placeholderImage);
        // The image which takes long to load
        final TestImageProvider imageProvider = TestImageProvider(targetImage);
        // Test case: No semantic text provided.
        await tester.pumpWidget(FadeInImage(
            placeholder: placeholderProvider,
            image: imageProvider,
            fadeOutDuration: animationDuration,
            fadeInDuration: animationDuration,
        ));

        placeholderProvider.complete(); // load the placeholder
        await tester.pump();
        expect(displayedWidget().properties.label, same(''));

        imageProvider.complete(); // load the image
        for (int i = 0; i < 10; i += 1) {
          await tester.pump(const Duration(milliseconds: 10)); // do the fadeout and fade in
        }
        expect(displayedWidget().properties.label, same(''));
      });
    });
207 208
  });
}