// Copyright 2016 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 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/gestures.dart'; class TestDragData { const TestDragData( this.slop, this.dragDistance, this.expectedOffsets, ); final Offset slop; final Offset dragDistance; final List<Offset> expectedOffsets; } void main() { testWidgets( 'WidgetTester.drag must break the offset into multiple parallel components if' 'the drag goes outside the touch slop values', (WidgetTester tester) async { // This test checks to make sure that the total drag will be correctly split into // pieces such that the first (and potentially second) moveBy function call(s) in // controller.drag() will never have a component greater than the touch // slop in that component's respective axis. const List<TestDragData> offsetResults = <TestDragData>[ TestDragData( Offset(10.0, 10.0), Offset(-150.0, 200.0), <Offset>[ Offset(-7.5, 10.0), Offset(-2.5, 3.333333333333333), Offset(-140.0, 186.66666666666666), ], ), TestDragData( Offset(10.0, 10.0), Offset(150, -200), <Offset>[ Offset(7.5, -10), Offset(2.5, -3.333333333333333), Offset(140.0, -186.66666666666666), ], ), TestDragData( Offset(10.0, 10.0), Offset(-200, 150), <Offset>[ Offset(-10, 7.5), Offset(-3.333333333333333, 2.5), Offset(-186.66666666666666, 140.0), ], ), TestDragData( Offset(10.0, 10.0), Offset(200.0, -150.0), <Offset>[ Offset(10, -7.5), Offset(3.333333333333333, -2.5), Offset(186.66666666666666, -140.0), ], ), TestDragData( Offset(10.0, 10.0), Offset(-150.0, -200.0), <Offset>[ Offset(-7.5, -10.0), Offset(-2.5, -3.333333333333333), Offset(-140.0, -186.66666666666666), ], ), TestDragData( Offset(10.0, 10.0), Offset(8.0, 3.0), <Offset>[ Offset(8.0, 3.0), ], ), TestDragData( Offset(10.0, 10.0), Offset(3.0, 8.0), <Offset>[ Offset(3.0, 8.0), ], ), TestDragData( Offset(10.0, 10.0), Offset(20.0, 5.0), <Offset>[ Offset(10.0, 2.5), Offset(10.0, 2.5), ], ), TestDragData( Offset(10.0, 10.0), Offset(5.0, 20.0), <Offset>[ Offset(2.5, 10.0), Offset(2.5, 10.0), ], ), TestDragData( Offset(10.0, 10.0), Offset(20.0, 15.0), <Offset>[ Offset(10.0, 7.5), Offset(3.333333333333333, 2.5), Offset(6.666666666666668, 5.0), ], ), TestDragData( Offset(10.0, 10.0), Offset(15.0, 20.0), <Offset>[ Offset(7.5, 10.0), Offset(2.5, 3.333333333333333), Offset(5.0, 6.666666666666668), ], ), TestDragData( Offset(10.0, 10.0), Offset(20.0, 20.0), <Offset>[ Offset(10.0, 10.0), Offset(10.0, 10.0), ], ), TestDragData( Offset(10.0, 10.0), Offset(0.0, 5.0), <Offset>[ Offset(0.0, 5.0), ], ), //// Varying touch slops TestDragData( Offset(12.0, 5.0), Offset(0.0, 5.0), <Offset>[ Offset(0.0, 5.0), ], ), TestDragData( Offset(12.0, 5.0), Offset(20.0, 5.0), <Offset>[ Offset(12.0, 3.0), Offset(8.0, 2.0), ], ), TestDragData( Offset(12.0, 5.0), Offset(5.0, 20.0), <Offset>[ Offset(1.25, 5.0), Offset(3.75, 15.0), ], ), TestDragData( Offset(5.0, 12.0), Offset(5.0, 20.0), <Offset>[ Offset(3.0, 12.0), Offset(2.0, 8.0), ], ), TestDragData( Offset(5.0, 12.0), Offset(20.0, 5.0), <Offset>[ Offset(5.0, 1.25), Offset(15.0, 3.75), ], ), TestDragData( Offset(18.0, 18.0), Offset(0.0, 150.0), <Offset>[ Offset(0.0, 18.0), Offset(0.0, 132.0), ], ), TestDragData( Offset(18.0, 18.0), Offset(0.0, -150.0), <Offset>[ Offset(0.0, -18.0), Offset(0.0, -132.0), ], ), TestDragData( Offset(18.0, 18.0), Offset(-150.0, 0.0), <Offset>[ Offset(-18.0, 0.0), Offset(-132.0, 0.0), ], ), TestDragData( Offset(0.0, 0.0), Offset(-150.0, 0.0), <Offset>[ Offset(-150.0, 0.0), ], ), TestDragData( Offset(18.0, 18.0), Offset(-32.0, 0.0), <Offset>[ Offset(-18.0, 0.0), Offset(-14.0, 0.0), ], ), ]; final List<Offset> dragOffsets = <Offset>[]; await tester.pumpWidget( Listener( onPointerMove: (PointerMoveEvent event) { dragOffsets.add(event.delta); }, child: const Text('test', textDirection: TextDirection.ltr), ), ); for (int resultIndex = 0; resultIndex < offsetResults.length; resultIndex += 1) { final TestDragData testResult = offsetResults[resultIndex]; await tester.drag( find.text('test'), testResult.dragDistance, touchSlopX: testResult.slop.dx, touchSlopY: testResult.slop.dy, ); expect( testResult.expectedOffsets.length, dragOffsets.length, reason: 'There is a difference in the number of expected and actual split offsets for the drag with:\n' 'Touch Slop: ${testResult.slop}\n' 'Delta: ${testResult.dragDistance}\n', ); for (int valueIndex = 0; valueIndex < offsetResults[resultIndex].expectedOffsets.length; valueIndex += 1) { expect( testResult.expectedOffsets[valueIndex], offsetMoreOrLessEquals(dragOffsets[valueIndex]), reason: 'There is a difference in the expected and actual value of the ' + (valueIndex == 2 ? 'first' : valueIndex == 3 ? 'second' : 'third') + ' split offset for the drag with:\n' 'Touch slop: ${testResult.slop}\n' 'Delta: ${testResult.dragDistance}\n' ); } dragOffsets.clear(); } }, ); testWidgets( 'WidgetTester.tap must respect buttons', (WidgetTester tester) async { final List<String> logs = <String>[]; await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Listener( onPointerDown: (PointerDownEvent event) => logs.add('down ${event.buttons}'), onPointerMove: (PointerMoveEvent event) => logs.add('move ${event.buttons}'), onPointerUp: (PointerUpEvent event) => logs.add('up ${event.buttons}'), child: const Text('test'), ), ), ); await tester.tap(find.text('test'), buttons: kSecondaryMouseButton); const String b = '$kSecondaryMouseButton'; for(int i = 0; i < logs.length; i++) { if (i == 0) expect(logs[i], 'down $b'); else if (i != logs.length - 1) expect(logs[i], 'move $b'); else expect(logs[i], 'up 0'); } }, ); testWidgets( 'WidgetTester.press must respect buttons', (WidgetTester tester) async { final List<String> logs = <String>[]; await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Listener( onPointerDown: (PointerDownEvent event) => logs.add('down ${event.buttons}'), onPointerMove: (PointerMoveEvent event) => logs.add('move ${event.buttons}'), onPointerUp: (PointerUpEvent event) => logs.add('up ${event.buttons}'), child: const Text('test'), ), ), ); await tester.press(find.text('test'), buttons: kSecondaryMouseButton); const String b = '$kSecondaryMouseButton'; expect(logs, equals(<String>['down $b'])); }, ); testWidgets( 'WidgetTester.longPress must respect buttons', (WidgetTester tester) async { final List<String> logs = <String>[]; await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Listener( onPointerDown: (PointerDownEvent event) => logs.add('down ${event.buttons}'), onPointerMove: (PointerMoveEvent event) => logs.add('move ${event.buttons}'), onPointerUp: (PointerUpEvent event) => logs.add('up ${event.buttons}'), child: const Text('test'), ), ), ); await tester.longPress(find.text('test'), buttons: kSecondaryMouseButton); await tester.pumpAndSettle(); const String b = '$kSecondaryMouseButton'; for(int i = 0; i < logs.length; i++) { if (i == 0) expect(logs[i], 'down $b'); else if (i != logs.length - 1) expect(logs[i], 'move $b'); else expect(logs[i], 'up 0'); } }, ); testWidgets( 'WidgetTester.drag must respect buttons', (WidgetTester tester) async { final List<String> logs = <String>[]; await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Listener( onPointerDown: (PointerDownEvent event) => logs.add('down ${event.buttons}'), onPointerMove: (PointerMoveEvent event) => logs.add('move ${event.buttons}'), onPointerUp: (PointerUpEvent event) => logs.add('up ${event.buttons}'), child: const Text('test'), ), ), ); await tester.drag(find.text('test'), const Offset(-150.0, 200.0), buttons: kSecondaryMouseButton); const String b = '$kSecondaryMouseButton'; for(int i = 0; i < logs.length; i++) { if (i == 0) expect(logs[i], 'down $b'); else if (i != logs.length - 1) expect(logs[i], 'move $b'); else expect(logs[i], 'up 0'); } }, ); testWidgets( 'WidgetTester.fling must respect buttons', (WidgetTester tester) async { final List<String> logs = <String>[]; await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Listener( onPointerDown: (PointerDownEvent event) => logs.add('down ${event.buttons}'), onPointerMove: (PointerMoveEvent event) => logs.add('move ${event.buttons}'), onPointerUp: (PointerUpEvent event) => logs.add('up ${event.buttons}'), child: const Text('test'), ), ), ); await tester.fling(find.text('test'), const Offset(-10.0, 0.0), 1000.0, buttons: kSecondaryMouseButton); await tester.pumpAndSettle(); const String b = '$kSecondaryMouseButton'; for(int i = 0; i < logs.length; i++) { if (i == 0) expect(logs[i], 'down $b'); else if (i != logs.length - 1) expect(logs[i], 'move $b'); else expect(logs[i], 'up 0'); } }, ); }