| // Copyright 2013 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 'dart:async'; |
| |
| import 'package:flutter/material.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| import 'package:go_router/go_router.dart'; |
| |
| class _GoRouteDataBuild extends GoRouteData { |
| const _GoRouteDataBuild(); |
| @override |
| Widget build(BuildContext context, GoRouterState state) => |
| const SizedBox(key: Key('build')); |
| } |
| |
| class _ShellRouteDataBuilder extends ShellRouteData { |
| const _ShellRouteDataBuilder(); |
| |
| @override |
| Widget builder( |
| BuildContext context, |
| GoRouterState state, |
| Widget navigator, |
| ) => |
| SizedBox( |
| key: const Key('builder'), |
| child: navigator, |
| ); |
| } |
| |
| class _ShellRouteDataWithKey extends ShellRouteData { |
| const _ShellRouteDataWithKey(this.key); |
| |
| final Key key; |
| |
| @override |
| Widget builder( |
| BuildContext context, |
| GoRouterState state, |
| Widget navigator, |
| ) => |
| SizedBox( |
| key: key, |
| child: navigator, |
| ); |
| } |
| |
| class _GoRouteDataBuildWithKey extends GoRouteData { |
| const _GoRouteDataBuildWithKey(this.key); |
| final Key key; |
| @override |
| Widget build(BuildContext context, GoRouterState state) => SizedBox(key: key); |
| } |
| |
| final GoRoute _goRouteDataBuild = GoRouteData.$route( |
| path: '/build', |
| factory: (GoRouterState state) => const _GoRouteDataBuild(), |
| ); |
| |
| final ShellRoute _shellRouteDataBuilder = ShellRouteData.$route( |
| factory: (GoRouterState state) => const _ShellRouteDataBuilder(), |
| routes: <RouteBase>[ |
| GoRouteData.$route( |
| path: '/child', |
| factory: (GoRouterState state) => const _GoRouteDataBuild(), |
| ), |
| ], |
| ); |
| |
| class _GoRouteDataBuildPage extends GoRouteData { |
| const _GoRouteDataBuildPage(); |
| @override |
| Page<void> buildPage(BuildContext context, GoRouterState state) => |
| const MaterialPage<void>( |
| child: SizedBox(key: Key('buildPage')), |
| ); |
| } |
| |
| class _ShellRouteDataPageBuilder extends ShellRouteData { |
| const _ShellRouteDataPageBuilder(); |
| |
| @override |
| Page<void> pageBuilder( |
| BuildContext context, |
| GoRouterState state, |
| Widget navigator, |
| ) => |
| MaterialPage<void>( |
| child: SizedBox( |
| key: const Key('page-builder'), |
| child: navigator, |
| ), |
| ); |
| } |
| |
| final GoRoute _goRouteDataBuildPage = GoRouteData.$route( |
| path: '/build-page', |
| factory: (GoRouterState state) => const _GoRouteDataBuildPage(), |
| ); |
| |
| final ShellRoute _shellRouteDataPageBuilder = ShellRouteData.$route( |
| factory: (GoRouterState state) => const _ShellRouteDataPageBuilder(), |
| routes: <RouteBase>[ |
| GoRouteData.$route( |
| path: '/child', |
| factory: (GoRouterState state) => const _GoRouteDataBuild(), |
| ), |
| ], |
| ); |
| |
| class _StatefulShellRouteDataBuilder extends StatefulShellRouteData { |
| const _StatefulShellRouteDataBuilder(); |
| |
| @override |
| Widget builder( |
| BuildContext context, |
| GoRouterState state, |
| StatefulNavigationShell navigator, |
| ) => |
| SizedBox( |
| key: const Key('builder'), |
| child: navigator, |
| ); |
| } |
| |
| final StatefulShellRoute _statefulShellRouteDataBuilder = |
| StatefulShellRouteData.$route( |
| factory: (GoRouterState state) => const _StatefulShellRouteDataBuilder(), |
| branches: <StatefulShellBranch>[ |
| StatefulShellBranchData.$branch( |
| routes: <RouteBase>[ |
| GoRouteData.$route( |
| path: '/child', |
| factory: (GoRouterState state) => const _GoRouteDataBuild(), |
| ), |
| ], |
| ), |
| ], |
| ); |
| |
| class _StatefulShellRouteDataPageBuilder extends StatefulShellRouteData { |
| const _StatefulShellRouteDataPageBuilder(); |
| |
| @override |
| Page<void> pageBuilder( |
| BuildContext context, |
| GoRouterState state, |
| StatefulNavigationShell navigator, |
| ) => |
| MaterialPage<void>( |
| child: SizedBox( |
| key: const Key('page-builder'), |
| child: navigator, |
| ), |
| ); |
| } |
| |
| final StatefulShellRoute _statefulShellRouteDataPageBuilder = |
| StatefulShellRouteData.$route( |
| factory: (GoRouterState state) => const _StatefulShellRouteDataPageBuilder(), |
| branches: <StatefulShellBranch>[ |
| StatefulShellBranchData.$branch( |
| routes: <RouteBase>[ |
| GoRouteData.$route( |
| path: '/child', |
| factory: (GoRouterState state) => const _GoRouteDataBuild(), |
| ), |
| ], |
| ), |
| ], |
| ); |
| |
| class _GoRouteDataRedirectPage extends GoRouteData { |
| const _GoRouteDataRedirectPage(); |
| @override |
| FutureOr<String> redirect(BuildContext context, GoRouterState state) => |
| '/build-page'; |
| } |
| |
| final GoRoute _goRouteDataRedirect = GoRouteData.$route( |
| path: '/redirect', |
| factory: (GoRouterState state) => const _GoRouteDataRedirectPage(), |
| ); |
| |
| final List<GoRoute> _routes = <GoRoute>[ |
| _goRouteDataBuild, |
| _goRouteDataBuildPage, |
| _goRouteDataRedirect, |
| ]; |
| |
| void main() { |
| group('GoRouteData', () { |
| testWidgets( |
| 'It should build the page from the overridden build method', |
| (WidgetTester tester) async { |
| final GoRouter goRouter = GoRouter( |
| initialLocation: '/build', |
| routes: _routes, |
| ); |
| await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter)); |
| expect(find.byKey(const Key('build')), findsOneWidget); |
| expect(find.byKey(const Key('buildPage')), findsNothing); |
| }, |
| ); |
| |
| testWidgets( |
| 'It should build the page from the overridden buildPage method', |
| (WidgetTester tester) async { |
| final GoRouter goRouter = GoRouter( |
| initialLocation: '/build-page', |
| routes: _routes, |
| ); |
| await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter)); |
| expect(find.byKey(const Key('build')), findsNothing); |
| expect(find.byKey(const Key('buildPage')), findsOneWidget); |
| }, |
| ); |
| }); |
| |
| group('ShellRouteData', () { |
| testWidgets( |
| 'It should build the page from the overridden build method', |
| (WidgetTester tester) async { |
| final GoRouter goRouter = GoRouter( |
| initialLocation: '/child', |
| routes: <RouteBase>[ |
| _shellRouteDataBuilder, |
| ], |
| ); |
| await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter)); |
| expect(find.byKey(const Key('builder')), findsOneWidget); |
| expect(find.byKey(const Key('page-builder')), findsNothing); |
| }, |
| ); |
| |
| testWidgets( |
| 'It should build the page from the overridden build method', |
| (WidgetTester tester) async { |
| final GlobalKey<NavigatorState> root = GlobalKey<NavigatorState>(); |
| final GlobalKey<NavigatorState> inner = GlobalKey<NavigatorState>(); |
| final GoRouter goRouter = GoRouter( |
| navigatorKey: root, |
| initialLocation: '/child/test', |
| routes: <RouteBase>[ |
| ShellRouteData.$route( |
| factory: (GoRouterState state) => |
| const _ShellRouteDataWithKey(Key('under-shell')), |
| routes: <RouteBase>[ |
| GoRouteData.$route( |
| path: '/child', |
| factory: (GoRouterState state) => |
| const _GoRouteDataBuildWithKey(Key('under')), |
| routes: <RouteBase>[ |
| ShellRouteData.$route( |
| factory: (GoRouterState state) => |
| const _ShellRouteDataWithKey(Key('above-shell')), |
| navigatorKey: inner, |
| parentNavigatorKey: root, |
| routes: <RouteBase>[ |
| GoRouteData.$route( |
| parentNavigatorKey: inner, |
| path: 'test', |
| factory: (GoRouterState state) => |
| const _GoRouteDataBuildWithKey(Key('above')), |
| ), |
| ], |
| ), |
| ]), |
| ], |
| ), |
| ], |
| ); |
| await tester.pumpWidget(MaterialApp.router( |
| routerConfig: goRouter, |
| )); |
| expect(find.byKey(const Key('under-shell')), findsNothing); |
| expect(find.byKey(const Key('under')), findsNothing); |
| |
| expect(find.byKey(const Key('above-shell')), findsOneWidget); |
| expect(find.byKey(const Key('above')), findsOneWidget); |
| |
| goRouter.pop(); |
| await tester.pumpAndSettle(); |
| |
| expect(find.byKey(const Key('under-shell')), findsOneWidget); |
| expect(find.byKey(const Key('under')), findsOneWidget); |
| |
| expect(find.byKey(const Key('above-shell')), findsNothing); |
| expect(find.byKey(const Key('above')), findsNothing); |
| }, |
| ); |
| |
| testWidgets( |
| 'It should build the page from the overridden buildPage method', |
| (WidgetTester tester) async { |
| final GoRouter goRouter = GoRouter( |
| initialLocation: '/child', |
| routes: <RouteBase>[ |
| _shellRouteDataPageBuilder, |
| ], |
| ); |
| await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter)); |
| expect(find.byKey(const Key('builder')), findsNothing); |
| expect(find.byKey(const Key('page-builder')), findsOneWidget); |
| }, |
| ); |
| }); |
| |
| group('StatefulShellRouteData', () { |
| testWidgets( |
| 'It should build the page from the overridden build method', |
| (WidgetTester tester) async { |
| final GoRouter goRouter = GoRouter( |
| initialLocation: '/child', |
| routes: <RouteBase>[ |
| _statefulShellRouteDataBuilder, |
| ], |
| ); |
| await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter)); |
| expect(find.byKey(const Key('builder')), findsOneWidget); |
| expect(find.byKey(const Key('page-builder')), findsNothing); |
| }, |
| ); |
| |
| testWidgets( |
| 'It should build the page from the overridden buildPage method', |
| (WidgetTester tester) async { |
| final GoRouter goRouter = GoRouter( |
| initialLocation: '/child', |
| routes: <RouteBase>[ |
| _statefulShellRouteDataPageBuilder, |
| ], |
| ); |
| await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter)); |
| expect(find.byKey(const Key('builder')), findsNothing); |
| expect(find.byKey(const Key('page-builder')), findsOneWidget); |
| }, |
| ); |
| |
| test('Can assign parent navigator key', () { |
| final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>(); |
| final StatefulShellRoute route = StatefulShellRouteData.$route( |
| parentNavigatorKey: key, |
| factory: (GoRouterState state) => |
| const _StatefulShellRouteDataPageBuilder(), |
| branches: <StatefulShellBranch>[ |
| StatefulShellBranchData.$branch( |
| routes: <RouteBase>[ |
| GoRouteData.$route( |
| path: '/child', |
| factory: (GoRouterState state) => const _GoRouteDataBuild(), |
| ), |
| ], |
| ), |
| ], |
| ); |
| expect(route.parentNavigatorKey, key); |
| }); |
| }); |
| |
| testWidgets( |
| 'It should redirect using the overridden redirect method', |
| (WidgetTester tester) async { |
| final GoRouter goRouter = GoRouter( |
| initialLocation: '/redirect', |
| routes: _routes, |
| ); |
| await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter)); |
| expect(find.byKey(const Key('build')), findsNothing); |
| expect(find.byKey(const Key('buildPage')), findsOneWidget); |
| }, |
| ); |
| |
| testWidgets( |
| 'It should redirect using the overridden redirect method', |
| (WidgetTester tester) async { |
| final GoRouter goRouter = GoRouter( |
| initialLocation: '/redirect-with-state', |
| routes: _routes, |
| ); |
| await tester.pumpWidget(MaterialApp.router(routerConfig: goRouter)); |
| expect(find.byKey(const Key('build')), findsNothing); |
| expect(find.byKey(const Key('buildPage')), findsNothing); |
| }, |
| ); |
| } |