| // 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/gestures.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| import 'velocity_tracker_data.dart'; |
| |
| bool _withinTolerance(double actual, double expected) { |
| const double kTolerance = 0.001; // Within .1% of expected value |
| final double diff = (actual - expected)/expected; |
| return diff.abs() < kTolerance; |
| } |
| |
| bool _checkVelocity(Velocity actual, Offset expected) { |
| return (actual != null) |
| && _withinTolerance(actual.pixelsPerSecond.dx, expected.dx) |
| && _withinTolerance(actual.pixelsPerSecond.dy, expected.dy); |
| } |
| |
| void main() { |
| const List<Offset> expected = <Offset>[ |
| Offset(219.5762939453125, 1304.6705322265625), |
| Offset(355.6900939941406, 967.1700439453125), |
| Offset(12.651158332824707, -36.9227180480957), |
| Offset(714.1383056640625, -2561.540283203125), |
| Offset(-19.658065795898438, -2910.080322265625), |
| Offset(646.8700561523438, 2976.982421875), |
| Offset(396.6878967285156, 2106.204833984375), |
| Offset(298.3150634765625, -3660.821044921875), |
| Offset(-1.7460877895355225, -3288.16162109375), |
| Offset(384.6415710449219, -2645.6484375), |
| Offset(176.3752899169922, 2711.24609375), |
| Offset(396.9254455566406, 4280.640625), |
| Offset(-71.51288604736328, 3716.74560546875), |
| ]; |
| |
| test('Velocity tracker gives expected results', () { |
| final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch); |
| int i = 0; |
| for (final PointerEvent event in velocityEventData) { |
| if (event is PointerDownEvent || event is PointerMoveEvent) |
| tracker.addPosition(event.timeStamp, event.position); |
| if (event is PointerUpEvent) { |
| _checkVelocity(tracker.getVelocity(), expected[i]); |
| i += 1; |
| } |
| } |
| }); |
| |
| test('Velocity control test', () { |
| const Velocity velocity1 = Velocity(pixelsPerSecond: Offset(7.0, 0.0)); |
| const Velocity velocity2 = Velocity(pixelsPerSecond: Offset(12.0, 0.0)); |
| expect(velocity1, equals(const Velocity(pixelsPerSecond: Offset(7.0, 0.0)))); |
| expect(velocity1, isNot(equals(velocity2))); |
| expect(velocity2 - velocity1, equals(const Velocity(pixelsPerSecond: Offset(5.0, 0.0)))); |
| expect((-velocity1).pixelsPerSecond, const Offset(-7.0, 0.0)); |
| expect(velocity1 + velocity2, equals(const Velocity(pixelsPerSecond: Offset(19.0, 0.0)))); |
| expect(velocity1.hashCode, isNot(equals(velocity2.hashCode))); |
| expect(velocity1, hasOneLineDescription); |
| }); |
| |
| test('Interrupted velocity estimation', () { |
| // Regression test for https://github.com/flutter/flutter/pull/7510 |
| final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch); |
| for (final PointerEvent event in interruptedVelocityEventData) { |
| if (event is PointerDownEvent || event is PointerMoveEvent) |
| tracker.addPosition(event.timeStamp, event.position); |
| if (event is PointerUpEvent) { |
| _checkVelocity(tracker.getVelocity(), const Offset(649.5, 3890.3)); |
| } |
| } |
| }); |
| |
| test('No data velocity estimation', () { |
| final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch); |
| expect(tracker.getVelocity(), Velocity.zero); |
| }); |
| |
| test('FreeScrollStartVelocityTracker.getVelocity throws when no points', () { |
| final IOSScrollViewFlingVelocityTracker tracker = IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch); |
| AssertionError? exception; |
| try { |
| tracker.getVelocity(); |
| } on AssertionError catch (e) { |
| exception = e; |
| } |
| |
| expect(exception?.toString(), contains('at least 1 point')); |
| }); |
| |
| test('FreeScrollStartVelocityTracker.getVelocity throws when the new point precedes the previous point', () { |
| final IOSScrollViewFlingVelocityTracker tracker = IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch); |
| AssertionError? exception; |
| |
| tracker.addPosition(const Duration(hours: 1), Offset.zero); |
| try { |
| tracker.getVelocity(); |
| tracker.addPosition(const Duration(seconds: 1), Offset.zero); |
| } on AssertionError catch (e) { |
| exception = e; |
| } |
| |
| expect(exception?.toString(), contains('has a smaller timestamp')); |
| }); |
| |
| test('Estimate does not throw when there are more than 1 point', () { |
| final IOSScrollViewFlingVelocityTracker tracker = IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch); |
| Offset position = Offset.zero; |
| Duration time = Duration.zero; |
| const Offset positionDelta = Offset(0, -1); |
| const Duration durationDelta = Duration(seconds: 1); |
| AssertionError? exception; |
| |
| for (int i = 0; i < 5; i+=1) { |
| position += positionDelta; |
| time += durationDelta; |
| tracker.addPosition(time, position); |
| |
| try { |
| tracker.getVelocity(); |
| } on AssertionError catch (e) { |
| exception = e; |
| } |
| expect(exception, isNull); |
| } |
| }); |
| |
| test('Makes consistent velocity estimates with consistent velocity', () { |
| final IOSScrollViewFlingVelocityTracker tracker = IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch); |
| Offset position = Offset.zero; |
| Duration time = Duration.zero; |
| const Offset positionDelta = Offset(0, -1); |
| const Duration durationDelta = Duration(seconds: 1); |
| |
| for (int i = 0; i < 10; i+=1) { |
| position += positionDelta; |
| time += durationDelta; |
| tracker.addPosition(time, position); |
| |
| if (i >= 3) { |
| expect(tracker.getVelocity().pixelsPerSecond, positionDelta); |
| } |
| } |
| }); |
| } |