refactor: rely on platform scroll physics and add scroll behavior tests
This commit is contained in:
91
test/scroll_behaviour_test.dart
Normal file
91
test/scroll_behaviour_test.dart
Normal file
@@ -0,0 +1,91 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:krow_worker_app/main.dart';
|
||||
|
||||
/// A list whose content is shorter than the viewport, so there is nothing to
|
||||
/// scroll to.
|
||||
Widget shortList() => MaterialApp(
|
||||
scrollBehavior: const KrowScrollBehavior(),
|
||||
home: Scaffold(
|
||||
body: ListView(
|
||||
children: const [SizedBox(height: 100, child: Text('only item'))],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Widget longList() => MaterialApp(
|
||||
scrollBehavior: const KrowScrollBehavior(),
|
||||
home: Scaffold(
|
||||
body: ListView(
|
||||
children: [
|
||||
for (var i = 0; i < 40; i++) SizedBox(height: 100, child: Text('$i')),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
ScrollPosition positionOf(WidgetTester tester) =>
|
||||
tester.state<ScrollableState>(find.byType(Scrollable)).position;
|
||||
|
||||
void main() {
|
||||
// TargetPlatformVariant sets and restores the override around each test;
|
||||
// assigning it by hand trips the framework's debug-variable invariant check.
|
||||
final android = TargetPlatformVariant.only(TargetPlatform.android);
|
||||
final ios = TargetPlatformVariant.only(TargetPlatform.iOS);
|
||||
|
||||
group('on Android', () {
|
||||
testWidgets('content that already fits does not move when dragged', (
|
||||
tester,
|
||||
) async {
|
||||
await tester.pumpWidget(shortList());
|
||||
final position = positionOf(tester);
|
||||
|
||||
// Every vertical list without a controller is handed an
|
||||
// AlwaysScrollableScrollPhysics by ScrollView itself, so the drag is
|
||||
// accepted whatever the content. Clamping is what pins it to the
|
||||
// boundary. Forcing bouncing globally instead let a one-item list be
|
||||
// dragged hundreds of pixels down, leaving a gap under the header.
|
||||
await tester.drag(find.text('only item'), const Offset(0, 300));
|
||||
await tester.pump();
|
||||
|
||||
expect(position.pixels, 0);
|
||||
}, variant: android);
|
||||
|
||||
testWidgets('a list that overflows still scrolls', (tester) async {
|
||||
await tester.pumpWidget(longList());
|
||||
final position = positionOf(tester);
|
||||
|
||||
await tester.drag(find.text('0'), const Offset(0, -200));
|
||||
await tester.pump();
|
||||
|
||||
expect(position.pixels, greaterThan(0));
|
||||
}, variant: android);
|
||||
|
||||
testWidgets('and does not overscroll past the top', (tester) async {
|
||||
await tester.pumpWidget(longList());
|
||||
final position = positionOf(tester);
|
||||
|
||||
await tester.drag(find.byType(Scrollable), const Offset(0, 400));
|
||||
await tester.pump();
|
||||
|
||||
expect(position.pixels, 0);
|
||||
}, variant: android);
|
||||
});
|
||||
|
||||
group('on iOS', () {
|
||||
testWidgets('short content rubber-bands, which is the convention there', (
|
||||
tester,
|
||||
) async {
|
||||
await tester.pumpWidget(shortList());
|
||||
final position = positionOf(tester);
|
||||
|
||||
await tester.drag(find.text('only item'), const Offset(0, 300));
|
||||
await tester.pump();
|
||||
expect(position.pixels, lessThan(0));
|
||||
|
||||
// And springs back on release, rather than leaving the gap behind.
|
||||
await tester.pumpAndSettle();
|
||||
expect(position.pixels, 0);
|
||||
}, variant: ios);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user