92 lines
3.0 KiB
Dart
92 lines
3.0 KiB
Dart
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);
|
|
});
|
|
}
|