tests to assert futures complete as expected (#5947)
This commit is contained in:
parent
74f50bfbe6
commit
8a186f3bbd
@ -154,6 +154,8 @@ class AnimationController extends Animation<double>
|
||||
AnimationStatus _status;
|
||||
|
||||
/// Starts running this animation forwards (towards the end).
|
||||
///
|
||||
/// Returns a [Future] that completes when the animation is complete.
|
||||
Future<Null> forward({ double from }) {
|
||||
_direction = _AnimationDirection.forward;
|
||||
if (from != null)
|
||||
@ -162,6 +164,8 @@ class AnimationController extends Animation<double>
|
||||
}
|
||||
|
||||
/// Starts running this animation in reverse (towards the beginning).
|
||||
///
|
||||
/// Returns a [Future] that completes when the animation is complete.
|
||||
Future<Null> reverse({ double from }) {
|
||||
_direction = _AnimationDirection.reverse;
|
||||
if (from != null)
|
||||
@ -170,6 +174,8 @@ class AnimationController extends Animation<double>
|
||||
}
|
||||
|
||||
/// Drives the animation from its current value to target.
|
||||
///
|
||||
/// Returns a [Future] that completes when the animation is complete.
|
||||
Future<Null> animateTo(double target, { Duration duration, Curve curve: Curves.linear }) {
|
||||
Duration simulationDuration = duration;
|
||||
if (simulationDuration == null) {
|
||||
|
@ -472,6 +472,8 @@ class ScrollableState<T extends Scrollable> extends State<T> {
|
||||
/// This function does not accept a zero duration. To jump-scroll to
|
||||
/// the new offset, do not provide a duration, rather than providing
|
||||
/// a zero duration.
|
||||
///
|
||||
/// The returned [Future] completes when the scrolling animation is complete.
|
||||
Future<Null> scrollTo(double newScrollOffset, {
|
||||
Duration duration,
|
||||
Curve curve: Curves.ease,
|
||||
@ -550,6 +552,8 @@ class ScrollableState<T extends Scrollable> extends State<T> {
|
||||
/// Calling this function starts a physics-based animation of the scroll
|
||||
/// offset with the given value as the initial velocity. The physics
|
||||
/// simulation is determined by the scroll behavior.
|
||||
///
|
||||
/// The returned [Future] completes when the scrolling animation is complete.
|
||||
Future<Null> fling(double scrollVelocity) {
|
||||
if (scrollVelocity.abs() > kPixelScrollTolerance.velocity)
|
||||
return _startToEndAnimation(scrollVelocity);
|
||||
|
@ -9,7 +9,6 @@ import 'package:flutter/widgets.dart';
|
||||
void main() {
|
||||
testWidgets('Verify that a tap dismisses a modal BottomSheet', (WidgetTester tester) async {
|
||||
BuildContext savedContext;
|
||||
bool showBottomSheetThenCalled = false;
|
||||
|
||||
await tester.pumpWidget(new MaterialApp(
|
||||
home: new Builder(
|
||||
@ -23,6 +22,7 @@ void main() {
|
||||
await tester.pump();
|
||||
expect(find.text('BottomSheet'), findsNothing);
|
||||
|
||||
bool showBottomSheetThenCalled = false;
|
||||
showModalBottomSheet/*<Null>*/(
|
||||
context: savedContext,
|
||||
builder: (BuildContext context) => new Text('BottomSheet')
|
||||
@ -44,14 +44,23 @@ void main() {
|
||||
await tester.pump(new Duration(seconds: 1)); // frame after the animation (sheet has been removed)
|
||||
expect(find.text('BottomSheet'), findsNothing);
|
||||
|
||||
showModalBottomSheet/*<Null>*/(context: savedContext, builder: (BuildContext context) => new Text('BottomSheet'));
|
||||
showBottomSheetThenCalled = false;
|
||||
showModalBottomSheet/*<Null>*/(
|
||||
context: savedContext,
|
||||
builder: (BuildContext context) => new Text('BottomSheet'),
|
||||
).then((Null result) {
|
||||
expectSync(result, isNull);
|
||||
showBottomSheetThenCalled = true;
|
||||
});
|
||||
await tester.pump(); // bottom sheet show animation starts
|
||||
await tester.pump(new Duration(seconds: 1)); // animation done
|
||||
expect(find.text('BottomSheet'), findsOneWidget);
|
||||
expect(showBottomSheetThenCalled, isFalse);
|
||||
|
||||
// Tap above the the bottom sheet to dismiss it
|
||||
await tester.tapAt(new Point(20.0, 20.0));
|
||||
await tester.pump(); // bottom sheet dismiss animation starts
|
||||
expect(showBottomSheetThenCalled, isTrue);
|
||||
await tester.pump(new Duration(seconds: 1)); // animation done
|
||||
await tester.pump(new Duration(seconds: 1)); // rebuild frame
|
||||
expect(find.text('BottomSheet'), findsNothing);
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
@ -53,22 +55,31 @@ void main() {
|
||||
)
|
||||
); // t=0
|
||||
recordMetrics();
|
||||
controller.forward();
|
||||
Completer<Null> completer = new Completer<Null>();
|
||||
controller.forward().whenComplete(completer.complete);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pump(); // t=0 again
|
||||
expect(completer.isCompleted, isFalse);
|
||||
recordMetrics();
|
||||
await tester.pump(const Duration(seconds: 1)); // t=1
|
||||
expect(completer.isCompleted, isFalse);
|
||||
recordMetrics();
|
||||
await tester.pump(const Duration(seconds: 1)); // t=2
|
||||
expect(completer.isCompleted, isFalse);
|
||||
recordMetrics();
|
||||
await tester.pump(const Duration(seconds: 3)); // t=5
|
||||
expect(completer.isCompleted, isFalse);
|
||||
recordMetrics();
|
||||
await tester.pump(const Duration(seconds: 5)); // t=10
|
||||
expect(completer.isCompleted, isFalse);
|
||||
recordMetrics();
|
||||
|
||||
expect(sizes, equals(<Size>[const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0)]));
|
||||
expect(positions, equals(<Offset>[const Offset(10.0, 10.0), const Offset(10.0, 10.0), const Offset(17.0, 17.0), const Offset(24.0, 24.0), const Offset(45.0, 45.0), const Offset(80.0, 80.0)]));
|
||||
|
||||
controller.stop();
|
||||
await tester.pump();
|
||||
expect(completer.isCompleted, isTrue);
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -57,8 +59,11 @@ Future<Null> performTest(WidgetTester tester, bool maintainState) async {
|
||||
expect(find.text('10'), findsNothing);
|
||||
expect(find.text('100'), findsNothing);
|
||||
|
||||
tester.state/*<ScrollableState>*/(find.byType(Scrollable)).scrollTo(1000.0);
|
||||
Completer<Null> completer = new Completer<Null>();
|
||||
tester.state/*<ScrollableState>*/(find.byType(Scrollable)).scrollTo(1000.0).whenComplete(completer.complete);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pump(new Duration(seconds: 1));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
|
||||
// we're 600 pixels high, each item is 100 pixels high, scroll position is
|
||||
// 1000, so we should have exactly 6 items, 10..15.
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@ -22,6 +24,14 @@ Widget _buildScroller({Key key, List<String> log}) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
GlobalKey<ScrollableState<Scrollable>> scrollKey;
|
||||
|
||||
Completer<Null> scrollTo(double newScrollOffset, { Duration duration }) {
|
||||
Completer<Null> completer = new Completer<Null>();
|
||||
scrollKey.currentState.scrollTo(newScrollOffset, duration: duration).whenComplete(completer.complete);
|
||||
return completer;
|
||||
}
|
||||
|
||||
testWidgets('Scroll event drag', (WidgetTester tester) async {
|
||||
List<String> log = <String>[];
|
||||
await tester.pumpWidget(_buildScroller(log: log));
|
||||
@ -42,12 +52,13 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('Scroll scrollTo animation', (WidgetTester tester) async {
|
||||
GlobalKey<ScrollableState<Scrollable>> scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
List<String> log = <String>[];
|
||||
await tester.pumpWidget(_buildScroller(key: scrollKey, log: log));
|
||||
|
||||
expect(log, equals(<String>[]));
|
||||
scrollKey.currentState.scrollTo(100.0, duration: const Duration(seconds: 1));
|
||||
Completer<Null> completer = scrollTo(100.0, duration: const Duration(seconds: 1));
|
||||
expect(completer.isCompleted, isFalse);
|
||||
expect(log, equals(<String>['scrollstart']));
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(log, equals(<String>['scrollstart']));
|
||||
@ -55,60 +66,74 @@ void main() {
|
||||
expect(log, equals(<String>['scrollstart', 'scroll']));
|
||||
await tester.pump(const Duration(milliseconds: 1500));
|
||||
expect(log, equals(<String>['scrollstart', 'scroll', 'scroll', 'scrollend']));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('Scroll scrollTo no animation', (WidgetTester tester) async {
|
||||
GlobalKey<ScrollableState<Scrollable>> scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
List<String> log = <String>[];
|
||||
await tester.pumpWidget(_buildScroller(key: scrollKey, log: log));
|
||||
|
||||
expect(log, equals(<String>[]));
|
||||
scrollKey.currentState.scrollTo(100.0);
|
||||
Completer<Null> completer = scrollTo(100.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
expect(log, equals(<String>['scrollstart', 'scroll', 'scrollend']));
|
||||
await tester.pump();
|
||||
expect(completer.isCompleted, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('Scroll during animation', (WidgetTester tester) async {
|
||||
GlobalKey<ScrollableState<Scrollable>> scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
List<String> log = <String>[];
|
||||
await tester.pumpWidget(_buildScroller(key: scrollKey, log: log));
|
||||
|
||||
expect(log, equals(<String>[]));
|
||||
scrollKey.currentState.scrollTo(100.0, duration: const Duration(seconds: 1));
|
||||
Completer<Null> completer = scrollTo(100.0, duration: const Duration(seconds: 1));
|
||||
expect(completer.isCompleted, isFalse);
|
||||
expect(log, equals(<String>['scrollstart']));
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(log, equals(<String>['scrollstart']));
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(log, equals(<String>['scrollstart', 'scroll']));
|
||||
scrollKey.currentState.scrollTo(100.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
|
||||
completer = scrollTo(100.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
expect(log, equals(<String>['scrollstart', 'scroll', 'scroll']));
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(log, equals(<String>['scrollstart', 'scroll', 'scroll', 'scrollend']));
|
||||
await tester.pump(const Duration(milliseconds: 1500));
|
||||
expect(log, equals(<String>['scrollstart', 'scroll', 'scroll', 'scrollend']));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('Scroll during animation', (WidgetTester tester) async {
|
||||
GlobalKey<ScrollableState<Scrollable>> scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
List<String> log = <String>[];
|
||||
await tester.pumpWidget(_buildScroller(key: scrollKey, log: log));
|
||||
|
||||
expect(log, equals(<String>[]));
|
||||
scrollKey.currentState.scrollTo(100.0, duration: const Duration(seconds: 1));
|
||||
Completer<Null> completer = scrollTo(100.0, duration: const Duration(seconds: 1));
|
||||
expect(completer.isCompleted, isFalse);
|
||||
expect(log, equals(<String>['scrollstart']));
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(log, equals(<String>['scrollstart']));
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(log, equals(<String>['scrollstart', 'scroll']));
|
||||
scrollKey.currentState.scrollTo(100.0, duration: const Duration(seconds: 1));
|
||||
expect(completer.isCompleted, isFalse);
|
||||
|
||||
completer = scrollTo(100.0, duration: const Duration(seconds: 1));
|
||||
expect(completer.isCompleted, isFalse);
|
||||
expect(log, equals(<String>['scrollstart', 'scroll']));
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(log, equals(<String>['scrollstart', 'scroll']));
|
||||
await tester.pump(const Duration(milliseconds: 1500));
|
||||
expect(log, equals(<String>['scrollstart', 'scroll', 'scroll', 'scrollend']));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('fling, fling generates two start/end pairs', (WidgetTester tester) async {
|
||||
GlobalKey<ScrollableState<Scrollable>> scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
List<String> log = <String>[];
|
||||
await tester.pumpWidget(_buildScroller(key: scrollKey, log: log));
|
||||
|
||||
@ -127,7 +152,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('fling up ends', (WidgetTester tester) async {
|
||||
GlobalKey<ScrollableState<Scrollable>> scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
scrollKey = new GlobalKey<ScrollableState<Scrollable>>();
|
||||
List<String> log = <String>[];
|
||||
await tester.pumpWidget(_buildScroller(key: scrollKey, log: log));
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@ -85,6 +87,11 @@ void main() {
|
||||
),
|
||||
right: new Text('Not Today')
|
||||
);
|
||||
Completer<Null> scrollTo(double newScrollOffset) {
|
||||
Completer<Null> completer = new Completer<Null>();
|
||||
scrollableKey.currentState.scrollTo(newScrollOffset).whenComplete(completer.complete);
|
||||
return completer;
|
||||
}
|
||||
|
||||
await tester.pumpWidget(testWidget);
|
||||
|
||||
@ -92,12 +99,14 @@ void main() {
|
||||
|
||||
callbackTracker.clear();
|
||||
|
||||
scrollableKey.currentState.scrollTo(400.0);
|
||||
Completer<Null> completer = scrollTo(400.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
// now only 3 should fit, numbered 2-4.
|
||||
|
||||
await tester.pumpWidget(testWidget);
|
||||
|
||||
expect(callbackTracker, equals(<int>[2, 3, 4]));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
|
||||
callbackTracker.clear();
|
||||
});
|
||||
@ -134,6 +143,11 @@ void main() {
|
||||
),
|
||||
right: new Text('Not Today')
|
||||
);
|
||||
Completer<Null> scrollTo(double newScrollOffset) {
|
||||
Completer<Null> completer = new Completer<Null>();
|
||||
scrollableKey.currentState.scrollTo(newScrollOffset).whenComplete(completer.complete);
|
||||
return completer;
|
||||
}
|
||||
|
||||
await tester.pumpWidget(testWidget);
|
||||
|
||||
@ -141,12 +155,14 @@ void main() {
|
||||
|
||||
callbackTracker.clear();
|
||||
|
||||
scrollableKey.currentState.scrollTo(400.0);
|
||||
Completer<Null> completer = scrollTo(400.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
// now only 4 should fit, numbered 2-5.
|
||||
|
||||
await tester.pumpWidget(testWidget);
|
||||
|
||||
expect(callbackTracker, equals(<int>[2, 3, 4, 5]));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
|
||||
callbackTracker.clear();
|
||||
});
|
||||
@ -174,24 +190,35 @@ void main() {
|
||||
itemExtent: 300.0,
|
||||
itemCount: 10
|
||||
);
|
||||
Completer<Null> scrollTo(double newScrollOffset) {
|
||||
Completer<Null> completer = new Completer<Null>();
|
||||
scrollableKey.currentState.scrollTo(newScrollOffset).whenComplete(completer.complete);
|
||||
return completer;
|
||||
}
|
||||
|
||||
await tester.pumpWidget(testWidget);
|
||||
expect(callbackTracker, equals(<int>[0, 1]));
|
||||
callbackTracker.clear();
|
||||
|
||||
scrollableKey.currentState.scrollTo(150.0);
|
||||
Completer<Null> completer = scrollTo(150.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pumpWidget(testWidget);
|
||||
expect(callbackTracker, equals(<int>[0, 1, 2]));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
callbackTracker.clear();
|
||||
|
||||
scrollableKey.currentState.scrollTo(600.0);
|
||||
completer = scrollTo(600.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pumpWidget(testWidget);
|
||||
expect(callbackTracker, equals(<int>[2, 3]));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
callbackTracker.clear();
|
||||
|
||||
scrollableKey.currentState.scrollTo(750.0);
|
||||
completer = scrollTo(750.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pumpWidget(testWidget);
|
||||
expect(callbackTracker, equals(<int>[2, 3, 4]));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
callbackTracker.clear();
|
||||
});
|
||||
|
||||
|
@ -46,8 +46,10 @@ set scrollOffset(double value) {
|
||||
scrollableState.scrollTo(value);
|
||||
}
|
||||
|
||||
Future<Null> fling(double velocity) {
|
||||
return scrollableState.fling(velocity);
|
||||
Completer<Null> fling(double velocity) {
|
||||
Completer<Null> completer = new Completer<Null>();
|
||||
scrollableState.fling(velocity).whenComplete(completer.complete);
|
||||
return completer;
|
||||
}
|
||||
|
||||
void main() {
|
||||
@ -60,49 +62,55 @@ void main() {
|
||||
|
||||
Duration dt = const Duration(seconds: 2);
|
||||
|
||||
fling(1000.0);
|
||||
Completer<Null> completer = fling(1000.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pump(); // Start the scheduler at 0.0
|
||||
await tester.pump(dt);
|
||||
expect(scrollOffset, closeTo(200.0, 1.0));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
|
||||
scrollOffset = 0.0;
|
||||
await tester.pump();
|
||||
expect(scrollOffset, 0.0);
|
||||
|
||||
fling(2000.0);
|
||||
completer = fling(2000.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pump();
|
||||
await tester.pump(dt);
|
||||
expect(scrollOffset, closeTo(400.0, 1.0));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
|
||||
scrollOffset = 400.0;
|
||||
await tester.pump();
|
||||
expect(scrollOffset, 400.0);
|
||||
|
||||
fling(-800.0);
|
||||
completer = fling(-800.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pump();
|
||||
await tester.pump(dt);
|
||||
expect(scrollOffset, closeTo(0.0, 1.0));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
|
||||
scrollOffset = 800.0;
|
||||
await tester.pump();
|
||||
expect(scrollOffset, 800.0);
|
||||
|
||||
fling(-2000.0);
|
||||
completer = fling(-2000.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pump();
|
||||
await tester.pump(dt);
|
||||
expect(scrollOffset, closeTo(200.0, 1.0));
|
||||
expect(completer.isCompleted, isTrue);
|
||||
|
||||
scrollOffset = 800.0;
|
||||
await tester.pump();
|
||||
expect(scrollOffset, 800.0);
|
||||
|
||||
bool completed = false;
|
||||
fling(-2000.0).then((_) {
|
||||
completed = true;
|
||||
expectSync(scrollOffset, closeTo(200.0, 1.0));
|
||||
});
|
||||
completer = fling(-2000.0);
|
||||
expect(completer.isCompleted, isFalse);
|
||||
await tester.pump();
|
||||
await tester.pump(dt);
|
||||
expect(completed, true);
|
||||
expect(completer.isCompleted, isTrue);
|
||||
expectSync(scrollOffset, closeTo(200.0, 1.0));
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user