// 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. import 'dart:collection'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; final List<String> results = <String>[]; Set<TestRoute> routes = new HashSet<TestRoute>(); class TestRoute extends Route<String> { TestRoute(this.name); final String name; @override List<OverlayEntry> get overlayEntries => _entries; List<OverlayEntry> _entries = <OverlayEntry>[]; void log(String s) { results.add('$name: $s'); } @override void install(OverlayEntry insertionPoint) { log('install'); OverlayEntry entry = new OverlayEntry( builder: (BuildContext context) => new Container(), opaque: true ); _entries.add(entry); navigator.overlay?.insert(entry, above: insertionPoint); routes.add(this); } @override void didPush() { log('didPush'); } @override void didReplace(TestRoute oldRoute) { log('didReplace ${oldRoute.name}'); } @override bool didPop(String result) { log('didPop $result'); bool returnValue; if (returnValue = super.didPop(result)) dispose(); return returnValue; } @override void didPopNext(TestRoute nextRoute) { log('didPopNext ${nextRoute.name}'); } @override void didChangeNext(TestRoute nextRoute) { log('didChangeNext ${nextRoute?.name}'); } @override void dispose() { log('dispose'); _entries.forEach((OverlayEntry entry) { entry.remove(); }); _entries.clear(); routes.remove(this); } } void runNavigatorTest( WidgetTester tester, NavigatorState host, NavigatorTransactionCallback test, List<String> expectations ) { expect(host, isNotNull); host.openTransaction(test); expect(results, equals(expectations)); results.clear(); tester.pump(); } void main() { testWidgets('Route management - push, replace, pop', (WidgetTester tester) { GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>(); tester.pumpWidget(new Navigator( key: navigatorKey, onGenerateRoute: (_) => new TestRoute('initial') )); NavigatorState host = navigatorKey.currentState; runNavigatorTest( tester, host, (NavigatorTransaction transaction) { }, <String>[ 'initial: install', 'initial: didPush', 'initial: didChangeNext null', ] ); TestRoute second; runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.push(second = new TestRoute('second')); }, <String>[ 'second: install', 'second: didPush', 'second: didChangeNext null', 'initial: didChangeNext second', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.push(new TestRoute('third')); }, <String>[ 'third: install', 'third: didPush', 'third: didChangeNext null', 'second: didChangeNext third', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.replace(oldRoute: second, newRoute: new TestRoute('two')); }, <String>[ 'two: install', 'two: didReplace second', 'two: didChangeNext third', 'initial: didChangeNext two', 'second: dispose', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.pop('hello'); }, <String>[ 'third: didPop hello', 'third: dispose', 'two: didPopNext third', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.pop('good bye'); }, <String>[ 'two: didPop good bye', 'two: dispose', 'initial: didPopNext two', ] ); tester.pumpWidget(new Container()); expect(results, equals(<String>['initial: dispose'])); expect(routes.isEmpty, isTrue); results.clear(); }); testWidgets('Route management - push, remove, pop', (WidgetTester tester) { GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>(); tester.pumpWidget(new Navigator( key: navigatorKey, onGenerateRoute: (_) => new TestRoute('first') )); NavigatorState host = navigatorKey.currentState; runNavigatorTest( tester, host, (NavigatorTransaction transaction) { }, <String>[ 'first: install', 'first: didPush', 'first: didChangeNext null', ] ); TestRoute second; runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.push(second = new TestRoute('second')); }, <String>[ 'second: install', 'second: didPush', 'second: didChangeNext null', 'first: didChangeNext second', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.push(new TestRoute('third')); }, <String>[ 'third: install', 'third: didPush', 'third: didChangeNext null', 'second: didChangeNext third', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.removeRouteBefore(second); }, <String>[ 'first: dispose', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.pop('good bye'); }, <String>[ 'third: didPop good bye', 'third: dispose', 'second: didPopNext third', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.push(new TestRoute('three')); }, <String>[ 'three: install', 'three: didPush', 'three: didChangeNext null', 'second: didChangeNext three', ] ); TestRoute four; runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.push(four = new TestRoute('four')); }, <String>[ 'four: install', 'four: didPush', 'four: didChangeNext null', 'three: didChangeNext four', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.removeRouteBefore(four); }, <String>[ 'second: didChangeNext four', 'three: dispose', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.pop('the end'); }, <String>[ 'four: didPop the end', 'four: dispose', 'second: didPopNext four', ] ); tester.pumpWidget(new Container()); expect(results, equals(<String>['second: dispose'])); expect(routes.isEmpty, isTrue); results.clear(); }); testWidgets('Route management - push, replace, popUntil', (WidgetTester tester) { GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>(); tester.pumpWidget(new Navigator( key: navigatorKey, onGenerateRoute: (_) => new TestRoute('A') )); NavigatorState host = navigatorKey.currentState; runNavigatorTest( tester, host, (NavigatorTransaction transaction) { }, <String>[ 'A: install', 'A: didPush', 'A: didChangeNext null', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.push(new TestRoute('B')); }, <String>[ 'B: install', 'B: didPush', 'B: didChangeNext null', 'A: didChangeNext B', ] ); TestRoute routeC; runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.push(routeC = new TestRoute('C')); }, <String>[ 'C: install', 'C: didPush', 'C: didChangeNext null', 'B: didChangeNext C', ] ); TestRoute routeB; runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.replaceRouteBefore(anchorRoute: routeC, newRoute: routeB = new TestRoute('b')); }, <String>[ 'b: install', 'b: didReplace B', 'b: didChangeNext C', 'A: didChangeNext b', 'B: dispose', ] ); runNavigatorTest( tester, host, (NavigatorTransaction transaction) { transaction.popUntil(routeB); }, <String>[ 'C: didPop null', 'C: dispose', 'b: didPopNext C', ] ); tester.pumpWidget(new Container()); expect(results, equals(<String>['A: dispose', 'b: dispose'])); expect(routes.isEmpty, isTrue); results.clear(); }); }