promote WidgetTester pumpAndSettle (#62640)
This commit is contained in:
parent
e03980ec47
commit
a36b0ba4f6
@ -440,6 +440,34 @@ abstract class WidgetController {
|
|||||||
/// be appropriate to return in the implementation of this method.
|
/// be appropriate to return in the implementation of this method.
|
||||||
Future<void> pump([Duration duration]);
|
Future<void> pump([Duration duration]);
|
||||||
|
|
||||||
|
/// Repeatedly calls [pump] with the given `duration` until there are no
|
||||||
|
/// longer any frames scheduled. This will call [pump] at least once, even if
|
||||||
|
/// no frames are scheduled when the function is called, to flush any pending
|
||||||
|
/// microtasks which may themselves schedule a frame.
|
||||||
|
///
|
||||||
|
/// This essentially waits for all animations to have completed.
|
||||||
|
///
|
||||||
|
/// If it takes longer that the given `timeout` to settle, then the test will
|
||||||
|
/// fail (this method will throw an exception). In particular, this means that
|
||||||
|
/// if there is an infinite animation in progress (for example, if there is an
|
||||||
|
/// indeterminate progress indicator spinning), this method will throw.
|
||||||
|
///
|
||||||
|
/// The default timeout is ten minutes, which is longer than most reasonable
|
||||||
|
/// finite animations would last.
|
||||||
|
///
|
||||||
|
/// If the function returns, it returns the number of pumps that it performed.
|
||||||
|
///
|
||||||
|
/// In general, it is better practice to figure out exactly why each frame is
|
||||||
|
/// needed, and then to [pump] exactly as many frames as necessary. This will
|
||||||
|
/// help catch regressions where, for instance, an animation is being started
|
||||||
|
/// one frame later than it should.
|
||||||
|
///
|
||||||
|
/// Alternatively, one can check that the return value from this function
|
||||||
|
/// matches the expected number of pumps.
|
||||||
|
Future<int> pumpAndSettle([
|
||||||
|
Duration duration = const Duration(milliseconds: 100),
|
||||||
|
]);
|
||||||
|
|
||||||
/// Attempts to drag the given widget by the given offset, by
|
/// Attempts to drag the given widget by the given offset, by
|
||||||
/// starting a drag in the middle of the widget.
|
/// starting a drag in the middle of the widget.
|
||||||
///
|
///
|
||||||
@ -908,6 +936,22 @@ class LiveWidgetController extends WidgetController {
|
|||||||
await binding.endOfFrame;
|
await binding.endOfFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<int> pumpAndSettle([
|
||||||
|
Duration duration = const Duration(milliseconds: 100),
|
||||||
|
]) {
|
||||||
|
assert(duration != null);
|
||||||
|
assert(duration > Duration.zero);
|
||||||
|
return TestAsyncUtils.guard<int>(() async {
|
||||||
|
int count = 0;
|
||||||
|
do {
|
||||||
|
await pump(duration);
|
||||||
|
count += 1;
|
||||||
|
} while (binding.hasScheduledFrame);
|
||||||
|
return count;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<Duration>> handlePointerEventRecord(List<PointerEventRecord> records) {
|
Future<List<Duration>> handlePointerEventRecord(List<PointerEventRecord> records) {
|
||||||
assert(records != null);
|
assert(records != null);
|
||||||
|
@ -604,39 +604,13 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Repeatedly calls [pump] with the given `duration` until there are no
|
@override
|
||||||
/// longer any frames scheduled. This will call [pump] at least once, even if
|
|
||||||
/// no frames are scheduled when the function is called, to flush any pending
|
|
||||||
/// microtasks which may themselves schedule a frame.
|
|
||||||
///
|
|
||||||
/// This essentially waits for all animations to have completed.
|
|
||||||
///
|
|
||||||
/// If it takes longer that the given `timeout` to settle, then the test will
|
|
||||||
/// fail (this method will throw an exception). In particular, this means that
|
|
||||||
/// if there is an infinite animation in progress (for example, if there is an
|
|
||||||
/// indeterminate progress indicator spinning), this method will throw.
|
|
||||||
///
|
|
||||||
/// The default timeout is ten minutes, which is longer than most reasonable
|
|
||||||
/// finite animations would last.
|
|
||||||
///
|
|
||||||
/// If the function returns, it returns the number of pumps that it performed.
|
|
||||||
///
|
|
||||||
/// In general, it is better practice to figure out exactly why each frame is
|
|
||||||
/// needed, and then to [pump] exactly as many frames as necessary. This will
|
|
||||||
/// help catch regressions where, for instance, an animation is being started
|
|
||||||
/// one frame later than it should.
|
|
||||||
///
|
|
||||||
/// Alternatively, one can check that the return value from this function
|
|
||||||
/// matches the expected number of pumps.
|
|
||||||
Future<int> pumpAndSettle([
|
Future<int> pumpAndSettle([
|
||||||
Duration duration = const Duration(milliseconds: 100),
|
Duration duration = const Duration(milliseconds: 100),
|
||||||
EnginePhase phase = EnginePhase.sendSemanticsUpdate,
|
EnginePhase phase = EnginePhase.sendSemanticsUpdate,
|
||||||
Duration timeout = const Duration(minutes: 10),
|
|
||||||
]) {
|
]) {
|
||||||
assert(duration != null);
|
assert(duration != null);
|
||||||
assert(duration > Duration.zero);
|
assert(duration > Duration.zero);
|
||||||
assert(timeout != null);
|
|
||||||
assert(timeout > Duration.zero);
|
|
||||||
assert(() {
|
assert(() {
|
||||||
final WidgetsBinding binding = this.binding;
|
final WidgetsBinding binding = this.binding;
|
||||||
if (binding is LiveTestWidgetsFlutterBinding &&
|
if (binding is LiveTestWidgetsFlutterBinding &&
|
||||||
@ -648,16 +622,14 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
|
return TestAsyncUtils.guard<int>(() async {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
return TestAsyncUtils.guard<void>(() async {
|
|
||||||
final DateTime endTime = binding.clock.fromNowBy(timeout);
|
|
||||||
do {
|
do {
|
||||||
if (binding.clock.now().isAfter(endTime))
|
|
||||||
throw FlutterError('pumpAndSettle timed out');
|
|
||||||
await binding.pump(duration, phase);
|
await binding.pump(duration, phase);
|
||||||
count += 1;
|
count += 1;
|
||||||
} while (binding.hasScheduledFrame);
|
} while (binding.hasScheduledFrame);
|
||||||
}).then<int>((_) => count);
|
return count;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Repeatedly pump frames that render the `target` widget with a fixed time
|
/// Repeatedly pump frames that render the `target` widget with a fixed time
|
||||||
|
@ -29,6 +29,39 @@ class _CountButtonState extends State<CountButton> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AnimateSample extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_AnimateSampleState createState() => _AnimateSampleState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AnimateSampleState extends State<AnimateSample>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
vsync: this,
|
||||||
|
duration: const Duration(seconds: 1),
|
||||||
|
)..forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnimatedBuilder(
|
||||||
|
animation: _controller,
|
||||||
|
builder: (BuildContext context, _) => Text('Value: ${_controller.value}'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('Test pump on LiveWidgetController', () async {
|
test('Test pump on LiveWidgetController', () async {
|
||||||
runApp(MaterialApp(home: Center(child: CountButton())));
|
runApp(MaterialApp(home: Center(child: CountButton())));
|
||||||
@ -44,6 +77,16 @@ void main() {
|
|||||||
expect(find.text('Counter 1'), findsOneWidget);
|
expect(find.text('Counter 1'), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Test pumpAndSettle on LiveWidgetController', () async {
|
||||||
|
runApp(MaterialApp(home: Center(child: AnimateSample())));
|
||||||
|
await SchedulerBinding.instance.endOfFrame;
|
||||||
|
final WidgetController controller =
|
||||||
|
LiveWidgetController(WidgetsBinding.instance);
|
||||||
|
expect(find.text('Value: 1.0'), findsNothing);
|
||||||
|
await controller.pumpAndSettle();
|
||||||
|
expect(find.text('Value: 1.0'), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
test('Input event array on LiveWidgetController', () async {
|
test('Input event array on LiveWidgetController', () async {
|
||||||
final List<String> logs = <String>[];
|
final List<String> logs = <String>[];
|
||||||
runApp(
|
runApp(
|
||||||
|
@ -465,21 +465,11 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('pumpAndSettle control test', (WidgetTester tester) async {
|
testWidgets('pumpAndSettle control test', (WidgetTester tester) async {
|
||||||
final AnimationController controller = AnimationController(
|
final AnimationController controller = AnimationController(
|
||||||
duration: const Duration(minutes: 525600),
|
duration: const Duration(seconds: 1),
|
||||||
vsync: const TestVSync(),
|
vsync: const TestVSync(),
|
||||||
);
|
);
|
||||||
expect(await tester.pumpAndSettle(), 1);
|
expect(await tester.pumpAndSettle(), 1);
|
||||||
controller.forward();
|
controller.forward();
|
||||||
try {
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
expect(true, isFalse);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e, isFlutterError);
|
|
||||||
}
|
|
||||||
controller.stop();
|
|
||||||
expect(await tester.pumpAndSettle(), 1);
|
|
||||||
controller.duration = const Duration(seconds: 1);
|
|
||||||
controller.forward();
|
|
||||||
expect(await tester.pumpAndSettle(const Duration(milliseconds: 300)), 5); // 0, 300, 600, 900, 1200ms
|
expect(await tester.pumpAndSettle(const Duration(milliseconds: 300)), 5); // 0, 300, 600, 900, 1200ms
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user