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.
|
||||
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
|
||||
/// starting a drag in the middle of the widget.
|
||||
///
|
||||
@ -908,6 +936,22 @@ class LiveWidgetController extends WidgetController {
|
||||
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
|
||||
Future<List<Duration>> handlePointerEventRecord(List<PointerEventRecord> records) {
|
||||
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
|
||||
/// 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.
|
||||
@override
|
||||
Future<int> pumpAndSettle([
|
||||
Duration duration = const Duration(milliseconds: 100),
|
||||
EnginePhase phase = EnginePhase.sendSemanticsUpdate,
|
||||
Duration timeout = const Duration(minutes: 10),
|
||||
]) {
|
||||
assert(duration != null);
|
||||
assert(duration > Duration.zero);
|
||||
assert(timeout != null);
|
||||
assert(timeout > Duration.zero);
|
||||
assert(() {
|
||||
final WidgetsBinding binding = this.binding;
|
||||
if (binding is LiveTestWidgetsFlutterBinding &&
|
||||
@ -648,16 +622,14 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
int count = 0;
|
||||
return TestAsyncUtils.guard<void>(() async {
|
||||
final DateTime endTime = binding.clock.fromNowBy(timeout);
|
||||
return TestAsyncUtils.guard<int>(() async {
|
||||
int count = 0;
|
||||
do {
|
||||
if (binding.clock.now().isAfter(endTime))
|
||||
throw FlutterError('pumpAndSettle timed out');
|
||||
await binding.pump(duration, phase);
|
||||
count += 1;
|
||||
} while (binding.hasScheduledFrame);
|
||||
}).then<int>((_) => count);
|
||||
return count;
|
||||
});
|
||||
}
|
||||
|
||||
/// 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() {
|
||||
test('Test pump on LiveWidgetController', () async {
|
||||
runApp(MaterialApp(home: Center(child: CountButton())));
|
||||
@ -44,6 +77,16 @@ void main() {
|
||||
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 {
|
||||
final List<String> logs = <String>[];
|
||||
runApp(
|
||||
|
@ -465,21 +465,11 @@ void main() {
|
||||
|
||||
testWidgets('pumpAndSettle control test', (WidgetTester tester) async {
|
||||
final AnimationController controller = AnimationController(
|
||||
duration: const Duration(minutes: 525600),
|
||||
duration: const Duration(seconds: 1),
|
||||
vsync: const TestVSync(),
|
||||
);
|
||||
expect(await tester.pumpAndSettle(), 1);
|
||||
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
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user