tween_test.dart 7.77 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/widgets.dart';
6
import 'package:flutter_test/flutter_test.dart';
7

8 9
const String kApiDocsLink = 'See "Types with special considerations" at https://api.flutter.dev/flutter/animation/Tween-class.html for more information.';

10
void main() {
11 12 13 14 15 16
  test('throws flutter error when tweening types that do not fully satisfy tween requirements - Object', () {
    final Tween<Object> objectTween = Tween<Object>(
      begin: Object(),
      end: Object(),
    );

17 18 19 20 21 22 23 24 25 26 27 28
    expect(
      () => objectTween.transform(0.1),
      throwsA(isA<FlutterError>().having(
        (FlutterError error) => error.diagnostics.map((DiagnosticsNode node) => node.toString()),
        'diagnostics',
        <String>[
          'Cannot lerp between "Instance of \'Object\'" and "Instance of \'Object\'".',
          'The type Object might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink',
          'There may be a dedicated "ObjectTween" for this type, or you may need to create one.',
        ],
      )),
    );
29 30 31 32 33 34 35 36
  });

  test('throws flutter error when tweening types that do not fully satisfy tween requirements - Color', () {
    final Tween<Color> colorTween = Tween<Color>(
      begin: const Color(0xFF000000),
      end: const Color(0xFFFFFFFF),
    );

37 38 39 40 41 42 43 44 45 46 47 48
    expect(
      () => colorTween.transform(0.1),
      throwsA(isA<FlutterError>().having(
        (FlutterError error) => error.diagnostics.map((DiagnosticsNode node) => node.toString()),
        'diagnostics',
        <String>[
          'Cannot lerp between "Color(0xff000000)" and "Color(0xffffffff)".',
          'The type Color might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink',
          'To lerp colors, consider ColorTween instead.',
        ],
      )),
    );
49 50 51 52 53
  });

  test('throws flutter error when tweening types that do not fully satisfy tween requirements - Rect', () {
    final Tween<Rect> rectTween = Tween<Rect>(
      begin: const Rect.fromLTWH(0, 0, 10, 10),
54
      end: const Rect.fromLTWH(2, 2, 2, 2),
55 56
    );

57 58 59 60 61 62 63 64 65 66 67 68
    expect(
      () => rectTween.transform(0.1),
      throwsA(isA<FlutterError>().having(
        (FlutterError error) => error.diagnostics.map((DiagnosticsNode node) => node.toString()),
        'diagnostics',
        <String>[
          'Cannot lerp between "Rect.fromLTRB(0.0, 0.0, 10.0, 10.0)" and "Rect.fromLTRB(2.0, 2.0, 4.0, 4.0)".',
          'The type Rect might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink',
          'To lerp rects, consider RectTween instead.',
        ],
      )),
    );
69 70 71 72 73 74 75 76
  });

  test('throws flutter error when tweening types that do not fully satisfy tween requirements - int', () {
    final Tween<int> colorTween = Tween<int>(
      begin: 0,
      end: 1,
    );

77 78 79 80 81 82 83 84 85 86 87 88
    expect(
      () => colorTween.transform(0.1),
      throwsA(isA<FlutterError>().having(
        (FlutterError error) => error.diagnostics.map((DiagnosticsNode node) => node.toString()),
        'diagnostics',
        <String>[
          'Cannot lerp between "0" and "1".',
          'The type int returned a double after multiplication with a double value. $kApiDocsLink',
          'To lerp int values, consider IntTween or StepTween instead.',
        ],
      )),
    );
89 90
  });

91
  test('Can chain tweens', () {
92
    final Tween<double> tween = Tween<double>(begin: 0.30, end: 0.50);
93
    expect(tween, hasOneLineDescription);
94 95
    final Animatable<double> chain = tween.chain(Tween<double>(begin: 0.50, end: 1.0));
    final AnimationController controller = AnimationController(
96 97
      vsync: const TestVSync(),
    );
98 99 100 101
    expect(chain.evaluate(controller), 0.40);
    expect(chain, hasOneLineDescription);
  });

102
  test('Can animate tweens', () {
103 104
    final Tween<double> tween = Tween<double>(begin: 0.30, end: 0.50);
    final AnimationController controller = AnimationController(
105 106
      vsync: const TestVSync(),
    );
107
    final Animation<double> animation = tween.animate(controller);
108 109 110 111 112 113
    controller.value = 0.50;
    expect(animation.value, 0.40);
    expect(animation, hasOneLineDescription);
    expect(animation.toStringDetails(), hasOneLineDescription);
  });

114 115 116 117 118 119 120 121 122 123 124 125
  test('Can drive tweens', () {
    final Tween<double> tween = Tween<double>(begin: 0.30, end: 0.50);
    final AnimationController controller = AnimationController(
      vsync: const TestVSync(),
    );
    final Animation<double> animation = controller.drive(tween);
    controller.value = 0.50;
    expect(animation.value, 0.40);
    expect(animation, hasOneLineDescription);
    expect(animation.toStringDetails(), hasOneLineDescription);
  });

126 127
  test('BorderTween nullable test', () {
    BorderTween tween = BorderTween();
128 129
    expect(tween.lerp(0.0), null);
    expect(tween.lerp(1.0), null);
130

131 132 133 134
    tween = BorderTween(end: const Border(top: BorderSide()));
    expect(tween.lerp(0.0), const Border());
    expect(tween.lerp(0.5), const Border(top: BorderSide(width: 0.5)));
    expect(tween.lerp(1.0), const Border(top: BorderSide()));
135 136
  });

137
  test('SizeTween', () {
138
    final SizeTween tween = SizeTween(begin: Size.zero, end: const Size(20.0, 30.0));
139
    expect(tween.lerp(0.5), equals(const Size(10.0, 15.0)));
140 141 142 143
    expect(tween, hasOneLineDescription);
  });

  test('IntTween', () {
144
    final IntTween tween = IntTween(begin: 5, end: 9);
145 146 147
    expect(tween.lerp(0.5), 7);
    expect(tween.lerp(0.7), 8);
  });
148 149

  test('RectTween', () {
Dan Field's avatar
Dan Field committed
150 151
    const Rect a = Rect.fromLTWH(5.0, 3.0, 7.0, 11.0);
    const Rect b = Rect.fromLTWH(8.0, 12.0, 14.0, 18.0);
152
    final RectTween tween = RectTween(begin: a, end: b);
153 154 155
    expect(tween.lerp(0.5), equals(Rect.lerp(a, b, 0.5)));
    expect(tween, hasOneLineDescription);
  });
156 157

  test('Matrix4Tween', () {
158
    final Matrix4 a = Matrix4.identity();
159
    final Matrix4 b = a.clone()..translate(6.0, -8.0)..scale(0.5, 1.0, 5.0);
160
    final Matrix4Tween tween = Matrix4Tween(begin: a, end: b);
161 162 163 164
    expect(tween.lerp(0.0), equals(a));
    expect(tween.lerp(1.0), equals(b));
    expect(
      tween.lerp(0.5),
165
      equals(a.clone()..translate(3.0, -4.0)..scale(0.75, 1.0, 3.0)),
166 167
    );
    final Matrix4 c = a.clone()..rotateZ(1.0);
168
    final Matrix4Tween rotationTween = Matrix4Tween(begin: a, end: c);
169 170 171
    expect(rotationTween.lerp(0.0), equals(a));
    expect(rotationTween.lerp(1.0), equals(c));
    expect(
172
      rotationTween.lerp(0.5).absoluteError(a.clone()..rotateZ(0.5)),
173
      moreOrLessEquals(0.0),
174
    );
175
  });
176 177

  test('ConstantTween', () {
178
    final ConstantTween<double> tween = ConstantTween<double>(100.0);
179 180 181 182 183 184
    expect(tween.begin, 100.0);
    expect(tween.end, 100.0);
    expect(tween.lerp(0.0), 100.0);
    expect(tween.lerp(0.5), 100.0);
    expect(tween.lerp(1.0), 100.0);
  });
185 186 187 188 189 190 191 192 193 194

  test('ReverseTween', () {
    final ReverseTween<int> tween = ReverseTween<int>(IntTween(begin: 5, end: 9));
    expect(tween.lerp(0.5), 7);
    expect(tween.lerp(0.7), 6);
  });

  test('ColorTween', () {
    final ColorTween tween = ColorTween(
      begin: const Color(0xff000000),
195
      end: const Color(0xffffffff),
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
    );
    expect(tween.lerp(0.0), const Color(0xff000000));
    expect(tween.lerp(0.5), const Color(0xff7f7f7f));
    expect(tween.lerp(0.7), const Color(0xffb2b2b2));
    expect(tween.lerp(1.0), const Color(0xffffffff));
  });

  test('StepTween', () {
    final StepTween tween = StepTween(begin: 5, end: 9);
    expect(tween.lerp(0.5), 7);
    expect(tween.lerp(0.7), 7);
  });

  test('CurveTween', () {
    final CurveTween tween = CurveTween(curve: Curves.easeIn);
    expect(tween.transform(0.0), 0.0);
    expect(tween.transform(0.5), 0.31640625);
    expect(tween.transform(1.0), 1.0);
  });
215 216

  test('BorderRadiusTween nullable test', () {
217
    final BorderRadiusTween tween = BorderRadiusTween();
218 219 220 221
    expect(tween.transform(0.0), null);
    expect(tween.transform(1.0), null);
    expect(tween.lerp(0.0), null);
  });
222
}