mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
408 lines
13 KiB
Dart
408 lines
13 KiB
Dart
// Copyright 2014 The Flutter 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 'package:flutter/widgets.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
void main() {
|
|
testWidgets('Animates forward when built', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
int endCount = 0;
|
|
await tester.pumpWidget(
|
|
TweenAnimationBuilder<int>(
|
|
duration: const Duration(seconds: 1),
|
|
tween: IntTween(begin: 10, end: 110),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
onEnd: () {
|
|
endCount++;
|
|
},
|
|
),
|
|
);
|
|
expect(endCount, 0);
|
|
expect(values, <int>[10]);
|
|
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[10, 60]);
|
|
|
|
await tester.pump(const Duration(milliseconds: 501));
|
|
expect(endCount, 1);
|
|
expect(values, <int>[10, 60, 110]);
|
|
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(endCount, 1);
|
|
expect(values, <int>[10, 60, 110]);
|
|
});
|
|
|
|
testWidgets('No initial animation when begin=null', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
int endCount = 0;
|
|
await tester.pumpWidget(
|
|
TweenAnimationBuilder<int>(
|
|
duration: const Duration(seconds: 1),
|
|
tween: IntTween(end: 100),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
onEnd: () {
|
|
endCount++;
|
|
},
|
|
),
|
|
);
|
|
expect(endCount, 0);
|
|
expect(values, <int>[100]);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(endCount, 0);
|
|
expect(values, <int>[100]);
|
|
});
|
|
|
|
|
|
testWidgets('No initial animation when begin=end', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
int endCount = 0;
|
|
await tester.pumpWidget(
|
|
TweenAnimationBuilder<int>(
|
|
duration: const Duration(seconds: 1),
|
|
tween: IntTween(begin: 100, end: 100),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
onEnd: () {
|
|
endCount++;
|
|
},
|
|
),
|
|
);
|
|
expect(endCount, 0);
|
|
expect(values, <int>[100]);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(endCount, 0);
|
|
expect(values, <int>[100]);
|
|
});
|
|
|
|
testWidgets('Replace tween animates new tween', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
Widget buildWidget({required IntTween tween}) {
|
|
return TweenAnimationBuilder<int>(
|
|
duration: const Duration(seconds: 1),
|
|
tween: tween,
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
await tester.pumpWidget(buildWidget(tween: IntTween(begin: 0, end: 100)));
|
|
expect(values, <int>[0]);
|
|
await tester.pump(const Duration(seconds: 2)); // finish first animation.
|
|
expect(values, <int>[0, 100]);
|
|
|
|
await tester.pumpWidget(buildWidget(tween: IntTween(begin: 100, end: 200)));
|
|
expect(values, <int>[0, 100, 100]);
|
|
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 100, 100, 150]);
|
|
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 100, 100, 150, 200]);
|
|
});
|
|
|
|
testWidgets('Curve is respected', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
Widget buildWidget({required IntTween tween, required Curve curve}) {
|
|
return TweenAnimationBuilder<int>(
|
|
duration: const Duration(seconds: 1),
|
|
tween: tween,
|
|
curve: curve,
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
await tester.pumpWidget(buildWidget(tween: IntTween(begin: 0, end: 100), curve: Curves.easeInExpo));
|
|
expect(values, <int>[0]);
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values.last, lessThan(50));
|
|
expect(values.last, greaterThan(0));
|
|
|
|
await tester.pump(const Duration(seconds: 2)); // finish animation.
|
|
|
|
values.clear();
|
|
// Update curve (and tween to re-trigger animation).
|
|
await tester.pumpWidget(buildWidget(tween: IntTween(begin: 100, end: 200), curve: Curves.linear));
|
|
expect(values, <int>[100]);
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[100, 150]);
|
|
});
|
|
|
|
testWidgets('Duration is respected', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
Widget buildWidget({required IntTween tween, required Duration duration}) {
|
|
return TweenAnimationBuilder<int>(
|
|
tween: tween,
|
|
duration: duration,
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
await tester.pumpWidget(buildWidget(tween: IntTween(begin: 0, end: 100), duration: const Duration(seconds: 1)));
|
|
expect(values, <int>[0]);
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 50]);
|
|
|
|
await tester.pump(const Duration(seconds: 2)); // finish animation.
|
|
|
|
values.clear();
|
|
// Update duration (and tween to re-trigger animation).
|
|
await tester.pumpWidget(buildWidget(tween: IntTween(begin: 100, end: 200), duration: const Duration(seconds: 2)));
|
|
expect(values, <int>[100]);
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[100, 125]);
|
|
});
|
|
|
|
testWidgets('Child is integrated into tree', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: TweenAnimationBuilder<int>(
|
|
tween: IntTween(begin: 0, end: 100),
|
|
duration: const Duration(seconds: 1),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
return child!;
|
|
},
|
|
child: const Text('Hello World'),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(find.text('Hello World'), findsOneWidget);
|
|
});
|
|
|
|
group('Change tween gapless while', () {
|
|
testWidgets('running forward', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
Widget buildWidget({required IntTween tween}) {
|
|
return TweenAnimationBuilder<int>(
|
|
tween: tween,
|
|
duration: const Duration(seconds: 1),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: IntTween(begin: 0, end: 100),
|
|
));
|
|
expect(values, <int>[0]);
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 50]);
|
|
|
|
// Change tween
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: IntTween(begin: 200, end: 300),
|
|
));
|
|
expect(values, <int>[0, 50, 50]); // gapless: animation continues where it left off.
|
|
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 50, 50, 175]); // 175 = halfway between 50 and new target 300.
|
|
|
|
// Run animation to end
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(values, <int>[0, 50, 50, 175, 300]);
|
|
values.clear();
|
|
});
|
|
|
|
testWidgets('running forward and then reverse with same tween instance', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
Widget buildWidget({required IntTween tween}) {
|
|
return TweenAnimationBuilder<int>(
|
|
tween: tween,
|
|
duration: const Duration(seconds: 1),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
final IntTween tween1 = IntTween(begin: 0, end: 100);
|
|
final IntTween tween2 = IntTween(begin: 200, end: 300);
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: tween1,
|
|
));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: tween2,
|
|
));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(values, <int>[0, 50, 50, 175, 300]);
|
|
values.clear();
|
|
});
|
|
});
|
|
|
|
testWidgets('Changing tween while gapless tween change is in progress', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
Widget buildWidget({required IntTween tween}) {
|
|
return TweenAnimationBuilder<int>(
|
|
tween: tween,
|
|
duration: const Duration(seconds: 1),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
final IntTween tween1 = IntTween(begin: 0, end: 100);
|
|
final IntTween tween2 = IntTween(begin: 200, end: 300);
|
|
final IntTween tween3 = IntTween(begin: 400, end: 501);
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: tween1,
|
|
));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 50]);
|
|
values.clear();
|
|
|
|
// Change tween
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: tween2,
|
|
));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[50, 175]);
|
|
values.clear();
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: tween3,
|
|
));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[175, 338, 501]);
|
|
});
|
|
|
|
testWidgets('Changing curve while no animation is running does not trigger animation', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
Widget buildWidget({required Curve curve}) {
|
|
return TweenAnimationBuilder<int>(
|
|
tween: IntTween(begin: 0, end: 100),
|
|
curve: curve,
|
|
duration: const Duration(seconds: 1),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
curve: Curves.linear,
|
|
));
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(values, <int>[0, 100]);
|
|
values.clear();
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
curve: Curves.easeInExpo,
|
|
));
|
|
expect(values, <int>[100]);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(values, <int>[100]);
|
|
});
|
|
|
|
testWidgets('Setting same tween and direction does not trigger animation', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
Widget buildWidget({required IntTween tween}) {
|
|
return TweenAnimationBuilder<int>(
|
|
tween: tween,
|
|
duration: const Duration(seconds: 1),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: IntTween(begin: 0, end: 100),
|
|
));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 50, 100]);
|
|
values.clear();
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: IntTween(begin: 0, end: 100),
|
|
));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, everyElement(100));
|
|
});
|
|
|
|
testWidgets('Setting same tween and direction while gapless animation is in progress works', (WidgetTester tester) async {
|
|
final List<int> values = <int>[];
|
|
Widget buildWidget({required IntTween tween}) {
|
|
return TweenAnimationBuilder<int>(
|
|
tween: tween,
|
|
duration: const Duration(seconds: 1),
|
|
builder: (BuildContext context, int i, Widget? child) {
|
|
values.add(i);
|
|
return const Placeholder();
|
|
},
|
|
);
|
|
}
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: IntTween(begin: 0, end: 100),
|
|
));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 50]);
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: IntTween(begin: 200, end: 300),
|
|
));
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 50, 50, 175]);
|
|
|
|
await tester.pumpWidget(buildWidget(
|
|
tween: IntTween(begin: 200, end: 300),
|
|
));
|
|
expect(values, <int>[0, 50, 50, 175, 175]);
|
|
await tester.pump(const Duration(milliseconds: 500));
|
|
expect(values, <int>[0, 50, 50, 175, 175, 300]);
|
|
|
|
values.clear();
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(values, everyElement(300));
|
|
});
|
|
|
|
testWidgets('Works with nullable tweens', (WidgetTester tester) async {
|
|
final List<Size?> values = <Size?>[];
|
|
await tester.pumpWidget(
|
|
TweenAnimationBuilder<Size?>(
|
|
duration: const Duration(seconds: 1),
|
|
tween: SizeTween(end: const Size(10,10)),
|
|
builder: (BuildContext context, Size? s, Widget? child) {
|
|
values.add(s);
|
|
return const Placeholder();
|
|
},
|
|
),
|
|
);
|
|
expect(values, <Size>[const Size(10,10)]);
|
|
await tester.pump(const Duration(seconds: 2));
|
|
expect(values, <Size>[const Size(10,10)]);
|
|
});
|
|
}
|