| // Copyright 2014 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/foundation.dart'; |
| import 'package:flutter/material.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| void main() { |
| testWidgets('Router state restoration without RouteInformationProvider', (WidgetTester tester) async { |
| final UniqueKey router = UniqueKey(); |
| _TestRouterDelegate delegate() => tester.widget<Router<Object?>>(find.byKey(router)).routerDelegate as _TestRouterDelegate; |
| |
| await tester.pumpWidget(_TestWidget(routerKey: router)); |
| expect(find.text('Current config: null'), findsOneWidget); |
| expect(delegate().newRoutePaths, isEmpty); |
| expect(delegate().restoredRoutePaths, isEmpty); |
| |
| delegate().currentConfiguration = '/foo'; |
| await tester.pumpAndSettle(); |
| expect(find.text('Current config: /foo'), findsOneWidget); |
| expect(delegate().newRoutePaths, isEmpty); |
| expect(delegate().restoredRoutePaths, isEmpty); |
| |
| await tester.restartAndRestore(); |
| expect(find.text('Current config: /foo'), findsOneWidget); |
| expect(delegate().newRoutePaths, isEmpty); |
| expect(delegate().restoredRoutePaths, <String>['/foo']); |
| |
| final TestRestorationData restorationData = await tester.getRestorationData(); |
| |
| delegate().currentConfiguration = '/bar'; |
| await tester.pumpAndSettle(); |
| expect(find.text('Current config: /bar'), findsOneWidget); |
| expect(delegate().newRoutePaths, isEmpty); |
| expect(delegate().restoredRoutePaths, <String>['/foo']); |
| |
| await tester.restoreFrom(restorationData); |
| expect(find.text('Current config: /foo'), findsOneWidget); |
| expect(delegate().newRoutePaths, isEmpty); |
| expect(delegate().restoredRoutePaths, <String>['/foo', '/foo']); |
| }); |
| |
| testWidgets('Router state restoration with RouteInformationProvider', (WidgetTester tester) async { |
| final UniqueKey router = UniqueKey(); |
| _TestRouterDelegate delegate() => tester.widget<Router<Object?>>(find.byKey(router)).routerDelegate as _TestRouterDelegate; |
| _TestRouteInformationProvider provider() => tester.widget<Router<Object?>>(find.byKey(router)).routeInformationProvider! as _TestRouteInformationProvider; |
| |
| await tester.pumpWidget(_TestWidget(routerKey: router, withInformationProvider: true)); |
| expect(find.text('Current config: /home'), findsOneWidget); |
| expect(delegate().newRoutePaths, <String>['/home']); |
| expect(delegate().restoredRoutePaths, isEmpty); |
| |
| provider().value = const RouteInformation(location: '/foo'); |
| await tester.pumpAndSettle(); |
| expect(find.text('Current config: /foo'), findsOneWidget); |
| expect(delegate().newRoutePaths, <String>['/home', '/foo']); |
| expect(delegate().restoredRoutePaths, isEmpty); |
| |
| await tester.restartAndRestore(); |
| expect(find.text('Current config: /foo'), findsOneWidget); |
| expect(delegate().newRoutePaths, isEmpty); |
| expect(delegate().restoredRoutePaths, <String>['/foo']); |
| |
| final TestRestorationData restorationData = await tester.getRestorationData(); |
| |
| provider().value = const RouteInformation(location: '/bar'); |
| await tester.pumpAndSettle(); |
| expect(find.text('Current config: /bar'), findsOneWidget); |
| expect(delegate().newRoutePaths, <String>['/bar']); |
| expect(delegate().restoredRoutePaths, <String>['/foo']); |
| |
| await tester.restoreFrom(restorationData); |
| expect(find.text('Current config: /foo'), findsOneWidget); |
| expect(delegate().newRoutePaths, <String>['/bar']); |
| expect(delegate().restoredRoutePaths, <String>['/foo', '/foo']); |
| }); |
| } |
| |
| class _TestRouteInformationParser extends RouteInformationParser<String> { |
| @override |
| Future<String> parseRouteInformation(RouteInformation routeInformation) { |
| return SynchronousFuture<String>(routeInformation.location!); |
| } |
| |
| @override |
| RouteInformation? restoreRouteInformation(String configuration) { |
| return RouteInformation(location: configuration); |
| } |
| } |
| |
| class _TestRouterDelegate extends RouterDelegate<String> with ChangeNotifier { |
| final List<String> newRoutePaths = <String>[]; |
| final List<String> restoredRoutePaths = <String>[]; |
| |
| @override |
| String? get currentConfiguration => _currentConfiguration; |
| String? _currentConfiguration; |
| set currentConfiguration(String? value) { |
| if (value == _currentConfiguration) { |
| return; |
| } |
| _currentConfiguration = value; |
| notifyListeners(); |
| } |
| |
| @override |
| Future<void> setNewRoutePath(String configuration) { |
| _currentConfiguration = configuration; |
| newRoutePaths.add(configuration); |
| return SynchronousFuture<void>(null); |
| } |
| |
| @override |
| Future<void> setRestoredRoutePath(String configuration) { |
| _currentConfiguration = configuration; |
| restoredRoutePaths.add(configuration); |
| return SynchronousFuture<void>(null); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return Text('Current config: $currentConfiguration', textDirection: TextDirection.ltr); |
| } |
| |
| @override |
| Future<bool> popRoute() async => throw UnimplementedError(); |
| } |
| |
| class _TestRouteInformationProvider extends RouteInformationProvider with ChangeNotifier { |
| @override |
| RouteInformation get value => _value; |
| RouteInformation _value = const RouteInformation(location: '/home'); |
| set value(RouteInformation value) { |
| if (value == _value) { |
| return; |
| } |
| _value = value; |
| notifyListeners(); |
| } |
| } |
| |
| class _TestWidget extends StatefulWidget { |
| const _TestWidget({Key? key, this.withInformationProvider = false, this.routerKey}) : super(key: key); |
| |
| final bool withInformationProvider; |
| final Key? routerKey; |
| |
| @override |
| State<_TestWidget> createState() => _TestWidgetState(); |
| } |
| |
| class _TestWidgetState extends State<_TestWidget> { |
| @override |
| Widget build(BuildContext context) { |
| return RootRestorationScope( |
| restorationId: 'root', |
| child: Router<String>( |
| key: widget.routerKey, |
| restorationScopeId: 'router', |
| routerDelegate: _TestRouterDelegate(), |
| routeInformationParser: _TestRouteInformationParser(), |
| routeInformationProvider: widget.withInformationProvider ? _TestRouteInformationProvider() : null, |
| ), |
| ); |
| } |
| } |