blob: 59cee73feca26a87333bf98866199d40f785909c [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 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';
import 'package:go_router/src/configuration.dart';
import 'test_helpers.dart';
void main() {
group('GoRouterState from context', () {
testWidgets('works in builder', (WidgetTester tester) async {
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (BuildContext context, _) {
final GoRouterState state = GoRouterState.of(context);
return Text('/ ${state.queryParams['p']}');
}),
GoRoute(
path: '/a',
builder: (BuildContext context, _) {
final GoRouterState state = GoRouterState.of(context);
return Text('/a ${state.queryParams['p']}');
}),
];
final GoRouter router = await createRouter(routes, tester);
router.go('/?p=123');
await tester.pumpAndSettle();
expect(find.text('/ 123'), findsOneWidget);
router.go('/a?p=456');
await tester.pumpAndSettle();
expect(find.text('/a 456'), findsOneWidget);
});
testWidgets('works in subtree', (WidgetTester tester) async {
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (_, __) {
return Builder(builder: (BuildContext context) {
return Text('1 ${GoRouterState.of(context).location}');
});
},
routes: <GoRoute>[
GoRoute(
path: 'a',
builder: (_, __) {
return Builder(builder: (BuildContext context) {
return Text('2 ${GoRouterState.of(context).location}');
});
}),
]),
];
final GoRouter router = await createRouter(routes, tester);
router.go('/?p=123');
await tester.pumpAndSettle();
expect(find.text('1 /?p=123'), findsOneWidget);
router.go('/a');
await tester.pumpAndSettle();
expect(find.text('2 /a'), findsOneWidget);
// The query parameter is removed, so is the location in first page.
expect(find.text('1 /a', skipOffstage: false), findsOneWidget);
});
testWidgets('path parameter persists after page is popped',
(WidgetTester tester) async {
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (_, __) {
return Builder(builder: (BuildContext context) {
return Text('1 ${GoRouterState.of(context).location}');
});
},
routes: <GoRoute>[
GoRoute(
path: ':id',
builder: (_, __) {
return Builder(builder: (BuildContext context) {
return Text(
'2 ${GoRouterState.of(context).params['id']}');
});
}),
]),
];
final GoRouter router = await createRouter(routes, tester);
await tester.pumpAndSettle();
expect(find.text('1 /'), findsOneWidget);
router.go('/123');
await tester.pumpAndSettle();
expect(find.text('2 123'), findsOneWidget);
router.pop();
await tester.pump();
// Page 2 is in popping animation but should still be on screen with the
// correct path parameter.
expect(find.text('2 123'), findsOneWidget);
});
testWidgets('registry retains GoRouterState for exiting route',
(WidgetTester tester) async {
final UniqueKey key = UniqueKey();
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (_, __) {
return Builder(builder: (BuildContext context) {
return Text(GoRouterState.of(context).location);
});
},
routes: <GoRoute>[
GoRoute(
path: 'a',
builder: (_, __) {
return Builder(builder: (BuildContext context) {
return Text(key: key, GoRouterState.of(context).location);
});
}),
]),
];
final GoRouter router =
await createRouter(routes, tester, initialLocation: '/a?p=123');
expect(tester.widget<Text>(find.byKey(key)).data, '/a?p=123');
final GoRouterStateRegistry registry = tester
.widget<GoRouterStateRegistryScope>(
find.byType(GoRouterStateRegistryScope))
.notifier!;
expect(registry.registry.length, 2);
router.go('/');
await tester.pump();
expect(registry.registry.length, 2);
// should retain the same location even if the location has changed.
expect(tester.widget<Text>(find.byKey(key)).data, '/a?p=123');
// Finish the pop animation.
await tester.pumpAndSettle();
expect(registry.registry.length, 1);
expect(find.byKey(key), findsNothing);
});
testWidgets('imperative pop clears out registry',
(WidgetTester tester) async {
final UniqueKey key = UniqueKey();
final GlobalKey<NavigatorState> nav = GlobalKey<NavigatorState>();
final List<GoRoute> routes = <GoRoute>[
GoRoute(
path: '/',
builder: (_, __) {
return Builder(builder: (BuildContext context) {
return Text(GoRouterState.of(context).location);
});
},
routes: <GoRoute>[
GoRoute(
path: 'a',
builder: (_, __) {
return Builder(builder: (BuildContext context) {
return Text(key: key, GoRouterState.of(context).location);
});
}),
]),
];
await createRouter(routes, tester,
initialLocation: '/a?p=123', navigatorKey: nav);
expect(tester.widget<Text>(find.byKey(key)).data, '/a?p=123');
final GoRouterStateRegistry registry = tester
.widget<GoRouterStateRegistryScope>(
find.byType(GoRouterStateRegistryScope))
.notifier!;
expect(registry.registry.length, 2);
nav.currentState!.pop();
await tester.pump();
expect(registry.registry.length, 2);
// should retain the same location even if the location has changed.
expect(tester.widget<Text>(find.byKey(key)).data, '/a?p=123');
// Finish the pop animation.
await tester.pumpAndSettle();
expect(registry.registry.length, 1);
expect(find.byKey(key), findsNothing);
});
});
}