blob: a37f361259c2ce6e852eb2d5cbdcea40d9c8853e [file] [log] [blame]
// 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,
),
);
}
}