1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// 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,
),
);
}
}