Unverified Commit d4e2c6bc authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[null-safety] remove mockito from refresh control test (#64280)

parent f37113dc
...@@ -8,55 +8,15 @@ import 'dart:async'; ...@@ -8,55 +8,15 @@ import 'dart:async';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
void main() { void main() {
MockHelper mockHelper; FakeBuilder mockHelper;
/// Completer that holds the future given to the CupertinoSliverRefreshControl.
Completer<void> refreshCompleter;
/// The widget that the indicator builder given to the CupertinoSliverRefreshControl
/// returns.
Widget refreshIndicator;
/// These two Functions are required to avoid tearing off of the MockHelper object,
/// which is not supported when using Dart 2 runtime semantics.
final RefreshControlIndicatorBuilder builder = (
BuildContext context,
RefreshIndicatorMode refreshState,
double pulledExtent,
double refreshTriggerPullDistance,
double refreshIndicatorExtent,
) => mockHelper.builder(context, refreshState, pulledExtent, refreshTriggerPullDistance, refreshIndicatorExtent);
Future<void> onRefresh() => mockHelper.refreshTask();
setUp(() { setUp(() {
mockHelper = MockHelper(); mockHelper = FakeBuilder();
refreshCompleter = Completer<void>.sync();
refreshIndicator = Container();
when(mockHelper.builder(any, any, any, any, any))
.thenAnswer((Invocation i) {
final double pulledExtent = i.positionalArguments[2] as double;
final double refreshTriggerPullDistance = i.positionalArguments[3] as double;
final double refreshIndicatorExtent = i.positionalArguments[4] as double;
if (pulledExtent < 0.0) {
throw TestFailure('The pulledExtent should never be less than 0.0');
}
if (refreshTriggerPullDistance < 0.0) {
throw TestFailure('The refreshTriggerPullDistance should never be less than 0.0');
}
if (refreshIndicatorExtent < 0.0) {
throw TestFailure('The refreshIndicatorExtent should never be less than 0.0');
}
return refreshIndicator;
});
when(mockHelper.refreshTask()).thenAnswer((_) => refreshCompleter.future);
}); });
int testListLength = 10; int testListLength = 10;
...@@ -82,7 +42,7 @@ void main() { ...@@ -82,7 +42,7 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -90,7 +50,7 @@ void main() { ...@@ -90,7 +50,7 @@ void main() {
), ),
); );
verifyNoMoreInteractions(mockHelper); expect(mockHelper.invocations, isEmpty);
expect( expect(
tester.getTopLeft(find.widgetWithText(Container, '0')), tester.getTopLeft(find.widgetWithText(Container, '0')),
...@@ -105,7 +65,7 @@ void main() { ...@@ -105,7 +65,7 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -119,14 +79,13 @@ void main() { ...@@ -119,14 +79,13 @@ void main() {
// The function is referenced once while passing into CupertinoSliverRefreshControl // The function is referenced once while passing into CupertinoSliverRefreshControl
// and is called. // and is called.
verify(mockHelper.builder( expect(mockHelper.invocations.first, matchesBuilder(
any, refreshState: RefreshIndicatorMode.drag,
RefreshIndicatorMode.drag, pulledExtent: 50,
50.0, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value.
)); ));
verifyNoMoreInteractions(mockHelper); expect(mockHelper.invocations, hasLength(1));
expect( expect(
tester.getTopLeft(find.widgetWithText(Container, '0')), tester.getTopLeft(find.widgetWithText(Container, '0')),
...@@ -143,7 +102,7 @@ void main() { ...@@ -143,7 +102,7 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -155,7 +114,7 @@ void main() { ...@@ -155,7 +114,7 @@ void main() {
await tester.drag(find.text('0'), const Offset(0.0, 50.0)); await tester.drag(find.text('0'), const Offset(0.0, 50.0));
await tester.pump(); await tester.pump();
verifyNoMoreInteractions(mockHelper); expect(mockHelper.invocations, isEmpty);
expect( expect(
tester.getTopLeft(find.widgetWithText(Container, '0')), tester.getTopLeft(find.widgetWithText(Container, '0')),
...@@ -170,7 +129,7 @@ void main() { ...@@ -170,7 +129,7 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -185,31 +144,28 @@ void main() { ...@@ -185,31 +144,28 @@ void main() {
await tester.pump(const Duration(milliseconds: 20)); await tester.pump(const Duration(milliseconds: 20));
await tester.pump(const Duration(seconds: 3)); await tester.pump(const Duration(seconds: 3));
verifyInOrder(<void>[ expect(mockHelper.invocations, containsAllInOrder(<void>[
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.drag,
RefreshIndicatorMode.drag, pulledExtent: 50,
50.0, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value.
), ),
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.drag,
RefreshIndicatorMode.drag, pulledExtent: moreOrLessEquals(48.36801747187993),
argThat(moreOrLessEquals(48.36801747187993)), refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value.
), ),
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.drag,
RefreshIndicatorMode.drag, pulledExtent: moreOrLessEquals(44.63031931875867),
argThat(moreOrLessEquals(44.63031931875867)), refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value.
), ),
// The builder isn't called again when the sliver completely goes away. ]));
]); // The builder isn't called again when the sliver completely goes away.
verifyNoMoreInteractions(mockHelper); expect(mockHelper.invocations, hasLength(3));
expect( expect(
tester.getTopLeft(find.widgetWithText(Container, '0')), tester.getTopLeft(find.widgetWithText(Container, '0')),
...@@ -230,8 +186,8 @@ void main() { ...@@ -230,8 +186,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -247,32 +203,29 @@ void main() { ...@@ -247,32 +203,29 @@ void main() {
await gesture.moveBy(const Offset(0.0, 50.0)); await gesture.moveBy(const Offset(0.0, 50.0));
await tester.pump(); await tester.pump();
verifyInOrder(<void>[ expect(mockHelper.invocations, containsAllInOrder(<void>[
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.drag,
RefreshIndicatorMode.drag, pulledExtent: 99,
99.0, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value.
), ),
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.drag,
RefreshIndicatorMode.drag, pulledExtent: moreOrLessEquals(86.78169),
argThat(moreOrLessEquals(86.78169)), refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value.
), ),
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.armed,
RefreshIndicatorMode.armed, pulledExtent: moreOrLessEquals(105.80452021305739),
argThat(moreOrLessEquals(105.80452021305739)), refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value.
), ),
// The refresh callback is triggered after the frame. ]));
mockHelper.refreshTask(), // The refresh callback is triggered after the frame.
]); expect(mockHelper.invocations.last, const RefreshTaskInvocation());
verifyNoMoreInteractions(mockHelper); expect(mockHelper.invocations, hasLength(4));
expect( expect(
platformCallLog.last, platformCallLog.last,
...@@ -289,8 +242,8 @@ void main() { ...@@ -289,8 +242,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -303,53 +256,49 @@ void main() { ...@@ -303,53 +256,49 @@ void main() {
// Let it start snapping back. // Let it start snapping back.
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
verifyInOrder(<void>[ expect(mockHelper.invocations, containsAllInOrder(<Matcher>[
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.armed,
RefreshIndicatorMode.armed, pulledExtent: 150,
150.0, refreshTriggerPullDistance: 100, // Default value.
100.0, // Default value. refreshIndicatorExtent: 60, // Default value.
60.0, // Default value.
), ),
mockHelper.refreshTask(), equals(const RefreshTaskInvocation()),
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.armed,
RefreshIndicatorMode.armed, pulledExtent: moreOrLessEquals(127.10396988577114),
argThat(moreOrLessEquals(127.10396988577114)), refreshTriggerPullDistance: 100, // Default value.
100.0, // Default value. refreshIndicatorExtent: 60, // Default value.
60.0, // Default value.
), ),
]); ]));
// Reaches refresh state and sliver's at 60.0 in height after a while. // Reaches refresh state and sliver's at 60.0 in height after a while.
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
verify(mockHelper.builder(
any, expect(mockHelper.invocations, contains(matchesBuilder(
RefreshIndicatorMode.refresh, refreshState: RefreshIndicatorMode.refresh,
60.0, pulledExtent: 60,
100.0, // Default value. refreshIndicatorExtent: 60, // Default value.
60.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
)); )));
// Stays in that state forever until future completes. // Stays in that state forever until future completes.
await tester.pump(const Duration(seconds: 1000)); await tester.pump(const Duration(seconds: 1000));
verifyNoMoreInteractions(mockHelper);
expect( expect(
tester.getTopLeft(find.widgetWithText(Container, '0')), tester.getTopLeft(find.widgetWithText(Container, '0')),
const Offset(0.0, 60.0), const Offset(0.0, 60.0),
); );
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
await tester.pump(); await tester.pump();
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.done,
RefreshIndicatorMode.done, pulledExtent: 60,
60.0, refreshIndicatorExtent: 60, // Default value.
100.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
60.0, // Default value. )));
)); expect(mockHelper.invocations, hasLength(5));
verifyNoMoreInteractions(mockHelper);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgets(
...@@ -360,16 +309,15 @@ void main() { ...@@ -360,16 +309,15 @@ void main() {
runZoned( runZoned(
() async { () async {
refreshCompleter = Completer<void>.sync(); mockHelper.refreshCompleter = Completer<void>.sync();
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -382,53 +330,48 @@ void main() { ...@@ -382,53 +330,48 @@ void main() {
// Let it start snapping back. // Let it start snapping back.
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
verifyInOrder(<void>[ expect(mockHelper.invocations, containsAllInOrder(<Matcher>[
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.armed,
RefreshIndicatorMode.armed, pulledExtent: 150,
150.0, refreshIndicatorExtent: 60, // Default value.
100.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
60.0, // Default value.
), ),
mockHelper.refreshTask(), equals(const RefreshTaskInvocation()),
mockHelper.builder( matchesBuilder(
any, refreshState: RefreshIndicatorMode.armed,
RefreshIndicatorMode.armed, pulledExtent: moreOrLessEquals(127.10396988577114),
argThat(moreOrLessEquals(127.10396988577114)), refreshIndicatorExtent: 60, // Default value.
100.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
60.0, // Default value.
), ),
]); ]));
// Reaches refresh state and sliver's at 60.0 in height after a while. // Reaches refresh state and sliver's at 60.0 in height after a while.
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.refresh,
RefreshIndicatorMode.refresh, pulledExtent: 60,
60.0, refreshIndicatorExtent: 60, // Default value.
100.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
60.0, // Default value. )));
));
// Stays in that state forever until future completes. // Stays in that state forever until future completes.
await tester.pump(const Duration(seconds: 1000)); await tester.pump(const Duration(seconds: 1000));
verifyNoMoreInteractions(mockHelper);
expect( expect(
tester.getTopLeft(find.widgetWithText(Container, '0')), tester.getTopLeft(find.widgetWithText(Container, '0')),
const Offset(0.0, 60.0), const Offset(0.0, 60.0),
); );
refreshCompleter.completeError(error); mockHelper.refreshCompleter.completeError(error);
await tester.pump(); await tester.pump();
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.done,
RefreshIndicatorMode.done, pulledExtent: 60,
60.0, refreshIndicatorExtent: 60, // Default value.
100.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
60.0, // Default value. )));
)); expect(mockHelper.invocations, hasLength(5));
verifyNoMoreInteractions(mockHelper);
}, },
onError: (dynamic e) { onError: (dynamic e) {
expect(e, error); expect(e, error);
...@@ -439,7 +382,7 @@ void main() { ...@@ -439,7 +382,7 @@ void main() {
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('expanded refreshing sliver scrolls normally', (WidgetTester tester) async { testWidgets('expanded refreshing sliver scrolls normally', (WidgetTester tester) async {
refreshIndicator = const Center(child: Text('-1')); mockHelper.refreshIndicator = const Center(child: Text('-1'));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -447,8 +390,8 @@ void main() { ...@@ -447,8 +390,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -459,13 +402,12 @@ void main() { ...@@ -459,13 +402,12 @@ void main() {
await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0); await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0);
await tester.pump(); await tester.pump();
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.armed,
RefreshIndicatorMode.armed, pulledExtent: 150,
150.0, refreshIndicatorExtent: 60, // Default value.
100.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
60.0, // Default value. )));
));
// Given a box constraint of 150, the Center will occupy all that height. // Given a box constraint of 150, the Center will occupy all that height.
expect( expect(
...@@ -477,13 +419,12 @@ void main() { ...@@ -477,13 +419,12 @@ void main() {
await tester.pump(); await tester.pump();
// Refresh indicator still being told to layout the same way. // Refresh indicator still being told to layout the same way.
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.refresh,
RefreshIndicatorMode.refresh, pulledExtent: 60,
60.0, refreshIndicatorExtent: 60, // Default value.
100.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
60.0, // Default value. )));
));
// Now the sliver is scrolled off screen. // Now the sliver is scrolled off screen.
expect( expect(
...@@ -515,7 +456,7 @@ void main() { ...@@ -515,7 +456,7 @@ void main() {
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('expanded refreshing sliver goes away when done', (WidgetTester tester) async { testWidgets('expanded refreshing sliver goes away when done', (WidgetTester tester) async {
refreshIndicator = const Center(child: Text('-1')); mockHelper.refreshIndicator = const Center(child: Text('-1'));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -523,8 +464,8 @@ void main() { ...@@ -523,8 +464,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -534,30 +475,29 @@ void main() { ...@@ -534,30 +475,29 @@ void main() {
await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0); await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0);
await tester.pump(); await tester.pump();
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.armed,
RefreshIndicatorMode.armed, pulledExtent: 150,
150.0, refreshIndicatorExtent: 60, // Default value.
100.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
60.0, // Default value. )));
));
expect( expect(
tester.getRect(find.widgetWithText(Center, '-1')), tester.getRect(find.widgetWithText(Center, '-1')),
const Rect.fromLTRB(0.0, 0.0, 800.0, 150.0), const Rect.fromLTRB(0.0, 0.0, 800.0, 150.0),
); );
verify(mockHelper.refreshTask()); expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));
// Rebuilds the sliver with a layout extent now. // Rebuilds the sliver with a layout extent now.
await tester.pump(); await tester.pump();
// Let it snap back to occupy the indicator's final sliver space only. // Let it snap back to occupy the indicator's final sliver space only.
await tester.pump(const Duration(seconds: 2)); await tester.pump(const Duration(seconds: 2));
verify(mockHelper.builder(
any, expect(mockHelper.invocations, contains(matchesBuilder(
RefreshIndicatorMode.refresh, refreshState: RefreshIndicatorMode.refresh,
60.0, pulledExtent: 60,
100.0, // Default value. refreshIndicatorExtent: 60, // Default value.
60.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
)); )));
expect( expect(
tester.getRect(find.widgetWithText(Center, '-1')), tester.getRect(find.widgetWithText(Center, '-1')),
const Rect.fromLTRB(0.0, 0.0, 800.0, 60.0), const Rect.fromLTRB(0.0, 0.0, 800.0, 60.0),
...@@ -567,15 +507,14 @@ void main() { ...@@ -567,15 +507,14 @@ void main() {
const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0), const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0),
); );
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
await tester.pump(); await tester.pump();
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.done,
RefreshIndicatorMode.done, pulledExtent: 60,
60.0, refreshIndicatorExtent: 60, // Default value.
100.0, // Default value. refreshTriggerPullDistance: 100, // Default value.
60.0, // Default value. )));
));
await tester.pump(const Duration(seconds: 5)); await tester.pump(const Duration(seconds: 5));
expect(find.text('-1'), findsNothing); expect(find.text('-1'), findsNothing);
...@@ -586,7 +525,7 @@ void main() { ...@@ -586,7 +525,7 @@ void main() {
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('builder still called when sliver snapped back more than 90%', (WidgetTester tester) async { testWidgets('builder still called when sliver snapped back more than 90%', (WidgetTester tester) async {
refreshIndicator = const Center(child: Text('-1')); mockHelper.refreshIndicator = const Center(child: Text('-1'));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -594,8 +533,8 @@ void main() { ...@@ -594,8 +533,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -605,30 +544,28 @@ void main() { ...@@ -605,30 +544,28 @@ void main() {
await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0); await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0);
await tester.pump(); await tester.pump();
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.armed,
RefreshIndicatorMode.armed, pulledExtent: 150,
150.0, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value. )));
));
expect( expect(
tester.getRect(find.widgetWithText(Center, '-1')), tester.getRect(find.widgetWithText(Center, '-1')),
const Rect.fromLTRB(0.0, 0.0, 800.0, 150.0), const Rect.fromLTRB(0.0, 0.0, 800.0, 150.0),
); );
verify(mockHelper.refreshTask()); expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));
// Rebuilds the sliver with a layout extent now. // Rebuilds the sliver with a layout extent now.
await tester.pump(); await tester.pump();
// Let it snap back to occupy the indicator's final sliver space only. // Let it snap back to occupy the indicator's final sliver space only.
await tester.pump(const Duration(seconds: 2)); await tester.pump(const Duration(seconds: 2));
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.refresh,
RefreshIndicatorMode.refresh, pulledExtent: 60,
60.0, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value. )));
));
expect( expect(
tester.getRect(find.widgetWithText(Center, '-1')), tester.getRect(find.widgetWithText(Center, '-1')),
const Rect.fromLTRB(0.0, 0.0, 800.0, 60.0), const Rect.fromLTRB(0.0, 0.0, 800.0, 60.0),
...@@ -638,15 +575,15 @@ void main() { ...@@ -638,15 +575,15 @@ void main() {
const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0), const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0),
); );
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
await tester.pump(); await tester.pump();
verify(mockHelper.builder(
any, expect(mockHelper.invocations, contains(matchesBuilder(
RefreshIndicatorMode.done, refreshState: RefreshIndicatorMode.done,
60.0, pulledExtent: 60,
100.0, // Default value. refreshTriggerPullDistance: 100, // default value.
60.0, // Default value. refreshIndicatorExtent: 60, // default value.
)); )));
// Waiting for refresh control to reach approximately 5% of height // Waiting for refresh control to reach approximately 5% of height
await tester.pump(const Duration(milliseconds: 400)); await tester.pump(const Duration(milliseconds: 400));
...@@ -659,20 +596,19 @@ void main() { ...@@ -659,20 +596,19 @@ void main() {
tester.getRect(find.widgetWithText(Center, '-1')).height, tester.getRect(find.widgetWithText(Center, '-1')).height,
moreOrLessEquals(3.0, epsilon: 4e-1), moreOrLessEquals(3.0, epsilon: 4e-1),
); );
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.inactive,
RefreshIndicatorMode.inactive, pulledExtent: 2.6980688300546443, // ~5% of 60.0
2.6980688300546443, // ~5% of 60.0 refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value. )));
));
expect(find.text('-1'), findsOneWidget); expect(find.text('-1'), findsOneWidget);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgets(
'retracting sliver during done cannot be pulled to refresh again until fully retracted', 'retracting sliver during done cannot be pulled to refresh again until fully retracted',
(WidgetTester tester) async { (WidgetTester tester) async {
refreshIndicator = const Center(child: Text('-1')); mockHelper.refreshIndicator = const Center(child: Text('-1'));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -680,8 +616,8 @@ void main() { ...@@ -680,8 +616,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -691,28 +627,27 @@ void main() { ...@@ -691,28 +627,27 @@ void main() {
await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0.0); await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0.0);
await tester.pump(); await tester.pump();
verify(mockHelper.refreshTask()); expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
await tester.pump(); await tester.pump();
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.done,
RefreshIndicatorMode.done, pulledExtent: 150.0, // Still overscrolled here.
150.0, // Still overscrolled here. refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value. )));
));
// Let it start going away but not fully. // Let it start going away but not fully.
await tester.pump(const Duration(milliseconds: 100)); await tester.pump(const Duration(milliseconds: 100));
// The refresh indicator is still building. // The refresh indicator is still building.
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.done,
RefreshIndicatorMode.done, pulledExtent: 91.31180913199277,
91.31180913199277, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value. )));
));
expect( expect(
tester.getBottomLeft(find.widgetWithText(Center, '-1')).dy, tester.getBottomLeft(find.widgetWithText(Center, '-1')).dy,
moreOrLessEquals(91.311809131992776), moreOrLessEquals(91.311809131992776),
...@@ -725,13 +660,12 @@ void main() { ...@@ -725,13 +660,12 @@ void main() {
// Instead, it's still in the done state because the sliver never // Instead, it's still in the done state because the sliver never
// fully retracted. // fully retracted.
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.done,
RefreshIndicatorMode.done, pulledExtent: 147.3772721631821,
147.3772721631821, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value. )));
));
// Now let it fully go away. // Now let it fully go away.
await tester.pump(const Duration(seconds: 5)); await tester.pump(const Duration(seconds: 5));
...@@ -744,19 +678,18 @@ void main() { ...@@ -744,19 +678,18 @@ void main() {
// Start another drag. It's now in drag mode. // Start another drag. It's now in drag mode.
await tester.drag(find.text('0'), const Offset(0.0, 40.0), touchSlopY: 0.0); await tester.drag(find.text('0'), const Offset(0.0, 40.0), touchSlopY: 0.0);
await tester.pump(); await tester.pump();
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.drag,
RefreshIndicatorMode.drag, pulledExtent: 40,
40.0, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value. )));
));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgets(
'sliver held in overscroll when task finishes completes normally', 'sliver held in overscroll when task finishes completes normally',
(WidgetTester tester) async { (WidgetTester tester) async {
refreshIndicator = const Center(child: Text('-1')); mockHelper.refreshIndicator = const Center(child: Text('-1'));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -764,8 +697,8 @@ void main() { ...@@ -764,8 +697,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -777,18 +710,18 @@ void main() { ...@@ -777,18 +710,18 @@ void main() {
// Start a refresh. // Start a refresh.
await gesture.moveBy(const Offset(0.0, 150.0)); await gesture.moveBy(const Offset(0.0, 150.0));
await tester.pump(); await tester.pump();
verify(mockHelper.refreshTask()); expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));
// Complete the task while held down. // Complete the task while held down.
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
await tester.pump(); await tester.pump();
verify(mockHelper.builder(
any, expect(mockHelper.invocations, contains(matchesBuilder(
RefreshIndicatorMode.done, refreshState: RefreshIndicatorMode.done,
150.0, // Still overscrolled here. pulledExtent: 150.0, // Still overscrolled here.
100.0, // Default value. refreshTriggerPullDistance: 100, // default value.
60.0, // Default value. refreshIndicatorExtent: 60, // default value.
)); )));
expect( expect(
tester.getRect(find.widgetWithText(Center, '0')), tester.getRect(find.widgetWithText(Center, '0')),
const Rect.fromLTRB(0.0, 150.0, 800.0, 350.0), const Rect.fromLTRB(0.0, 150.0, 800.0, 350.0),
...@@ -812,7 +745,7 @@ void main() { ...@@ -812,7 +745,7 @@ void main() {
// the indicator can be scrolled away while refreshing. // the indicator can be scrolled away while refreshing.
return; return;
} }
refreshIndicator = const Center(child: Text('-1')); mockHelper.refreshIndicator = const Center(child: Text('-1'));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -820,8 +753,8 @@ void main() { ...@@ -820,8 +753,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -832,19 +765,18 @@ void main() { ...@@ -832,19 +765,18 @@ void main() {
// Start a refresh. // Start a refresh.
await tester.drag(find.text('0'), const Offset(0.0, 150.0)); await tester.drag(find.text('0'), const Offset(0.0, 150.0));
await tester.pump(); await tester.pump();
verify(mockHelper.refreshTask()); expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));
await tester.drag(find.text('0'), const Offset(0.0, -300.0)); await tester.drag(find.text('0'), const Offset(0.0, -300.0));
await tester.pump(); await tester.pump();
// Refresh indicator still being told to layout the same way. // Refresh indicator still being told to layout the same way.
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.done,
RefreshIndicatorMode.refresh, pulledExtent: 60,
60.0, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value. )));
));
// Now the sliver is scrolled off screen. // Now the sliver is scrolled off screen.
expect( expect(
...@@ -857,7 +789,7 @@ void main() { ...@@ -857,7 +789,7 @@ void main() {
); );
// Complete the task while scrolled away. // Complete the task while scrolled away.
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
// The sliver is instantly gone since there is no overscroll physics // The sliver is instantly gone since there is no overscroll physics
// simulation. // simulation.
await tester.pump(); await tester.pump();
...@@ -873,13 +805,12 @@ void main() { ...@@ -873,13 +805,12 @@ void main() {
await tester.drag(find.text('1'), const Offset(0.0, 120.0)); await tester.drag(find.text('1'), const Offset(0.0, 120.0));
await tester.pump(); await tester.pump();
verify(mockHelper.builder( expect(mockHelper.invocations, contains(matchesBuilder(
any, refreshState: RefreshIndicatorMode.done,
RefreshIndicatorMode.drag, pulledExtent: 4.615384615384642,
4.615384615384642, refreshTriggerPullDistance: 100, // default value.
100.0, // Default value. refreshIndicatorExtent: 60, // default value.
60.0, // Default value. )));
));
// Snaps away normally. // Snaps away normally.
await tester.pump(); await tester.pump();
...@@ -894,7 +825,7 @@ void main() { ...@@ -894,7 +825,7 @@ void main() {
testWidgets( testWidgets(
"don't do anything unless it can be overscrolled at the start of the list", "don't do anything unless it can be overscrolled at the start of the list",
(WidgetTester tester) async { (WidgetTester tester) async {
refreshIndicator = const Center(child: Text('-1')); mockHelper.refreshIndicator = const Center(child: Text('-1'));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -903,8 +834,8 @@ void main() { ...@@ -903,8 +834,8 @@ void main() {
slivers: <Widget>[ slivers: <Widget>[
buildAListOfStuff(), buildAListOfStuff(),
CupertinoSliverRefreshControl( // it's in the middle now. CupertinoSliverRefreshControl( // it's in the middle now.
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -916,13 +847,13 @@ void main() { ...@@ -916,13 +847,13 @@ void main() {
await tester.fling(find.byType(Container).first, const Offset(0.0, -200.0), 3000.0); await tester.fling(find.byType(Container).first, const Offset(0.0, -200.0), 3000.0);
verifyNoMoreInteractions(mockHelper); expect(mockHelper.invocations, isEmpty);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets( testWidgets(
'without an onRefresh, builder is called with arm for one frame then sliver goes away', 'without an onRefresh, builder is called with arm for one frame then sliver goes away',
(WidgetTester tester) async { (WidgetTester tester) async {
refreshIndicator = const Center(child: Text('-1')); mockHelper.refreshIndicator = const Center(child: Text('-1'));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -930,7 +861,7 @@ void main() { ...@@ -930,7 +861,7 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -940,21 +871,21 @@ void main() { ...@@ -940,21 +871,21 @@ void main() {
await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0.0); await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0.0);
await tester.pump(); await tester.pump();
verify(mockHelper.builder(
any, expect(mockHelper.invocations.first, matchesBuilder(
RefreshIndicatorMode.armed, refreshState: RefreshIndicatorMode.armed,
150.0, pulledExtent: 150.0,
100.0, // Default value. refreshTriggerPullDistance: 100.0, // Default value.
60.0, // Default value. refreshIndicatorExtent: 60.0, // Default value.
)); ));
await tester.pump(const Duration(milliseconds: 10)); await tester.pump(const Duration(milliseconds: 10));
verify(mockHelper.builder(
any, expect(mockHelper.invocations.last, matchesBuilder(
RefreshIndicatorMode.done, // Goes to done on the next frame. refreshState: RefreshIndicatorMode.done,
148.6463892921364, pulledExtent: moreOrLessEquals(148.6463892921364,),
100.0, // Default value. refreshTriggerPullDistance: 100.0, // Default value.
60.0, // Default value. refreshIndicatorExtent: 60.0, // Default value.
)); ));
await tester.pump(const Duration(seconds: 5)); await tester.pump(const Duration(seconds: 5));
...@@ -998,7 +929,7 @@ void main() { ...@@ -998,7 +929,7 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -1019,7 +950,7 @@ void main() { ...@@ -1019,7 +950,7 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -1050,7 +981,7 @@ void main() { ...@@ -1050,7 +981,7 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
refreshTriggerPullDistance: 80.0, refreshTriggerPullDistance: 80.0,
), ),
buildAListOfStuff(), buildAListOfStuff(),
...@@ -1084,8 +1015,8 @@ void main() { ...@@ -1084,8 +1015,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
refreshTriggerPullDistance: 90.0, refreshTriggerPullDistance: 90.0,
refreshIndicatorExtent: 50.0, refreshIndicatorExtent: 50.0,
), ),
...@@ -1124,8 +1055,8 @@ void main() { ...@@ -1124,8 +1055,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -1152,7 +1083,7 @@ void main() { ...@@ -1152,7 +1083,7 @@ void main() {
const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0), const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0),
); );
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
// The task completed between frames. The internal state goes to done // The task completed between frames. The internal state goes to done
// right away even though the sliver gets a new offset correction the // right away even though the sliver gets a new offset correction the
// next frame. // next frame.
...@@ -1171,8 +1102,8 @@ void main() { ...@@ -1171,8 +1102,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -1188,7 +1119,7 @@ void main() { ...@@ -1188,7 +1119,7 @@ void main() {
RefreshIndicatorMode.armed, RefreshIndicatorMode.armed,
); );
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
expect( expect(
CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))), CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
RefreshIndicatorMode.done, RefreshIndicatorMode.done,
...@@ -1229,8 +1160,8 @@ void main() { ...@@ -1229,8 +1160,8 @@ void main() {
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: builder, builder: mockHelper.builder,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
), ),
buildAListOfStuff(), buildAListOfStuff(),
], ],
...@@ -1259,7 +1190,7 @@ void main() { ...@@ -1259,7 +1190,7 @@ void main() {
RefreshIndicatorMode.refresh, RefreshIndicatorMode.refresh,
); );
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
// The sliver layout extent is removed on next frame. // The sliver layout extent is removed on next frame.
await tester.pump(); await tester.pump();
expect( expect(
...@@ -1282,7 +1213,7 @@ void main() { ...@@ -1282,7 +1213,7 @@ void main() {
testWidgets( testWidgets(
"don't have to build any indicators or occupy space during refresh", "don't have to build any indicators or occupy space during refresh",
(WidgetTester tester) async { (WidgetTester tester) async {
refreshIndicator = const Center(child: Text('-1')); mockHelper.refreshIndicator = const Center(child: Text('-1'));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -1291,7 +1222,7 @@ void main() { ...@@ -1291,7 +1222,7 @@ void main() {
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: null, builder: null,
onRefresh: onRefresh, onRefresh: mockHelper.refreshTask,
refreshIndicatorExtent: 0.0, refreshIndicatorExtent: 0.0,
), ),
buildAListOfStuff(), buildAListOfStuff(),
...@@ -1318,9 +1249,8 @@ void main() { ...@@ -1318,9 +1249,8 @@ void main() {
tester.getRect(find.widgetWithText(Center, '0')), tester.getRect(find.widgetWithText(Center, '0')),
const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0), const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
); );
verify(mockHelper.refreshTask()); // The refresh function still called.
refreshCompleter.complete(null); mockHelper.refreshCompleter.complete(null);
await tester.pump(); await tester.pump();
// Goes to inactive right away since the sliver is already collapsed. // Goes to inactive right away since the sliver is already collapsed.
expect( expect(
...@@ -1426,14 +1356,81 @@ void main() { ...@@ -1426,14 +1356,81 @@ void main() {
}); });
} }
class MockHelper extends Mock { class FakeBuilder {
Completer<void> refreshCompleter = Completer<void>.sync();
final List<MockHelperInvocation> invocations = <MockHelperInvocation>[];
Widget refreshIndicator = Container();
Widget builder( Widget builder(
BuildContext context, BuildContext context,
RefreshIndicatorMode refreshState, RefreshIndicatorMode refreshState,
double pulledExtent, double pulledExtent,
double refreshTriggerPullDistance, double refreshTriggerPullDistance,
double refreshIndicatorExtent, double refreshIndicatorExtent,
); ) {
if (pulledExtent < 0.0) {
throw TestFailure('The pulledExtent should never be less than 0.0');
}
if (refreshTriggerPullDistance < 0.0) {
throw TestFailure('The refreshTriggerPullDistance should never be less than 0.0');
}
if (refreshIndicatorExtent < 0.0) {
throw TestFailure('The refreshIndicatorExtent should never be less than 0.0');
}
invocations.add(
BuilderInvocation(
refreshState: refreshState,
pulledExtent: pulledExtent,
refreshTriggerPullDistance: refreshTriggerPullDistance,
refreshIndicatorExtent: refreshIndicatorExtent,
)
);
return refreshIndicator;
}
Future<void> refreshTask() {
invocations.add(const RefreshTaskInvocation());
return refreshCompleter.future;
}
}
abstract class MockHelperInvocation {
const MockHelperInvocation();
}
@immutable
class RefreshTaskInvocation extends MockHelperInvocation {
const RefreshTaskInvocation();
}
@immutable
class BuilderInvocation extends MockHelperInvocation {
const BuilderInvocation({
@required this.refreshState,
@required this.pulledExtent,
@required this.refreshIndicatorExtent,
@required this.refreshTriggerPullDistance,
});
final RefreshIndicatorMode refreshState;
final double pulledExtent;
final double refreshTriggerPullDistance;
final double refreshIndicatorExtent;
@override
String toString() => '{refreshState: $refreshState, pulledExtent: $pulledExtent, refreshTriggerPullDistance: $refreshTriggerPullDistance, refreshIndicatorExtent: $refreshIndicatorExtent}';
}
Future<void> refreshTask(); Matcher matchesBuilder({
@required RefreshIndicatorMode refreshState,
@required dynamic pulledExtent,
@required dynamic refreshTriggerPullDistance,
@required dynamic refreshIndicatorExtent,
}) {
return isA<BuilderInvocation>()
.having((BuilderInvocation invocation) => invocation.refreshState, 'refreshState', refreshState)
.having((BuilderInvocation invocation) => invocation.pulledExtent, 'pulledExtent', pulledExtent)
.having((BuilderInvocation invocation) => invocation.refreshTriggerPullDistance, 'refreshTriggerPullDistance', refreshTriggerPullDistance)
.having((BuilderInvocation invocation) => invocation.refreshIndicatorExtent, 'refreshIndicatorExtent', refreshIndicatorExtent);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment