routes_test.dart 9.67 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
import 'dart:collection';

7 8
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
Adam Barth's avatar
Adam Barth committed
9
import 'package:meta/meta.dart';
10 11 12

final List<String> results = <String>[];

13
Set<TestRoute> routes = new HashSet<TestRoute>();
14

Hans Muller's avatar
Hans Muller committed
15
class TestRoute extends LocalHistoryRoute<String> {
16 17 18
  TestRoute(this.name);
  final String name;

19
  @override
20 21 22 23 24 25 26 27
  List<OverlayEntry> get overlayEntries => _entries;

  List<OverlayEntry> _entries = <OverlayEntry>[];

  void log(String s) {
    results.add('$name: $s');
  }

28
  @override
Hixie's avatar
Hixie committed
29
  void install(OverlayEntry insertionPoint) {
30 31 32 33 34 35
    log('install');
    OverlayEntry entry = new OverlayEntry(
      builder: (BuildContext context) => new Container(),
      opaque: true
    );
    _entries.add(entry);
Hixie's avatar
Hixie committed
36
    navigator.overlay?.insert(entry, above: insertionPoint);
37
    routes.add(this);
38
    super.install(insertionPoint);
39 40
  }

41
  @override
42 43
  void didPush() {
    log('didPush');
44
    super.didPush();
45 46
  }

47
  @override
Adam Barth's avatar
Adam Barth committed
48
  void didReplace(@checked TestRoute oldRoute) {
49
    log('didReplace ${oldRoute.name}');
50
    super.didReplace(oldRoute);
51 52
  }

53
  @override
54 55
  bool didPop(String result) {
    log('didPop $result');
56 57
    bool returnValue;
    if (returnValue = super.didPop(result))
58
      navigator.finalizeRoute(this);
59
    return returnValue;
60 61
  }

62
  @override
Adam Barth's avatar
Adam Barth committed
63
  void didPopNext(@checked TestRoute nextRoute) {
64
    log('didPopNext ${nextRoute.name}');
65
    super.didPopNext(nextRoute);
66 67
  }

68
  @override
Adam Barth's avatar
Adam Barth committed
69
  void didChangeNext(@checked TestRoute nextRoute) {
Hixie's avatar
Hixie committed
70
    log('didChangeNext ${nextRoute?.name}');
71
    super.didChangeNext(nextRoute);
72 73
  }

74
  @override
75 76 77 78
  void dispose() {
    log('dispose');
    _entries.forEach((OverlayEntry entry) { entry.remove(); });
    _entries.clear();
79
    routes.remove(this);
80
    super.dispose();
81 82 83 84
  }

}

85
Future<Null> runNavigatorTest(
86 87
  WidgetTester tester,
  NavigatorState host,
88
  VoidCallback test,
89
  List<String> expectations
90
) async {
91
  expect(host, isNotNull);
92
  test();
93 94
  expect(results, equals(expectations));
  results.clear();
95
  await tester.pump();
96 97 98
}

void main() {
99 100 101 102 103
  testWidgets('Route settings', (WidgetTester tester) async {
    RouteSettings settings = const RouteSettings(name: 'A');
    expect(settings, hasOneLineDescription);
  });

104
  testWidgets('Route management - push, replace, pop', (WidgetTester tester) async {
105
    GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
106
    await tester.pumpWidget(new Navigator(
107 108 109 110
      key: navigatorKey,
      onGenerateRoute: (_) => new TestRoute('initial')
    ));
    NavigatorState host = navigatorKey.currentState;
111
    await runNavigatorTest(
112 113
      tester,
      host,
114
      () { },
115
      <String>[
116 117 118 119 120 121
        'initial: install',
        'initial: didPush',
        'initial: didChangeNext null',
      ]
    );
    TestRoute second;
122
    await runNavigatorTest(
123 124
      tester,
      host,
125
      () { host.push(second = new TestRoute('second')); },
126
      <String>[
127 128 129 130 131 132
        'second: install',
        'second: didPush',
        'second: didChangeNext null',
        'initial: didChangeNext second',
      ]
    );
133
    await runNavigatorTest(
134 135
      tester,
      host,
136
      () { host.push(new TestRoute('third')); },
137
      <String>[
138 139 140 141 142 143
        'third: install',
        'third: didPush',
        'third: didChangeNext null',
        'second: didChangeNext third',
      ]
    );
144
    await runNavigatorTest(
145 146
      tester,
      host,
147
      () { host.replace(oldRoute: second, newRoute: new TestRoute('two')); },
148
      <String>[
149 150 151 152 153 154 155
        'two: install',
        'two: didReplace second',
        'two: didChangeNext third',
        'initial: didChangeNext two',
        'second: dispose',
      ]
    );
156
    await runNavigatorTest(
157 158
      tester,
      host,
159
      () { host.pop('hello'); },
160
      <String>[
161 162 163 164 165
        'third: didPop hello',
        'third: dispose',
        'two: didPopNext third',
      ]
    );
166
    await runNavigatorTest(
167 168
      tester,
      host,
169
      () { host.pop('good bye'); },
170
      <String>[
171 172 173 174 175
        'two: didPop good bye',
        'two: dispose',
        'initial: didPopNext two',
      ]
    );
176
    await tester.pumpWidget(new Container());
177
    expect(results, equals(<String>['initial: dispose']));
178 179
    expect(routes.isEmpty, isTrue);
    results.clear();
180 181
  });

182
  testWidgets('Route management - push, remove, pop', (WidgetTester tester) async {
183
    GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
184
    await tester.pumpWidget(new Navigator(
185 186 187 188
      key: navigatorKey,
      onGenerateRoute: (_) => new TestRoute('first')
    ));
    NavigatorState host = navigatorKey.currentState;
189
    await runNavigatorTest(
190 191
      tester,
      host,
192
      () { },
193
      <String>[
194 195 196 197 198 199
        'first: install',
        'first: didPush',
        'first: didChangeNext null',
      ]
    );
    TestRoute second;
200
    await runNavigatorTest(
201 202
      tester,
      host,
203
      () { host.push(second = new TestRoute('second')); },
204
      <String>[
205 206 207 208 209 210
        'second: install',
        'second: didPush',
        'second: didChangeNext null',
        'first: didChangeNext second',
      ]
    );
211
    await runNavigatorTest(
212 213
      tester,
      host,
214
      () { host.push(new TestRoute('third')); },
215
      <String>[
216 217 218 219 220 221
        'third: install',
        'third: didPush',
        'third: didChangeNext null',
        'second: didChangeNext third',
      ]
    );
222
    await runNavigatorTest(
223 224
      tester,
      host,
225
      () { host.removeRouteBelow(second); },
226
      <String>[
227 228 229
        'first: dispose',
      ]
    );
230
    await runNavigatorTest(
231 232
      tester,
      host,
233
      () { host.pop('good bye'); },
234
      <String>[
235 236 237 238 239
        'third: didPop good bye',
        'third: dispose',
        'second: didPopNext third',
      ]
    );
240
    await runNavigatorTest(
241 242
      tester,
      host,
243
      () { host.push(new TestRoute('three')); },
244
      <String>[
245 246 247 248 249 250 251
        'three: install',
        'three: didPush',
        'three: didChangeNext null',
        'second: didChangeNext three',
      ]
    );
    TestRoute four;
252
    await runNavigatorTest(
253 254
      tester,
      host,
255
      () { host.push(four = new TestRoute('four')); },
256
      <String>[
257 258 259 260 261 262
        'four: install',
        'four: didPush',
        'four: didChangeNext null',
        'three: didChangeNext four',
      ]
    );
263
    await runNavigatorTest(
264 265
      tester,
      host,
266
      () { host.removeRouteBelow(four); },
267
      <String>[
268 269 270 271
        'second: didChangeNext four',
        'three: dispose',
      ]
    );
272
    await runNavigatorTest(
273 274
      tester,
      host,
275
      () { host.pop('the end'); },
276
      <String>[
277 278 279 280 281
        'four: didPop the end',
        'four: dispose',
        'second: didPopNext four',
      ]
    );
282
    await tester.pumpWidget(new Container());
283
    expect(results, equals(<String>['second: dispose']));
284 285
    expect(routes.isEmpty, isTrue);
    results.clear();
286 287
  });

288
  testWidgets('Route management - push, replace, popUntil', (WidgetTester tester) async {
289
    GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
290
    await tester.pumpWidget(new Navigator(
291 292 293 294
      key: navigatorKey,
      onGenerateRoute: (_) => new TestRoute('A')
    ));
    NavigatorState host = navigatorKey.currentState;
295
    await runNavigatorTest(
296 297
      tester,
      host,
298
      () { },
299
      <String>[
300 301 302 303 304
        'A: install',
        'A: didPush',
        'A: didChangeNext null',
      ]
    );
305
    await runNavigatorTest(
306 307
      tester,
      host,
308
      () { host.push(new TestRoute('B')); },
309
      <String>[
310 311 312 313 314 315 316
        'B: install',
        'B: didPush',
        'B: didChangeNext null',
        'A: didChangeNext B',
      ]
    );
    TestRoute routeC;
317
    await runNavigatorTest(
318 319
      tester,
      host,
320
      () { host.push(routeC = new TestRoute('C')); },
321
      <String>[
322 323 324 325 326 327
        'C: install',
        'C: didPush',
        'C: didChangeNext null',
        'B: didChangeNext C',
      ]
    );
328
    expect(routeC.isActive, isTrue);
329
    TestRoute routeB;
330
    await runNavigatorTest(
331 332
      tester,
      host,
333
      () { host.replaceRouteBelow(anchorRoute: routeC, newRoute: routeB = new TestRoute('b')); },
334
      <String>[
335 336 337 338 339 340 341
        'b: install',
        'b: didReplace B',
        'b: didChangeNext C',
        'A: didChangeNext b',
        'B: dispose',
      ]
    );
342
    await runNavigatorTest(
343 344
      tester,
      host,
Hans Muller's avatar
Hans Muller committed
345
      () { host.popUntil((Route<dynamic> route) => route == routeB); },
346
      <String>[
347 348 349 350 351
        'C: didPop null',
        'C: dispose',
        'b: didPopNext C',
      ]
    );
352
    await tester.pumpWidget(new Container());
353
    expect(results, equals(<String>['A: dispose', 'b: dispose']));
354 355
    expect(routes.isEmpty, isTrue);
    results.clear();
356
  });
Hans Muller's avatar
Hans Muller committed
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394

  testWidgets('Route localHistory - popUntil', (WidgetTester tester) async {
    TestRoute routeA = new TestRoute('A');
    routeA.addLocalHistoryEntry(new LocalHistoryEntry(
      onRemove: () { routeA.log('onRemove 0'); }
    ));
    routeA.addLocalHistoryEntry(new LocalHistoryEntry(
      onRemove: () { routeA.log('onRemove 1'); }
    ));
    GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
    await tester.pumpWidget(new Navigator(
      key: navigatorKey,
      onGenerateRoute: (_) => routeA
    ));
    NavigatorState host = navigatorKey.currentState;
    await runNavigatorTest(
      tester,
      host,
      () { host.popUntil((Route<dynamic> route) => !route.willHandlePopInternally); },
      <String>[
        'A: install',
        'A: didPush',
        'A: didChangeNext null',
        'A: didPop null',
        'A: onRemove 1',
        'A: didPop null',
        'A: onRemove 0',
      ]
    );

    await runNavigatorTest(
      tester,
      host,
      () { host.popUntil((Route<dynamic> route) => !route.willHandlePopInternally); },
      <String>[
      ]
    );
  });
395
}