blob: 10f11882afd0bd9df9e0b5131ed144c61a66670d [file] [log] [blame]
// Copyright 2018 The Chromium 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_test/flutter_test.dart';
import 'package:flutter/gestures.dart' show PointerDeviceKind;
import 'package:flutter/widgets.dart';
void main() {
int tapCount;
int singleTapUpCount;
int singleTapCancelCount;
int singleLongTapStartCount;
int doubleTapDownCount;
int forcePressStartCount;
int forcePressEndCount;
int dragStartCount;
int dragUpdateCount;
int dragEndCount;
const Offset forcePressOffset = Offset(400.0, 50.0);
void _handleTapDown(TapDownDetails details) { tapCount++; }
void _handleSingleTapUp(TapUpDetails details) { singleTapUpCount++; }
void _handleSingleTapCancel() { singleTapCancelCount++; }
void _handleSingleLongTapStart(LongPressStartDetails details) { singleLongTapStartCount++; }
void _handleDoubleTapDown(TapDownDetails details) { doubleTapDownCount++; }
void _handleForcePressStart(ForcePressDetails details) { forcePressStartCount++; }
void _handleForcePressEnd(ForcePressDetails details) { forcePressEndCount++; }
void _handleDragSelectionStart(DragStartDetails details) { dragStartCount++; }
void _handleDragSelectionUpdate(DragStartDetails _, DragUpdateDetails details) { dragUpdateCount++; }
void _handleDragSelectionEnd(DragEndDetails details) { dragEndCount++; }
setUp(() {
tapCount = 0;
singleTapUpCount = 0;
singleTapCancelCount = 0;
singleLongTapStartCount = 0;
doubleTapDownCount = 0;
forcePressStartCount = 0;
forcePressEndCount = 0;
dragStartCount = 0;
dragUpdateCount = 0;
dragEndCount = 0;
});
Future<void> pumpGestureDetector(WidgetTester tester) async {
await tester.pumpWidget(
TextSelectionGestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: _handleTapDown,
onSingleTapUp: _handleSingleTapUp,
onSingleTapCancel: _handleSingleTapCancel,
onSingleLongTapStart: _handleSingleLongTapStart,
onDoubleTapDown: _handleDoubleTapDown,
onForcePressStart: _handleForcePressStart,
onForcePressEnd: _handleForcePressEnd,
onDragSelectionStart: _handleDragSelectionStart,
onDragSelectionUpdate: _handleDragSelectionUpdate,
onDragSelectionEnd: _handleDragSelectionEnd,
child: Container(),
),
);
}
testWidgets('a series of taps all call onTaps', (WidgetTester tester) async {
await pumpGestureDetector(tester);
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 150));
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 150));
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 150));
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 150));
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 150));
await tester.tapAt(const Offset(200, 200));
expect(tapCount, 6);
});
testWidgets('in a series of rapid taps, onTapDown and onDoubleTapDown alternate', (WidgetTester tester) async {
await pumpGestureDetector(tester);
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 50));
expect(singleTapUpCount, 1);
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 50));
expect(singleTapUpCount, 1);
expect(doubleTapDownCount, 1);
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 50));
expect(singleTapUpCount, 2);
expect(doubleTapDownCount, 1);
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 50));
expect(singleTapUpCount, 2);
expect(doubleTapDownCount, 2);
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 50));
expect(singleTapUpCount, 3);
expect(doubleTapDownCount, 2);
await tester.tapAt(const Offset(200, 200));
expect(singleTapUpCount, 3);
expect(doubleTapDownCount, 3);
expect(tapCount, 6);
});
testWidgets('quick tap-tap-hold is a double tap down', (WidgetTester tester) async {
await pumpGestureDetector(tester);
await tester.tapAt(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 50));
expect(singleTapUpCount, 1);
final TestGesture gesture = await tester.startGesture(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 200));
expect(singleTapUpCount, 1);
// Every down is counted.
expect(tapCount, 2);
// No cancels because the second tap of the double tap is a second successful
// single tap behind the scene.
expect(singleTapCancelCount, 0);
expect(doubleTapDownCount, 1);
// The double tap down hold supersedes the single tap down.
expect(singleLongTapStartCount, 0);
await gesture.up();
// Nothing else happens on up.
expect(singleTapUpCount, 1);
expect(tapCount, 2);
expect(singleTapCancelCount, 0);
expect(doubleTapDownCount, 1);
expect(singleLongTapStartCount, 0);
});
testWidgets('a very quick swipe is ignored', (WidgetTester tester) async {
await pumpGestureDetector(tester);
final TestGesture gesture = await tester.startGesture(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 20));
await gesture.moveBy(const Offset(100, 100));
await tester.pump();
expect(singleTapUpCount, 0);
expect(tapCount, 0);
expect(singleTapCancelCount, 0);
expect(doubleTapDownCount, 0);
expect(singleLongTapStartCount, 0);
await gesture.up();
// Nothing else happens on up.
expect(singleTapUpCount, 0);
expect(tapCount, 0);
expect(singleTapCancelCount, 0);
expect(doubleTapDownCount, 0);
expect(singleLongTapStartCount, 0);
});
testWidgets('a slower swipe has a tap down and a canceled tap', (WidgetTester tester) async {
await pumpGestureDetector(tester);
final TestGesture gesture = await tester.startGesture(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 120));
await gesture.moveBy(const Offset(100, 100));
await tester.pump();
expect(singleTapUpCount, 0);
expect(tapCount, 1);
expect(singleTapCancelCount, 1);
expect(doubleTapDownCount, 0);
expect(singleLongTapStartCount, 0);
});
testWidgets('a force press intiates a force press', (WidgetTester tester) async {
await pumpGestureDetector(tester);
const int pointerValue = 1;
final TestGesture gesture = await tester.createGesture();
await gesture.downWithCustomEvent(
forcePressOffset,
const PointerDownEvent(
pointer: pointerValue,
position: forcePressOffset,
pressure: 0.0,
pressureMax: 6.0,
pressureMin: 0.0,
),
);
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
await gesture.up();
await tester.pumpAndSettle();
await gesture.downWithCustomEvent(
forcePressOffset,
const PointerDownEvent(
pointer: pointerValue,
position: forcePressOffset,
pressure: 0.0,
pressureMax: 6.0,
pressureMin: 0.0,
),
);
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
await gesture.up();
await tester.pump(const Duration(milliseconds: 20));
await gesture.downWithCustomEvent(
forcePressOffset,
const PointerDownEvent(
pointer: pointerValue,
position: forcePressOffset,
pressure: 0.0,
pressureMax: 6.0,
pressureMin: 0.0,
),
);
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
await gesture.up();
await tester.pump(const Duration(milliseconds: 20));
await gesture.downWithCustomEvent(
forcePressOffset,
const PointerDownEvent(
pointer: pointerValue,
position: forcePressOffset,
pressure: 0.0,
pressureMax: 6.0,
pressureMin: 0.0,
),
);
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
await gesture.up();
expect(forcePressStartCount, 4);
});
testWidgets('a tap and then force press intiates a force press and not a double tap', (WidgetTester tester) async {
await pumpGestureDetector(tester);
const int pointerValue = 1;
final TestGesture gesture = await tester.createGesture();
await gesture.downWithCustomEvent(
forcePressOffset,
const PointerDownEvent(
pointer: pointerValue,
position: forcePressOffset,
pressure: 0.0,
pressureMax: 6.0,
pressureMin: 0.0,
),
);
// Initiate a quick tap.
await gesture.updateWithCustomEvent(
const PointerMoveEvent(
pointer: pointerValue,
position: Offset(0.0, 0.0),
pressure: 0.0,
pressureMin: 0,
pressureMax: 1,
)
);
await tester.pump(const Duration(milliseconds: 50));
await gesture.up();
// Initiate a force tap.
await gesture.downWithCustomEvent(
forcePressOffset,
const PointerDownEvent(
pointer: pointerValue,
position: forcePressOffset,
pressure: 0.0,
pressureMax: 6.0,
pressureMin: 0.0,
),
);
await gesture.updateWithCustomEvent(const PointerMoveEvent(
pointer: pointerValue,
position: Offset(0.0, 0.0),
pressure: 0.5,
pressureMin: 0,
pressureMax: 1,
));
expect(forcePressStartCount, 1);
await tester.pump(const Duration(milliseconds: 50));
await gesture.up();
await tester.pumpAndSettle();
expect(forcePressEndCount, 1);
expect(doubleTapDownCount, 0);
});
testWidgets('a long press from a touch device is recognized as a long single tap', (WidgetTester tester) async {
await pumpGestureDetector(tester);
const int pointerValue = 1;
final TestGesture gesture =
await tester.startGesture(const Offset(200.0, 200.0), pointer: pointerValue, kind: PointerDeviceKind.touch);
await tester.pump(const Duration(seconds: 2));
await gesture.up();
await tester.pumpAndSettle();
expect(tapCount, 1);
expect(singleTapUpCount, 0);
expect(singleLongTapStartCount, 1);
});
testWidgets('a long press from a mouse is just a tap', (WidgetTester tester) async {
await pumpGestureDetector(tester);
const int pointerValue = 1;
final TestGesture gesture =
await tester.startGesture(const Offset(200.0, 200.0), pointer: pointerValue, kind: PointerDeviceKind.mouse);
await tester.pump(const Duration(seconds: 2));
await gesture.up();
await tester.pumpAndSettle();
expect(tapCount, 1);
expect(singleTapUpCount, 1);
expect(singleLongTapStartCount, 0);
});
testWidgets('a touch drag is not recognized for text selection', (WidgetTester tester) async {
await pumpGestureDetector(tester);
const int pointerValue = 1;
final TestGesture gesture =
await tester.startGesture(const Offset(200.0, 200.0), pointer: pointerValue, kind: PointerDeviceKind.touch);
await tester.pump();
await gesture.moveBy(const Offset(210.0, 200.0));
await tester.pump();
await gesture.up();
await tester.pumpAndSettle();
expect(tapCount, 0);
expect(singleTapUpCount, 0);
expect(dragStartCount, 0);
expect(dragUpdateCount, 0);
expect(dragEndCount, 0);
});
testWidgets('a mouse drag is recognized for text selection', (WidgetTester tester) async {
await pumpGestureDetector(tester);
const int pointerValue = 1;
final TestGesture gesture =
await tester.startGesture(const Offset(200.0, 200.0), pointer: pointerValue, kind: PointerDeviceKind.mouse);
await tester.pump();
await gesture.moveBy(const Offset(210.0, 200.0));
await tester.pump();
await gesture.up();
await tester.pumpAndSettle();
expect(tapCount, 0);
expect(singleTapUpCount, 0);
expect(dragStartCount, 1);
expect(dragUpdateCount, 1);
expect(dragEndCount, 1);
});
testWidgets('a slow mouse drag is still recognized for text selection', (WidgetTester tester) async {
await pumpGestureDetector(tester);
const int pointerValue = 1;
final TestGesture gesture =
await tester.startGesture(const Offset(200.0, 200.0), pointer: pointerValue, kind: PointerDeviceKind.mouse);
await tester.pump(const Duration(seconds: 2));
await gesture.moveBy(const Offset(210.0, 200.0));
await tester.pump();
await gesture.up();
await tester.pumpAndSettle();
expect(dragStartCount, 1);
expect(dragUpdateCount, 1);
expect(dragEndCount, 1);
});
}