transitions_test.dart 11.2 KB
Newer Older
1 2 3 4
// Copyright 2016 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.

5 6
import 'dart:math' as math;

7
import 'package:flutter_test/flutter_test.dart';
8
import 'package:flutter/rendering.dart';
9
import 'package:flutter/widgets.dart';
10 11 12

void main() {
  testWidgets('toString control test', (WidgetTester tester) async {
13
    const Widget widget = FadeTransition(
14
      opacity: kAlwaysCompleteAnimation,
15
      child: Text('Ready', textDirection: TextDirection.ltr),
16 17 18
    );
    expect(widget.toString, isNot(throwsException));
  });
19

20
  group('DecoratedBoxTransition test', () {
21 22
    final DecorationTween decorationTween = DecorationTween(
      begin: BoxDecoration(
23
        color: const Color(0xFFFFFFFF),
24
        border: Border.all(
25 26 27 28 29 30
          color: const Color(0xFF000000),
          style: BorderStyle.solid,
          width: 4.0,
        ),
        borderRadius: BorderRadius.zero,
        shape: BoxShape.rectangle,
31 32
        boxShadow: const <BoxShadow> [BoxShadow(
          color: Color(0x66000000),
33 34 35 36
          blurRadius: 10.0,
          spreadRadius: 4.0,
        )],
      ),
37
      end: BoxDecoration(
38
        color: const Color(0xFF000000),
39
        border: Border.all(
40 41 42 43
          color: const Color(0xFF202020),
          style: BorderStyle.solid,
          width: 1.0,
        ),
44
        borderRadius: BorderRadius.circular(10.0),
45 46 47 48 49 50 51 52
        shape: BoxShape.rectangle,
        // No shadow.
      ),
    );

    AnimationController controller;

    setUp(() {
53
      controller = AnimationController(vsync: const TestVSync());
54 55 56
    });

    testWidgets(
57
      'decoration test',
58
      (WidgetTester tester) async {
59
        final DecoratedBoxTransition transitionUnderTest =
60
            DecoratedBoxTransition(
61
              decoration: decorationTween.animate(controller),
Ian Hickson's avatar
Ian Hickson committed
62
              child: const Text('Doesn\'t matter', textDirection: TextDirection.ltr),
63
            );
64

65
        await tester.pumpWidget(transitionUnderTest);
66
        RenderDecoratedBox actualBox =
67 68 69
            tester.renderObject(find.byType(DecoratedBox));
        BoxDecoration actualDecoration = actualBox.decoration;

70
        expect(actualDecoration.color, const Color(0xFFFFFFFF));
71 72 73 74 75 76 77 78 79 80
        expect(actualDecoration.boxShadow[0].blurRadius, 10.0);
        expect(actualDecoration.boxShadow[0].spreadRadius, 4.0);
        expect(actualDecoration.boxShadow[0].color, const Color(0x66000000));

        controller.value = 0.5;

        await tester.pump();
        actualBox = tester.renderObject(find.byType(DecoratedBox));
        actualDecoration = actualBox.decoration;

81
        expect(actualDecoration.color, const Color(0xFF7F7F7F));
82
        expect(actualDecoration.border, isInstanceOf<Border>());
Ian Hickson's avatar
Ian Hickson committed
83 84 85 86
        final Border border = actualDecoration.border;
        expect(border.left.width, 2.5);
        expect(border.left.style, BorderStyle.solid);
        expect(border.left.color, const Color(0xFF101010));
87
        expect(actualDecoration.borderRadius, BorderRadius.circular(5.0));
88 89 90 91 92 93 94 95 96 97 98 99
        expect(actualDecoration.shape, BoxShape.rectangle);
        expect(actualDecoration.boxShadow[0].blurRadius, 5.0);
        expect(actualDecoration.boxShadow[0].spreadRadius, 2.0);
        // Scaling a shadow doesn't change the color.
        expect(actualDecoration.boxShadow[0].color, const Color(0x66000000));

        controller.value = 1.0;

        await tester.pump();
        actualBox = tester.renderObject(find.byType(DecoratedBox));
        actualDecoration = actualBox.decoration;

100
        expect(actualDecoration.color, const Color(0xFF000000));
101
        expect(actualDecoration.boxShadow, null);
102
      },
103 104 105
    );

    testWidgets('animations work with curves test', (WidgetTester tester) async {
106
      final Animation<Decoration> curvedDecorationAnimation =
107
          decorationTween.animate(CurvedAnimation(
108 109 110
            parent: controller,
            curve: Curves.easeOut,
          ));
111 112

      final DecoratedBoxTransition transitionUnderTest =
113
          DecoratedBoxTransition(
114 115
            decoration: curvedDecorationAnimation,
            position: DecorationPosition.foreground,
Ian Hickson's avatar
Ian Hickson committed
116
            child: const Text('Doesn\'t matter', textDirection: TextDirection.ltr),
117 118 119
          );

      await tester.pumpWidget(transitionUnderTest);
120
      RenderDecoratedBox actualBox =
121 122 123
          tester.renderObject(find.byType(DecoratedBox));
      BoxDecoration actualDecoration = actualBox.decoration;

124
      expect(actualDecoration.color, const Color(0xFFFFFFFF));
125 126 127 128 129 130 131 132 133 134
      expect(actualDecoration.boxShadow[0].blurRadius, 10.0);
      expect(actualDecoration.boxShadow[0].spreadRadius, 4.0);
      expect(actualDecoration.boxShadow[0].color, const Color(0x66000000));

      controller.value = 0.5;

      await tester.pump();
      actualBox = tester.renderObject(find.byType(DecoratedBox));
      actualDecoration = actualBox.decoration;

135
      // Same as the test above but the values should be much closer to the
136
      // tween's end values given the easeOut curve.
137
      expect(actualDecoration.color, const Color(0xFF505050));
138
      expect(actualDecoration.border, isInstanceOf<Border>());
Ian Hickson's avatar
Ian Hickson committed
139 140 141 142
      final Border border = actualDecoration.border;
      expect(border.left.width, closeTo(1.9, 0.1));
      expect(border.left.style, BorderStyle.solid);
      expect(border.left.color, const Color(0xFF151515));
143
      expect(actualDecoration.borderRadius.resolve(TextDirection.ltr).topLeft.x, closeTo(6.8, 0.1));
144 145 146 147 148 149 150
      expect(actualDecoration.shape, BoxShape.rectangle);
      expect(actualDecoration.boxShadow[0].blurRadius, closeTo(3.1, 0.1));
      expect(actualDecoration.boxShadow[0].spreadRadius, closeTo(1.2, 0.1));
      // Scaling a shadow doesn't change the color.
      expect(actualDecoration.boxShadow[0].color, const Color(0x66000000));
    });
  });
151 152

  testWidgets('AlignTransition animates', (WidgetTester tester) async {
153 154
    final AnimationController controller = AnimationController(vsync: const TestVSync());
    final Animation<Alignment> alignmentTween = AlignmentTween(
155 156 157
      begin: const Alignment(-1.0, 0.0),
      end: const Alignment(1.0, 1.0),
    ).animate(controller);
158
    final Widget widget = AlignTransition(
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
      alignment: alignmentTween,
      child: const Text('Ready', textDirection: TextDirection.ltr),
    );

    await tester.pumpWidget(widget);

    final RenderPositionedBox actualPositionedBox = tester.renderObject(find.byType(Align));

    Alignment actualAlignment = actualPositionedBox.alignment;
    expect(actualAlignment, const Alignment(-1.0, 0.0));

    controller.value = 0.5;
    await tester.pump();
    actualAlignment = actualPositionedBox.alignment;
    expect(actualAlignment, const Alignment(0.0, 0.5));
  });

  testWidgets('AlignTransition keeps width and height factors', (WidgetTester tester) async {
177 178
    final AnimationController controller = AnimationController(vsync: const TestVSync());
    final Animation<Alignment> alignmentTween = AlignmentTween(
179 180 181
      begin: const Alignment(-1.0, 0.0),
      end: const Alignment(1.0, 1.0),
    ).animate(controller);
182
    final Widget widget = AlignTransition(
183 184 185 186 187 188 189 190 191 192 193 194 195
      alignment: alignmentTween,
      child: const Text('Ready', textDirection: TextDirection.ltr),
      widthFactor: 0.3,
      heightFactor: 0.4,
    );

    await tester.pumpWidget(widget);

    final Align actualAlign = tester.widget(find.byType(Align));

    expect(actualAlign.widthFactor, 0.3);
    expect(actualAlign.heightFactor, 0.4);
  });
196 197

  testWidgets('SizeTransition clamps negative size factors - vertical axis', (WidgetTester tester) async {
198 199
    final AnimationController controller = AnimationController(vsync: const TestVSync());
    final Animation<double> animation = Tween<double>(begin: -1.0, end: 1.0).animate(controller);
200

201
    final Widget widget =  Directionality(
202
        textDirection: TextDirection.ltr,
203
        child: SizeTransition(
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
          axis: Axis.vertical,
          sizeFactor: animation,
          child: const Text('Ready'),
        ),
      );

    await tester.pumpWidget(widget);

    final RenderPositionedBox actualPositionedBox = tester.renderObject(find.byType(Align));
    expect(actualPositionedBox.heightFactor, 0.0);

    controller.value = 0.0;
    await tester.pump();
    expect(actualPositionedBox.heightFactor, 0.0);

    controller.value = 0.75;
    await tester.pump();
    expect(actualPositionedBox.heightFactor, 0.5);

    controller.value = 1.0;
    await tester.pump();
    expect(actualPositionedBox.heightFactor, 1.0);
  });

  testWidgets('SizeTransition clamps negative size factors - horizontal axis', (WidgetTester tester) async {
229 230
    final AnimationController controller = AnimationController(vsync: const TestVSync());
    final Animation<double> animation = Tween<double>(begin: -1.0, end: 1.0).animate(controller);
231

232
    final Widget widget =  Directionality(
233
        textDirection: TextDirection.ltr,
234
        child: SizeTransition(
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
          axis: Axis.horizontal,
          sizeFactor: animation,
          child: const Text('Ready'),
        ),
      );

    await tester.pumpWidget(widget);

    final RenderPositionedBox actualPositionedBox = tester.renderObject(find.byType(Align));
    expect(actualPositionedBox.widthFactor, 0.0);

    controller.value = 0.0;
    await tester.pump();
    expect(actualPositionedBox.widthFactor, 0.0);

    controller.value = 0.75;
    await tester.pump();
    expect(actualPositionedBox.widthFactor, 0.5);

    controller.value = 1.0;
    await tester.pump();
    expect(actualPositionedBox.widthFactor, 1.0);
  });
258 259

  testWidgets('RotationTransition animates', (WidgetTester tester) async {
260 261
    final AnimationController controller = AnimationController(vsync: const TestVSync());
    final Widget widget = RotationTransition(
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
      alignment: Alignment.topRight,
      turns: controller,
      child: const Text('Rotation', textDirection: TextDirection.ltr),
    );

    await tester.pumpWidget(widget);
    Transform actualRotatedBox = tester.widget(find.byType(Transform));
    Matrix4 actualTurns = actualRotatedBox.transform;
    expect(actualTurns, equals(Matrix4.rotationZ(0.0)));

    controller.value = 0.5;
    await tester.pump();
    actualRotatedBox = tester.widget(find.byType(Transform));
    actualTurns = actualRotatedBox.transform;
    expect(actualTurns, Matrix4.rotationZ(math.pi));

    controller.value = 0.75;
    await tester.pump();
    actualRotatedBox = tester.widget(find.byType(Transform));
    actualTurns = actualRotatedBox.transform;
    expect(actualTurns, Matrix4.rotationZ(math.pi * 1.5));
  });

285
  testWidgets('RotationTransition maintains chosen alignment during animation', (WidgetTester tester) async {
286 287
    final AnimationController controller = AnimationController(vsync: const TestVSync());
    final Widget widget = RotationTransition(
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
      alignment: Alignment.topRight,
      turns: controller,
      child: const Text('Rotation', textDirection: TextDirection.ltr),
    );

    await tester.pumpWidget(widget);
    RotationTransition actualRotatedBox =
        tester.widget(find.byType(RotationTransition));
    Alignment actualAlignment = actualRotatedBox.alignment;
    expect(actualAlignment, const Alignment(1.0, -1.0));

    controller.value = 0.5;
    await tester.pump();
    actualRotatedBox = tester.widget(find.byType(RotationTransition));
    actualAlignment = actualRotatedBox.alignment;
    expect(actualAlignment, const Alignment(1.0, -1.0));
  });
305
}