blob: 8a7bd83ab6487d2b56f953b20c8e491feb3b8721 [file] [log] [blame]
// 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';
import 'test_helpers.dart';
void main() {
testWidgets('back button works synchronously', (WidgetTester tester) async {
bool allow = false;
final UniqueKey home = UniqueKey();
final UniqueKey page1 = UniqueKey();
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: home),
routes: <GoRoute>[
GoRoute(
path: '1',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page1),
onExit: (BuildContext context, GoRouterState state) {
return allow;
},
)
],
),
];
final GoRouter router =
await createRouter(routes, tester, initialLocation: '/1');
expect(find.byKey(page1), findsOneWidget);
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOneWidget);
allow = true;
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(home), findsOneWidget);
});
testWidgets('context.go works synchronously', (WidgetTester tester) async {
bool allow = false;
final UniqueKey home = UniqueKey();
final UniqueKey page1 = UniqueKey();
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: home),
),
GoRoute(
path: '/1',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page1),
onExit: (BuildContext context, GoRouterState state) {
return allow;
},
)
];
final GoRouter router =
await createRouter(routes, tester, initialLocation: '/1');
expect(find.byKey(page1), findsOneWidget);
router.go('/');
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOneWidget);
allow = true;
router.go('/');
await tester.pumpAndSettle();
expect(find.byKey(home), findsOneWidget);
});
testWidgets('back button works asynchronously', (WidgetTester tester) async {
Completer<bool> allow = Completer<bool>();
final UniqueKey home = UniqueKey();
final UniqueKey page1 = UniqueKey();
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: home),
routes: <GoRoute>[
GoRoute(
path: '1',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page1),
onExit: (BuildContext context, GoRouterState state) async {
return allow.future;
},
)
],
),
];
final GoRouter router =
await createRouter(routes, tester, initialLocation: '/1');
expect(find.byKey(page1), findsOneWidget);
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOneWidget);
allow.complete(false);
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOneWidget);
allow = Completer<bool>();
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOneWidget);
allow.complete(true);
await tester.pumpAndSettle();
expect(find.byKey(home), findsOneWidget);
});
testWidgets('context.go works asynchronously', (WidgetTester tester) async {
Completer<bool> allow = Completer<bool>();
final UniqueKey home = UniqueKey();
final UniqueKey page1 = UniqueKey();
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: home),
),
GoRoute(
path: '/1',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page1),
onExit: (BuildContext context, GoRouterState state) async {
return allow.future;
},
)
];
final GoRouter router =
await createRouter(routes, tester, initialLocation: '/1');
expect(find.byKey(page1), findsOneWidget);
router.go('/');
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOneWidget);
allow.complete(false);
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOneWidget);
allow = Completer<bool>();
router.go('/');
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOneWidget);
allow.complete(true);
await tester.pumpAndSettle();
expect(find.byKey(home), findsOneWidget);
});
testWidgets('android back button respects the last route.',
(WidgetTester tester) async {
bool allow = false;
final UniqueKey home = UniqueKey();
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: home),
onExit: (BuildContext context, GoRouterState state) {
return allow;
},
),
];
final GoRouter router = await createRouter(routes, tester);
expect(find.byKey(home), findsOneWidget);
// Not allow system pop.
expect(await router.routerDelegate.popRoute(), true);
allow = true;
expect(await router.routerDelegate.popRoute(), false);
});
testWidgets('android back button respects the last route. async',
(WidgetTester tester) async {
bool allow = false;
final UniqueKey home = UniqueKey();
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: home),
onExit: (BuildContext context, GoRouterState state) async {
return allow;
},
),
];
final GoRouter router = await createRouter(routes, tester);
expect(find.byKey(home), findsOneWidget);
// Not allow system pop.
expect(await router.routerDelegate.popRoute(), true);
allow = true;
expect(await router.routerDelegate.popRoute(), false);
});
testWidgets('android back button respects the last route with shell route.',
(WidgetTester tester) async {
bool allow = false;
final UniqueKey home = UniqueKey();
final List<RouteBase> routes = <RouteBase>[
ShellRoute(builder: (_, __, Widget child) => child, routes: <RouteBase>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: home),
onExit: (BuildContext context, GoRouterState state) {
return allow;
},
),
])
];
final GoRouter router = await createRouter(routes, tester);
expect(find.byKey(home), findsOneWidget);
// Not allow system pop.
expect(await router.routerDelegate.popRoute(), true);
allow = true;
expect(await router.routerDelegate.popRoute(), false);
});
testWidgets('It should provide the correct uri to the onExit callback',
(WidgetTester tester) async {
final UniqueKey home = UniqueKey();
final UniqueKey page1 = UniqueKey();
final UniqueKey page2 = UniqueKey();
final UniqueKey page3 = UniqueKey();
late final GoRouterState onExitState1;
late final GoRouterState onExitState2;
late final GoRouterState onExitState3;
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: home),
routes: <GoRoute>[
GoRoute(
path: '1',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page1),
onExit: (BuildContext context, GoRouterState state) {
onExitState1 = state;
return true;
},
routes: <GoRoute>[
GoRoute(
path: '2',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page2),
onExit: (BuildContext context, GoRouterState state) {
onExitState2 = state;
return true;
},
routes: <GoRoute>[
GoRoute(
path: '3',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page3),
onExit: (BuildContext context, GoRouterState state) {
onExitState3 = state;
return true;
},
)
],
)
],
)
],
),
];
final GoRouter router =
await createRouter(routes, tester, initialLocation: '/1/2/3');
expect(find.byKey(page3), findsOneWidget);
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(page2), findsOneWidget);
expect(onExitState3.uri.toString(), '/1/2/3');
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOneWidget);
expect(onExitState2.uri.toString(), '/1/2');
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(home), findsOneWidget);
expect(onExitState1.uri.toString(), '/1');
});
testWidgets(
'It should provide the correct path parameters to the onExit callback',
(WidgetTester tester) async {
final UniqueKey page0 = UniqueKey();
final UniqueKey page1 = UniqueKey();
final UniqueKey page2 = UniqueKey();
final UniqueKey page3 = UniqueKey();
late final GoRouterState onExitState1;
late final GoRouterState onExitState2;
late final GoRouterState onExitState3;
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/route-0/:id0',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page0),
),
GoRoute(
path: '/route-1/:id1',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page1),
onExit: (BuildContext context, GoRouterState state) {
onExitState1 = state;
return true;
},
),
GoRoute(
path: '/route-2/:id2',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page2),
onExit: (BuildContext context, GoRouterState state) {
onExitState2 = state;
return true;
},
),
GoRoute(
path: '/route-3/:id3',
builder: (BuildContext context, GoRouterState state) {
return DummyScreen(key: page3);
},
onExit: (BuildContext context, GoRouterState state) {
onExitState3 = state;
return true;
},
),
];
final GoRouter router = await createRouter(
routes,
tester,
initialLocation: '/route-0/0?param0=0',
);
unawaited(router.push('/route-1/1?param1=1'));
unawaited(router.push('/route-2/2?param2=2'));
unawaited(router.push('/route-3/3?param3=3'));
await tester.pumpAndSettle();
expect(find.byKey(page3), findsOne);
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(page2), findsOne);
expect(onExitState3.uri.toString(), '/route-3/3?param3=3');
expect(onExitState3.pathParameters, const <String, String>{'id3': '3'});
expect(onExitState3.fullPath, '/route-3/:id3');
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOne);
expect(onExitState2.uri.toString(), '/route-2/2?param2=2');
expect(onExitState2.pathParameters, const <String, String>{'id2': '2'});
expect(onExitState2.fullPath, '/route-2/:id2');
router.pop();
await tester.pumpAndSettle();
expect(find.byKey(page0), findsOne);
expect(onExitState1.uri.toString(), '/route-1/1?param1=1');
expect(onExitState1.pathParameters, const <String, String>{'id1': '1'});
expect(onExitState1.fullPath, '/route-1/:id1');
},
);
testWidgets(
'It should provide the correct path parameters to the onExit callback during a go',
(WidgetTester tester) async {
final UniqueKey page0 = UniqueKey();
final UniqueKey page1 = UniqueKey();
final UniqueKey page2 = UniqueKey();
final UniqueKey page3 = UniqueKey();
late final GoRouterState onExitState0;
late final GoRouterState onExitState1;
late final GoRouterState onExitState2;
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/route-0/:id0',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page0),
onExit: (BuildContext context, GoRouterState state) {
onExitState0 = state;
return true;
},
),
GoRoute(
path: '/route-1/:id1',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page1),
onExit: (BuildContext context, GoRouterState state) {
onExitState1 = state;
return true;
},
),
GoRoute(
path: '/route-2/:id2',
builder: (BuildContext context, GoRouterState state) =>
DummyScreen(key: page2),
onExit: (BuildContext context, GoRouterState state) {
onExitState2 = state;
return true;
},
),
GoRoute(
path: '/route-3/:id3',
builder: (BuildContext context, GoRouterState state) {
return DummyScreen(key: page3);
},
),
];
final GoRouter router = await createRouter(
routes,
tester,
initialLocation: '/route-0/0?param0=0',
);
expect(find.byKey(page0), findsOne);
router.go('/route-1/1?param1=1');
await tester.pumpAndSettle();
expect(find.byKey(page1), findsOne);
expect(onExitState0.uri.toString(), '/route-0/0?param0=0');
expect(onExitState0.pathParameters, const <String, String>{'id0': '0'});
expect(onExitState0.fullPath, '/route-0/:id0');
router.go('/route-2/2?param2=2');
await tester.pumpAndSettle();
expect(find.byKey(page2), findsOne);
expect(onExitState1.uri.toString(), '/route-1/1?param1=1');
expect(onExitState1.pathParameters, const <String, String>{'id1': '1'});
expect(onExitState1.fullPath, '/route-1/:id1');
router.go('/route-3/3?param3=3');
await tester.pumpAndSettle();
expect(find.byKey(page3), findsOne);
expect(onExitState2.uri.toString(), '/route-2/2?param2=2');
expect(onExitState2.pathParameters, const <String, String>{'id2': '2'});
expect(onExitState2.fullPath, '/route-2/:id2');
},
);
}