routes_test.dart 9.22 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 9 10 11
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';

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

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

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

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

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

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

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

39
  @override
40 41 42 43
  void didPush() {
    log('didPush');
  }

44
  @override
45 46 47 48
  void didReplace(TestRoute oldRoute) {
    log('didReplace ${oldRoute.name}');
  }

49
  @override
50 51
  bool didPop(String result) {
    log('didPop $result');
52 53 54 55
    bool returnValue;
    if (returnValue = super.didPop(result))
      dispose();
    return returnValue;
56 57
  }

58
  @override
59 60 61 62
  void didPopNext(TestRoute nextRoute) {
    log('didPopNext ${nextRoute.name}');
  }

63
  @override
Hixie's avatar
Hixie committed
64 65
  void didChangeNext(TestRoute nextRoute) {
    log('didChangeNext ${nextRoute?.name}');
66 67
  }

68
  @override
69 70 71 72
  void dispose() {
    log('dispose');
    _entries.forEach((OverlayEntry entry) { entry.remove(); });
    _entries.clear();
73
    routes.remove(this);
74 75 76 77
  }

}

78
Future<Null> runNavigatorTest(
79 80
  WidgetTester tester,
  NavigatorState host,
81
  VoidCallback test,
82
  List<String> expectations
83
) async {
84
  expect(host, isNotNull);
85
  test();
86 87
  expect(results, equals(expectations));
  results.clear();
88
  await tester.pump();
89 90 91
}

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

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

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

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