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

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

283
  testWidgets('Route management - push, replace, popUntil', (WidgetTester tester) async {
284
    GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
285
    await tester.pumpWidget(new Navigator(
286 287 288 289
      key: navigatorKey,
      onGenerateRoute: (_) => new TestRoute('A')
    ));
    NavigatorState host = navigatorKey.currentState;
290
    await runNavigatorTest(
291 292
      tester,
      host,
293
      () { },
294
      <String>[
295 296 297 298 299
        'A: install',
        'A: didPush',
        'A: didChangeNext null',
      ]
    );
300
    await runNavigatorTest(
301 302
      tester,
      host,
303
      () { host.push(new TestRoute('B')); },
304
      <String>[
305 306 307 308 309 310 311
        'B: install',
        'B: didPush',
        'B: didChangeNext null',
        'A: didChangeNext B',
      ]
    );
    TestRoute routeC;
312
    await runNavigatorTest(
313 314
      tester,
      host,
315
      () { host.push(routeC = new TestRoute('C')); },
316
      <String>[
317 318 319 320 321 322 323
        'C: install',
        'C: didPush',
        'C: didChangeNext null',
        'B: didChangeNext C',
      ]
    );
    TestRoute routeB;
324
    await runNavigatorTest(
325 326
      tester,
      host,
327
      () { host.replaceRouteBelow(anchorRoute: routeC, newRoute: routeB = new TestRoute('b')); },
328
      <String>[
329 330 331 332 333 334 335
        'b: install',
        'b: didReplace B',
        'b: didChangeNext C',
        'A: didChangeNext b',
        'B: dispose',
      ]
    );
336
    await runNavigatorTest(
337 338
      tester,
      host,
Hans Muller's avatar
Hans Muller committed
339
      () { host.popUntil((Route<dynamic> route) => route == routeB); },
340
      <String>[
341 342 343 344 345
        'C: didPop null',
        'C: dispose',
        'b: didPopNext C',
      ]
    );
346
    await tester.pumpWidget(new Container());
347
    expect(results, equals(<String>['A: dispose', 'b: dispose']));
348 349
    expect(routes.isEmpty, isTrue);
    results.clear();
350
  });
Hans Muller's avatar
Hans Muller committed
351 352 353 354 355 356 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

  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>[
      ]
    );
  });
389
}