mirror of
https://github.com/flutter/flutter
synced 2024-10-13 03:32:55 +00:00
This reverts commit aee9e94c21
.
This commit is contained in:
parent
a1f6c173ba
commit
a206bf7e2f
File diff suppressed because it is too large
Load diff
|
@ -1708,6 +1708,666 @@ void main() {
|
|||
await tester.pump(const Duration(seconds: 1));
|
||||
expect(tickCount, 4);
|
||||
});
|
||||
|
||||
group('Page api', (){
|
||||
Widget buildNavigator(
|
||||
List<Page<dynamic>> pages,
|
||||
PopPageCallback onPopPage, [
|
||||
GlobalKey<NavigatorState> key,
|
||||
TransitionDelegate<dynamic> transitionDelegate
|
||||
]) {
|
||||
return MediaQuery(
|
||||
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window),
|
||||
child: Localizations(
|
||||
locale: const Locale('en', 'US'),
|
||||
delegates: const <LocalizationsDelegate<dynamic>>[
|
||||
DefaultMaterialLocalizations.delegate,
|
||||
DefaultWidgetsLocalizations.delegate
|
||||
],
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Navigator(
|
||||
key: key,
|
||||
pages: pages,
|
||||
onPopPage: onPopPage,
|
||||
transitionDelegate: transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('can initialize with pages list', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
final List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name:'initial'),
|
||||
const TestPage(key: ValueKey<String>('2'), name:'second'),
|
||||
const TestPage(key: ValueKey<String>('3'), name:'third'),
|
||||
];
|
||||
|
||||
bool onPopPage(Route<dynamic> route, dynamic result) {
|
||||
myPages.removeWhere((Page<dynamic> page) => route.settings == page);
|
||||
return route.didPop(result);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
expect(find.text('third'), findsOneWidget);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('initial'), findsNothing);
|
||||
|
||||
navigator.currentState.pop();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('third'), findsNothing);
|
||||
expect(find.text('second'), findsOneWidget);
|
||||
expect(find.text('initial'), findsNothing);
|
||||
|
||||
navigator.currentState.pop();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('third'), findsNothing);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('initial'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('can push and pop pages using page api', (WidgetTester tester) async {
|
||||
Animation<double> secondaryAnimationOfRouteOne;
|
||||
Animation<double> primaryAnimationOfRouteOne;
|
||||
Animation<double> secondaryAnimationOfRouteTwo;
|
||||
Animation<double> primaryAnimationOfRouteTwo;
|
||||
Animation<double> secondaryAnimationOfRouteThree;
|
||||
Animation<double> primaryAnimationOfRouteThree;
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<Page<dynamic>> myPages = <Page<dynamic>>[
|
||||
CustomBuilderPage<void>(
|
||||
key: const ValueKey<String>('1'),
|
||||
name:'initial',
|
||||
routeBuilder: (BuildContext context, RouteSettings settings) {
|
||||
return PageRouteBuilder<void>(
|
||||
settings: settings,
|
||||
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
|
||||
secondaryAnimationOfRouteOne = secondaryAnimation;
|
||||
primaryAnimationOfRouteOne = animation;
|
||||
return const Text('initial');
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
bool onPopPage(Route<dynamic> route, dynamic result) {
|
||||
myPages.removeWhere((Page<dynamic> page) => route.settings == page);
|
||||
return route.didPop(result);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
expect(find.text('initial'), findsOneWidget);
|
||||
|
||||
myPages = <Page<dynamic>>[
|
||||
CustomBuilderPage<void>(
|
||||
key: const ValueKey<String>('1'),
|
||||
name:'initial',
|
||||
routeBuilder: (BuildContext context, RouteSettings settings) {
|
||||
return PageRouteBuilder<void>(
|
||||
settings: settings,
|
||||
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
|
||||
secondaryAnimationOfRouteOne = secondaryAnimation;
|
||||
primaryAnimationOfRouteOne = animation;
|
||||
return const Text('initial');
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
CustomBuilderPage<void>(
|
||||
key: const ValueKey<String>('2'),
|
||||
name:'second',
|
||||
routeBuilder: (BuildContext context, RouteSettings settings) {
|
||||
return PageRouteBuilder<void>(
|
||||
settings: settings,
|
||||
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
|
||||
secondaryAnimationOfRouteTwo = secondaryAnimation;
|
||||
primaryAnimationOfRouteTwo = animation;
|
||||
return const Text('second');
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
CustomBuilderPage<void>(
|
||||
key: const ValueKey<String>('3'),
|
||||
name:'third',
|
||||
routeBuilder: (BuildContext context, RouteSettings settings) {
|
||||
return PageRouteBuilder<void>(
|
||||
settings: settings,
|
||||
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
|
||||
secondaryAnimationOfRouteThree = secondaryAnimation;
|
||||
primaryAnimationOfRouteThree = animation;
|
||||
return const Text('third');
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
];
|
||||
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
// The third page is transitioning, and the secondary animation of first
|
||||
// page should chain with the third page. The animation of second page
|
||||
// won't start until the third page finishes transition.
|
||||
expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteThree.value);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.dismissed);
|
||||
expect(secondaryAnimationOfRouteThree.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.forward);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 30));
|
||||
expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteThree.value);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.dismissed);
|
||||
expect(secondaryAnimationOfRouteThree.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteThree.value, 0.1);
|
||||
await tester.pumpAndSettle();
|
||||
// After transition finishes, the routes' animations are correctly chained.
|
||||
expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.value, primaryAnimationOfRouteThree.value);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteThree.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.completed);
|
||||
expect(find.text('third'), findsOneWidget);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('initial'), findsNothing);
|
||||
// Starts pops the pages using page api and verify the animations chain
|
||||
// correctly.
|
||||
|
||||
myPages = <Page<dynamic>>[
|
||||
CustomBuilderPage<void>(
|
||||
key: const ValueKey<String>('1'),
|
||||
name:'initial',
|
||||
routeBuilder: (BuildContext context, RouteSettings settings) {
|
||||
return PageRouteBuilder<void>(
|
||||
settings: settings,
|
||||
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
|
||||
secondaryAnimationOfRouteOne = secondaryAnimation;
|
||||
primaryAnimationOfRouteOne = animation;
|
||||
return const Text('initial');
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
CustomBuilderPage<void>(
|
||||
key: const ValueKey<String>('2'),
|
||||
name:'second',
|
||||
routeBuilder: (BuildContext context, RouteSettings settings) {
|
||||
return PageRouteBuilder<void>(
|
||||
settings: settings,
|
||||
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
|
||||
secondaryAnimationOfRouteTwo = secondaryAnimation;
|
||||
primaryAnimationOfRouteTwo = animation;
|
||||
return const Text('second');
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
await tester.pump(const Duration(milliseconds: 30));
|
||||
expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.value, primaryAnimationOfRouteThree.value);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteThree.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteThree.value, 0.9);
|
||||
await tester.pumpAndSettle();
|
||||
expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.value, primaryAnimationOfRouteThree.value);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteThree.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.dismissed);
|
||||
});
|
||||
|
||||
testWidgets('can modify routes history and secondary animation still works', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
Animation<double> secondaryAnimationOfRouteOne;
|
||||
Animation<double> primaryAnimationOfRouteOne;
|
||||
Animation<double> secondaryAnimationOfRouteTwo;
|
||||
Animation<double> primaryAnimationOfRouteTwo;
|
||||
Animation<double> secondaryAnimationOfRouteThree;
|
||||
Animation<double> primaryAnimationOfRouteThree;
|
||||
List<Page<dynamic>> myPages = <CustomBuilderPage<void>>[
|
||||
CustomBuilderPage<void>(
|
||||
key: const ValueKey<String>('1'),
|
||||
name:'initial',
|
||||
routeBuilder: (BuildContext context, RouteSettings settings) {
|
||||
return PageRouteBuilder<void>(
|
||||
settings: settings,
|
||||
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
|
||||
secondaryAnimationOfRouteOne = secondaryAnimation;
|
||||
primaryAnimationOfRouteOne = animation;
|
||||
return const Text('initial');
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
CustomBuilderPage<void>(
|
||||
key: const ValueKey<String>('2'),
|
||||
name:'second',
|
||||
routeBuilder: (BuildContext context, RouteSettings settings) {
|
||||
return PageRouteBuilder<void>(
|
||||
settings: settings,
|
||||
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
|
||||
secondaryAnimationOfRouteTwo = secondaryAnimation;
|
||||
primaryAnimationOfRouteTwo = animation;
|
||||
return const Text('second');
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
CustomBuilderPage<void>(
|
||||
key: const ValueKey<String>('3'),
|
||||
name:'third',
|
||||
routeBuilder: (BuildContext context, RouteSettings settings) {
|
||||
return PageRouteBuilder<void>(
|
||||
settings: settings,
|
||||
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
|
||||
secondaryAnimationOfRouteThree = secondaryAnimation;
|
||||
primaryAnimationOfRouteThree = animation;
|
||||
return const Text('third');
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
];
|
||||
bool onPopPage(Route<dynamic> route, dynamic result) {
|
||||
myPages.removeWhere((Page<dynamic> page) => route.settings == page);
|
||||
return route.didPop(result);
|
||||
}
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
expect(find.text('third'), findsOneWidget);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('initial'), findsNothing);
|
||||
expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.value, primaryAnimationOfRouteThree.value);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteThree.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.completed);
|
||||
|
||||
myPages = myPages.reversed.toList();
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
// Reversed routes are still chained up correctly.
|
||||
expect(secondaryAnimationOfRouteThree.value, primaryAnimationOfRouteTwo.value);
|
||||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.value, primaryAnimationOfRouteOne.value);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteOne.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.completed);
|
||||
|
||||
navigator.currentState.pop();
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 30));
|
||||
expect(secondaryAnimationOfRouteThree.value, primaryAnimationOfRouteTwo.value);
|
||||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.value, primaryAnimationOfRouteOne.value);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteOne.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteOne.value, 0.9);
|
||||
await tester.pumpAndSettle();
|
||||
expect(secondaryAnimationOfRouteThree.value, primaryAnimationOfRouteTwo.value);
|
||||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.value, primaryAnimationOfRouteOne.value);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteOne.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.dismissed);
|
||||
|
||||
navigator.currentState.pop();
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 30));
|
||||
expect(secondaryAnimationOfRouteThree.value, primaryAnimationOfRouteTwo.value);
|
||||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.value, primaryAnimationOfRouteOne.value);
|
||||
expect(primaryAnimationOfRouteTwo.value, 0.9);
|
||||
expect(secondaryAnimationOfRouteOne.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.dismissed);
|
||||
await tester.pumpAndSettle();
|
||||
expect(secondaryAnimationOfRouteThree.value, primaryAnimationOfRouteTwo.value);
|
||||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.completed);
|
||||
expect(secondaryAnimationOfRouteTwo.value, primaryAnimationOfRouteOne.value);
|
||||
expect(primaryAnimationOfRouteTwo.status, AnimationStatus.dismissed);
|
||||
expect(secondaryAnimationOfRouteOne.status, AnimationStatus.dismissed);
|
||||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.dismissed);
|
||||
});
|
||||
|
||||
testWidgets('can work with pageless route', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name:'initial'),
|
||||
const TestPage(key: ValueKey<String>('2'), name:'second'),
|
||||
];
|
||||
|
||||
bool onPopPage(Route<dynamic> route, dynamic result) {
|
||||
myPages.removeWhere((Page<dynamic> page) => route.settings == page);
|
||||
return route.didPop(result);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
expect(find.text('second'), findsOneWidget);
|
||||
expect(find.text('initial'), findsNothing);
|
||||
// Pushes two pageless routes to second page route
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('second-pageless1'),
|
||||
settings: null,
|
||||
)
|
||||
);
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('second-pageless2'),
|
||||
settings: null,
|
||||
)
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
// Now the history should look like
|
||||
// [initial, second, second-pageless1, second-pageless2].
|
||||
expect(find.text('initial'), findsNothing);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('second-pageless1'), findsNothing);
|
||||
expect(find.text('second-pageless2'), findsOneWidget);
|
||||
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name:'initial'),
|
||||
const TestPage(key: ValueKey<String>('2'), name:'second'),
|
||||
const TestPage(key: ValueKey<String>('3'), name:'third'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('initial'), findsNothing);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('second-pageless1'), findsNothing);
|
||||
expect(find.text('second-pageless2'), findsNothing);
|
||||
expect(find.text('third'), findsOneWidget);
|
||||
|
||||
// Pushes one pageless routes to third page route
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('third-pageless1'),
|
||||
settings: null,
|
||||
)
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
// Now the history should look like
|
||||
// [initial, second, second-pageless1, second-pageless2, third, third-pageless1].
|
||||
expect(find.text('initial'), findsNothing);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('second-pageless1'), findsNothing);
|
||||
expect(find.text('second-pageless2'), findsNothing);
|
||||
expect(find.text('third'), findsNothing);
|
||||
expect(find.text('third-pageless1'), findsOneWidget);
|
||||
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name:'initial'),
|
||||
const TestPage(key: ValueKey<String>('3'), name:'third'),
|
||||
const TestPage(key: ValueKey<String>('2'), name:'second'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
// Swaps the order without any adding or removing should not trigger any
|
||||
// transition. The routes should update without a pumpAndSettle
|
||||
// Now the history should look like
|
||||
// [initial, third, third-pageless1, second, second-pageless1, second-pageless2].
|
||||
expect(find.text('initial'), findsNothing);
|
||||
expect(find.text('third'), findsNothing);
|
||||
expect(find.text('third-pageless1'), findsNothing);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('second-pageless1'), findsNothing);
|
||||
expect(find.text('second-pageless2'), findsOneWidget);
|
||||
// Pops the route one by one to make sure the order is correct.
|
||||
navigator.currentState.pop();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('initial'), findsNothing);
|
||||
expect(find.text('third'), findsNothing);
|
||||
expect(find.text('third-pageless1'), findsNothing);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('second-pageless1'), findsOneWidget);
|
||||
expect(find.text('second-pageless2'), findsNothing);
|
||||
expect(myPages.length, 3);
|
||||
navigator.currentState.pop();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('initial'), findsNothing);
|
||||
expect(find.text('third'), findsNothing);
|
||||
expect(find.text('third-pageless1'), findsNothing);
|
||||
expect(find.text('second'), findsOneWidget);
|
||||
expect(find.text('second-pageless1'), findsNothing);
|
||||
expect(find.text('second-pageless2'), findsNothing);
|
||||
expect(myPages.length, 3);
|
||||
navigator.currentState.pop();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('initial'), findsNothing);
|
||||
expect(find.text('third'), findsNothing);
|
||||
expect(find.text('third-pageless1'), findsOneWidget);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('second-pageless1'), findsNothing);
|
||||
expect(find.text('second-pageless2'), findsNothing);
|
||||
expect(myPages.length, 2);
|
||||
navigator.currentState.pop();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('initial'), findsNothing);
|
||||
expect(find.text('third'), findsOneWidget);
|
||||
expect(find.text('third-pageless1'), findsNothing);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('second-pageless1'), findsNothing);
|
||||
expect(find.text('second-pageless2'), findsNothing);
|
||||
expect(myPages.length, 2);
|
||||
navigator.currentState.pop();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('initial'), findsOneWidget);
|
||||
expect(find.text('third'), findsNothing);
|
||||
expect(find.text('third-pageless1'), findsNothing);
|
||||
expect(find.text('second'), findsNothing);
|
||||
expect(find.text('second-pageless1'), findsNothing);
|
||||
expect(find.text('second-pageless2'), findsNothing);
|
||||
expect(myPages.length, 1);
|
||||
});
|
||||
|
||||
testWidgets('complex case 1', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
];
|
||||
bool onPopPage(Route<dynamic> route, dynamic result) {
|
||||
myPages.removeWhere((Page<dynamic> page) => route.settings == page);
|
||||
return route.didPop(result);
|
||||
}
|
||||
|
||||
// Add initial page route with one pageless route.
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
bool initialPageless1Completed = false;
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('initial-pageless1'),
|
||||
settings: null,
|
||||
)
|
||||
).then((_) => initialPageless1Completed = true);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Pushes second page route with two pageless routes.
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
const TestPage(key: ValueKey<String>('2'), name: 'second'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
await tester.pumpAndSettle();
|
||||
bool secondPageless1Completed = false;
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('second-pageless1'),
|
||||
settings: null,
|
||||
)
|
||||
).then((_) => secondPageless1Completed = true);
|
||||
await tester.pumpAndSettle();
|
||||
bool secondPageless2Completed = false;
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('second-pageless2'),
|
||||
settings: null,
|
||||
)
|
||||
).then((_) => secondPageless2Completed = true);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Pushes third page route with one pageless route.
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
const TestPage(key: ValueKey<String>('2'), name: 'second'),
|
||||
const TestPage(key: ValueKey<String>('3'), name: 'third'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
await tester.pumpAndSettle();
|
||||
bool thirdPageless1Completed = false;
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('third-pageless1'),
|
||||
settings: null,
|
||||
)
|
||||
).then((_) => thirdPageless1Completed = true);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Nothing has been popped.
|
||||
expect(initialPageless1Completed, false);
|
||||
expect(secondPageless1Completed, false);
|
||||
expect(secondPageless2Completed, false);
|
||||
expect(thirdPageless1Completed, false);
|
||||
|
||||
// Switches order and removes the initial page route.
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('3'), name: 'third'),
|
||||
const TestPage(key: ValueKey<String>('2'), name: 'second'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
// The pageless route of initial page route should be completed.
|
||||
expect(initialPageless1Completed, true);
|
||||
expect(secondPageless1Completed, false);
|
||||
expect(secondPageless2Completed, false);
|
||||
expect(thirdPageless1Completed, false);
|
||||
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('3'), name: 'third'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
await tester.pumpAndSettle();
|
||||
expect(secondPageless1Completed, true);
|
||||
expect(secondPageless2Completed, true);
|
||||
expect(thirdPageless1Completed, false);
|
||||
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('4'), name: 'forth'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator));
|
||||
expect(thirdPageless1Completed, true);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('forth'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('complex case 1 - with always remove transition delegate', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
final AlwaysRemoveTransitionDelegate transitionDelegate = AlwaysRemoveTransitionDelegate();
|
||||
List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
];
|
||||
bool onPopPage(Route<dynamic> route, dynamic result) {
|
||||
myPages.removeWhere((Page<dynamic> page) => route.settings == page);
|
||||
return route.didPop(result);
|
||||
}
|
||||
|
||||
// Add initial page route with one pageless route.
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator, transitionDelegate));
|
||||
bool initialPageless1Completed = false;
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('initial-pageless1'),
|
||||
settings: null,
|
||||
)
|
||||
).then((_) => initialPageless1Completed = true);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Pushes second page route with two pageless routes.
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
const TestPage(key: ValueKey<String>('2'), name: 'second'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator, transitionDelegate));
|
||||
bool secondPageless1Completed = false;
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('second-pageless1'),
|
||||
settings: null,
|
||||
)
|
||||
).then((_) => secondPageless1Completed = true);
|
||||
await tester.pumpAndSettle();
|
||||
bool secondPageless2Completed = false;
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('second-pageless2'),
|
||||
settings: null,
|
||||
)
|
||||
).then((_) => secondPageless2Completed = true);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Pushes third page route with one pageless route.
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
const TestPage(key: ValueKey<String>('2'), name: 'second'),
|
||||
const TestPage(key: ValueKey<String>('3'), name: 'third'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator, transitionDelegate));
|
||||
bool thirdPageless1Completed = false;
|
||||
navigator.currentState.push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => const Text('third-pageless1'),
|
||||
settings: null,
|
||||
)
|
||||
).then((_) => thirdPageless1Completed = true);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Nothing has been popped.
|
||||
expect(initialPageless1Completed, false);
|
||||
expect(secondPageless1Completed, false);
|
||||
expect(secondPageless2Completed, false);
|
||||
expect(thirdPageless1Completed, false);
|
||||
|
||||
// Switches order and removes the initial page route.
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('3'), name: 'third'),
|
||||
const TestPage(key: ValueKey<String>('2'), name: 'second'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator, transitionDelegate));
|
||||
// The pageless route of initial page route should be removed without complete.
|
||||
expect(initialPageless1Completed, false);
|
||||
expect(secondPageless1Completed, false);
|
||||
expect(secondPageless2Completed, false);
|
||||
expect(thirdPageless1Completed, false);
|
||||
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('3'), name: 'third'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator, transitionDelegate));
|
||||
await tester.pumpAndSettle();
|
||||
expect(initialPageless1Completed, false);
|
||||
expect(secondPageless1Completed, false);
|
||||
expect(secondPageless2Completed, false);
|
||||
expect(thirdPageless1Completed, false);
|
||||
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('4'), name: 'forth'),
|
||||
];
|
||||
await tester.pumpWidget(buildNavigator(myPages, onPopPage, navigator, transitionDelegate));
|
||||
await tester.pump();
|
||||
expect(initialPageless1Completed, false);
|
||||
expect(secondPageless1Completed, false);
|
||||
expect(secondPageless2Completed, false);
|
||||
expect(thirdPageless1Completed, false);
|
||||
expect(find.text('forth'), findsOneWidget);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
class _TickingWidget extends StatefulWidget {
|
||||
|
@ -1742,6 +2402,62 @@ class _TickingWidgetState extends State<_TickingWidget> with SingleTickerProvide
|
|||
}
|
||||
}
|
||||
|
||||
class AlwaysRemoveTransitionDelegate extends TransitionDelegate<void> {
|
||||
@override
|
||||
Iterable<RouteTransitionRecord> resolve({
|
||||
List<RouteTransitionRecord> newPageRouteHistory,
|
||||
Map<RouteTransitionRecord, RouteTransitionRecord> locationToExitingPageRoute,
|
||||
Map<RouteTransitionRecord, List<RouteTransitionRecord>> pageRouteToPagelessRoutes,
|
||||
}) {
|
||||
final List<RouteTransitionRecord> results = <RouteTransitionRecord>[];
|
||||
void handleExitingRoute(RouteTransitionRecord location) {
|
||||
if (!locationToExitingPageRoute.containsKey(location))
|
||||
return;
|
||||
|
||||
final RouteTransitionRecord exitingPageRoute = locationToExitingPageRoute[location];
|
||||
final bool hasPagelessRoute = pageRouteToPagelessRoutes.containsKey(exitingPageRoute);
|
||||
|
||||
exitingPageRoute.markForRemove();
|
||||
results.add(exitingPageRoute);
|
||||
|
||||
if (hasPagelessRoute) {
|
||||
final List<RouteTransitionRecord> pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
|
||||
for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) {
|
||||
pagelessRoute.markForRemove();
|
||||
}
|
||||
}
|
||||
handleExitingRoute(exitingPageRoute);
|
||||
}
|
||||
handleExitingRoute(null);
|
||||
|
||||
for (final RouteTransitionRecord pageRoute in newPageRouteHistory) {
|
||||
if (pageRoute.isEntering) {
|
||||
pageRoute.markForAdd();
|
||||
}
|
||||
results.add(pageRoute);
|
||||
handleExitingRoute(pageRoute);
|
||||
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
class TestPage extends Page<void> {
|
||||
const TestPage({
|
||||
LocalKey key,
|
||||
String name,
|
||||
Object arguments,
|
||||
}) : super(key: key, name: name, arguments: arguments);
|
||||
|
||||
@override
|
||||
Route<void> createRoute(BuildContext context) {
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => Text(name),
|
||||
settings: this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NoAnimationPageRoute extends PageRouteBuilder<void> {
|
||||
NoAnimationPageRoute({WidgetBuilder pageBuilder})
|
||||
: super(pageBuilder: (BuildContext context, __, ___) {
|
||||
|
|
Loading…
Reference in a new issue