Commit 7791acd8 authored by Hans Muller's avatar Hans Muller

Merge pull request #303 from HansMuller/bottom_sheet_test

Add a unit test for persistent bottom sheets

ShowBottomSheet now clears its placeholder after the bottom sheet has been dismissed.

Added support for generating fling gestures to WidgetTester.
parents 97b1d21b b4c39703
......@@ -216,5 +216,7 @@ Future showBottomSheet({ BuildContext context, GlobalKey<PlaceholderState> place
_BottomSheetRoute route = new _BottomSheetRoute(child: child, completer: completer);
placeholderKey.currentState.child = new _PersistentBottomSheet(route: route);
Navigator.of(context).pushEphemeral(route);
return completer.future;
return completer.future.then((_) {
placeholderKey.currentState.child = null;
});
}
......@@ -11,7 +11,7 @@ class TestPointer {
bool isDown = false;
ui.Point location;
PointerInputEvent down([ui.Point newLocation = ui.Point.origin ]) {
PointerInputEvent down([ui.Point newLocation = ui.Point.origin, double timeStamp = 0.0 ]) {
assert(!isDown);
isDown = true;
location = newLocation;
......@@ -19,11 +19,12 @@ class TestPointer {
type: 'pointerdown',
pointer: pointer,
x: location.x,
y: location.y
y: location.y,
timeStamp: timeStamp
);
}
PointerInputEvent move([ui.Point newLocation = ui.Point.origin ]) {
PointerInputEvent move([ui.Point newLocation = ui.Point.origin, double timeStamp = 0.0]) {
assert(isDown);
ui.Offset delta = newLocation - location;
location = newLocation;
......@@ -33,29 +34,32 @@ class TestPointer {
x: newLocation.x,
y: newLocation.y,
dx: delta.dx,
dy: delta.dy
dy: delta.dy,
timeStamp: timeStamp
);
}
PointerInputEvent up() {
PointerInputEvent up([ double timeStamp = 0.0 ]) {
assert(isDown);
isDown = false;
return new PointerInputEvent(
type: 'pointerup',
pointer: pointer,
x: location.x,
y: location.y
y: location.y,
timeStamp: timeStamp
);
}
PointerInputEvent cancel() {
PointerInputEvent cancel([ double timeStamp = 0.0 ]) {
assert(isDown);
isDown = false;
return new PointerInputEvent(
type: 'pointercancel',
pointer: pointer,
x: location.x,
y: location.y
y: location.y,
timeStamp: timeStamp
);
}
......
......@@ -5,7 +5,7 @@ import 'package:test/test.dart';
import 'widget_tester.dart';
void main() {
test('Verify that a tap dismisses the BottomSheet', () {
test('Verify that a tap dismisses a modal BottomSheet', () {
testWidgets((WidgetTester tester) {
BuildContext context;
tester.pumpWidget(new MaterialApp(
......@@ -46,4 +46,43 @@ void main() {
});
});
test('Verify that a downwards fling dismisses a persistent BottomSheet', () {
testWidgets((WidgetTester tester) {
GlobalKey<PlaceholderState> _bottomSheetPlaceholderKey = new GlobalKey<PlaceholderState>();
BuildContext context;
tester.pumpWidget(new MaterialApp(
routes: <String, RouteBuilder>{
'/': (RouteArguments args) {
context = args.context;
return new Scaffold(
bottomSheet: new Placeholder(key: _bottomSheetPlaceholderKey),
body: new Center(child: new Text('body'))
);
}
}
));
tester.pump();
expect(tester.findText('BottomSheet'), isNull);
showBottomSheet(
context: context,
child: new Container(child: new Text('BottomSheet'), margin: new EdgeDims.all(40.0)),
placeholderKey: _bottomSheetPlaceholderKey
);
expect(_bottomSheetPlaceholderKey.currentState.child, isNotNull);
tester.pump(); // bottom sheet show animation starts
tester.pump(new Duration(seconds: 1)); // animation done
expect(tester.findText('BottomSheet'), isNotNull);
tester.fling(tester.findText('BottomSheet'), const Offset(0.0, 20.0), 1000.0);
tester.pump(); // bottom sheet dismiss animation starts
tester.pump(new Duration(seconds: 1)); // animation done
tester.pump(new Duration(seconds: 2)); // rebuild frame without the bottom sheet
expect(tester.findText('BottomSheet'), isNull);
expect(_bottomSheetPlaceholderKey.currentState.child, isNull);
});
});
}
......@@ -144,6 +144,27 @@ class WidgetTester {
_dispatchEvent(p.up(), result);
}
void fling(Element element, Offset offset, velocity, { int pointer: 1 }) {
flingFrom(getCenter(element), offset, velocity, pointer: pointer);
}
void flingFrom(Point startLocation, Offset offset, double velocity, { int pointer: 1 }) {
assert(offset.distance > 0.0);
assert(velocity != 0.0); // velocity is pixels/second
final TestPointer p = new TestPointer(pointer);
final HitTestResult result = _hitTest(startLocation);
final kMoveCount = 50; // Needs to be >= kHistorySize, see _LeastSquaresVelocityTrackerStrategy
final double timeStampDelta = 1000.0 * offset.distance / (kMoveCount * velocity);
double timeStamp = 0.0;
_dispatchEvent(p.down(startLocation, timeStamp), result);
for(int i = 0; i < kMoveCount; i++) {
final Point location = startLocation + Offset.lerp(Offset.zero, offset, i / kMoveCount);
_dispatchEvent(p.move(location, timeStamp), result);
timeStamp += timeStampDelta;
}
_dispatchEvent(p.up(timeStamp), result);
}
void scroll(Element element, Offset offset, { int pointer: 1 }) {
scrollAt(getCenter(element), offset, pointer: pointer);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment