| // Copyright 2014 The Flutter 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/material.dart'; |
| import 'package:flutter/gestures.dart'; |
| import 'package:flutter/scheduler.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| class CountButton extends StatefulWidget { |
| const CountButton({Key? key}) : super(key: key); |
| |
| @override |
| _CountButtonState createState() => _CountButtonState(); |
| } |
| |
| class _CountButtonState extends State<CountButton> { |
| int counter = 0; |
| @override |
| Widget build(BuildContext context) { |
| return ElevatedButton( |
| child: Text('Counter $counter'), |
| onPressed: () { |
| setState(() { |
| counter += 1; |
| }); |
| }, |
| ); |
| } |
| } |
| |
| class AnimateSample extends StatefulWidget { |
| const AnimateSample({Key? key}) : super(key: key); |
| |
| @override |
| _AnimateSampleState createState() => _AnimateSampleState(); |
| } |
| |
| class _AnimateSampleState extends State<AnimateSample> |
| with SingleTickerProviderStateMixin { |
| late 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(const MaterialApp(home: Center(child: CountButton()))); |
| |
| await SchedulerBinding.instance!.endOfFrame; |
| final WidgetController controller = |
| LiveWidgetController(WidgetsBinding.instance!); |
| await controller.tap(find.text('Counter 0')); |
| expect(find.text('Counter 0'), findsOneWidget); |
| expect(find.text('Counter 1'), findsNothing); |
| await controller.pump(); |
| expect(find.text('Counter 0'), findsNothing); |
| expect(find.text('Counter 1'), findsOneWidget); |
| }); |
| |
| test('Test pumpAndSettle on LiveWidgetController', () async { |
| runApp(const 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( |
| MaterialApp( |
| home: 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 SchedulerBinding.instance!.endOfFrame; |
| final WidgetController controller = |
| LiveWidgetController(WidgetsBinding.instance!); |
| |
| final Offset location = controller.getCenter(find.text('test')); |
| final List<PointerEventRecord> records = <PointerEventRecord>[ |
| PointerEventRecord(Duration.zero, <PointerEvent>[ |
| // Typically PointerAddedEvent is not used in testers, but for records |
| // captured on a device it is usually what start a gesture. |
| PointerAddedEvent( |
| timeStamp: Duration.zero, |
| position: location, |
| ), |
| PointerDownEvent( |
| timeStamp: Duration.zero, |
| position: location, |
| buttons: kSecondaryMouseButton, |
| pointer: 1, |
| ), |
| ]), |
| ...<PointerEventRecord>[ |
| for (Duration t = const Duration(milliseconds: 5); |
| t < const Duration(milliseconds: 80); |
| t += const Duration(milliseconds: 16)) |
| PointerEventRecord(t, <PointerEvent>[ |
| PointerMoveEvent( |
| timeStamp: t - const Duration(milliseconds: 1), |
| position: location, |
| buttons: kSecondaryMouseButton, |
| pointer: 1, |
| ) |
| ]) |
| ], |
| PointerEventRecord(const Duration(milliseconds: 80), <PointerEvent>[ |
| PointerUpEvent( |
| timeStamp: const Duration(milliseconds: 79), |
| position: location, |
| buttons: kSecondaryMouseButton, |
| pointer: 1, |
| ) |
| ]) |
| ]; |
| final List<Duration> timeDiffs = |
| await controller.handlePointerEventRecord(records); |
| |
| expect(timeDiffs.length, records.length); |
| for (final Duration diff in timeDiffs) { |
| // Allow some freedom of time delay in real world. |
| assert(diff.inMilliseconds > -1); |
| } |
| |
| const String b = '$kSecondaryMouseButton'; |
| expect(logs.first, 'down $b'); |
| for (int i = 1; i < logs.length - 1; i++) { |
| expect(logs[i], 'move $b'); |
| } |
| expect(logs.last, 'up $b'); |
| }); |
| } |