| // 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/cupertino.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| void main() { |
| testWidgets('Use home', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| builder: (BuildContext context) => const Text('home'), |
| ), |
| ), |
| ); |
| |
| expect(find.text('home'), findsOneWidget); |
| }); |
| |
| testWidgets('Use routes', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| routes: <String, WidgetBuilder>{ |
| '/': (BuildContext context) => const Text('first route'), |
| }, |
| ), |
| ), |
| ); |
| |
| expect(find.text('first route'), findsOneWidget); |
| }); |
| |
| testWidgets('Use home and named routes', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| builder: (BuildContext context) { |
| return CupertinoButton( |
| child: const Text('go to second page'), |
| onPressed: () { |
| Navigator.of(context).pushNamed('/2'); |
| }, |
| ); |
| }, |
| routes: <String, WidgetBuilder>{ |
| '/2': (BuildContext context) => const Text('second named route'), |
| }, |
| ), |
| ), |
| ); |
| |
| expect(find.text('go to second page'), findsOneWidget); |
| await tester.tap(find.text('go to second page')); |
| await tester.pump(); |
| await tester.pump(const Duration(milliseconds: 300)); |
| expect(find.text('second named route'), findsOneWidget); |
| }); |
| |
| testWidgets('Use onGenerateRoute', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| onGenerateRoute: (RouteSettings settings) { |
| if (settings.name == Navigator.defaultRouteName) { |
| return CupertinoPageRoute<void>( |
| settings: settings, |
| builder: (BuildContext context) { |
| return const Text('generated home'); |
| }, |
| ); |
| } |
| return null; |
| }, |
| ), |
| ), |
| ); |
| |
| expect(find.text('generated home'), findsOneWidget); |
| }); |
| |
| testWidgets('Use onUnknownRoute', (WidgetTester tester) async { |
| late String unknownForRouteCalled; |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| onUnknownRoute: (RouteSettings settings) { |
| unknownForRouteCalled = settings.name!; |
| return null; |
| }, |
| ), |
| ), |
| ); |
| |
| expect(tester.takeException(), isFlutterError); |
| expect(unknownForRouteCalled, '/'); |
| |
| // Work-around for https://github.com/flutter/flutter/issues/65655. |
| await tester.pumpWidget(Container()); |
| expect(tester.takeException(), isAssertionError); |
| }); |
| |
| testWidgets('Can use navigatorKey to navigate', (WidgetTester tester) async { |
| final GlobalKey<NavigatorState> key = GlobalKey(); |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| navigatorKey: key, |
| builder: (BuildContext context) => const Text('first route'), |
| routes: <String, WidgetBuilder>{ |
| '/2': (BuildContext context) => const Text('second route'), |
| }, |
| ), |
| ), |
| ); |
| |
| key.currentState!.pushNamed('/2'); |
| |
| await tester.pump(); |
| await tester.pump(const Duration(milliseconds: 300)); |
| expect(find.text('second route'), findsOneWidget); |
| }); |
| |
| testWidgets('Changing the key resets the navigator', (WidgetTester tester) async { |
| final GlobalKey<NavigatorState> key = GlobalKey(); |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| builder: (BuildContext context) { |
| return CupertinoButton( |
| child: const Text('go to second page'), |
| onPressed: () { |
| Navigator.of(context).pushNamed('/2'); |
| }, |
| ); |
| }, |
| routes: <String, WidgetBuilder>{ |
| '/2': (BuildContext context) => const Text('second route'), |
| }, |
| ), |
| ), |
| ); |
| |
| expect(find.text('go to second page'), findsOneWidget); |
| await tester.tap(find.text('go to second page')); |
| await tester.pump(); |
| await tester.pump(const Duration(milliseconds: 300)); |
| expect(find.text('second route'), findsOneWidget); |
| |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| key: key, |
| builder: (BuildContext context) { |
| return CupertinoButton( |
| child: const Text('go to second page'), |
| onPressed: () { |
| Navigator.of(context).pushNamed('/2'); |
| }, |
| ); |
| }, |
| routes: <String, WidgetBuilder>{ |
| '/2': (BuildContext context) => const Text('second route'), |
| }, |
| ), |
| ), |
| ); |
| |
| // The stack is gone and we're back to a re-built page 1. |
| expect(find.text('go to second page'), findsOneWidget); |
| expect(find.text('second route'), findsNothing); |
| }); |
| |
| testWidgets('Throws FlutterError when onUnknownRoute is null', (WidgetTester tester) async { |
| final GlobalKey<NavigatorState> key = GlobalKey(); |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| navigatorKey: key, |
| builder: (BuildContext context) => const Text('first route'), |
| ), |
| ), |
| ); |
| late FlutterError error; |
| try { |
| key.currentState!.pushNamed('/2'); |
| } on FlutterError catch (e) { |
| error = e; |
| } |
| expect(error, isNotNull); |
| expect( |
| error.toStringDeep(), |
| equalsIgnoringHashCodes( |
| 'FlutterError\n' |
| ' Could not find a generator for route RouteSettings("/2", null) in\n' |
| ' the _CupertinoTabViewState.\n' |
| ' Generators for routes are searched for in the following order:\n' |
| ' 1. For the "/" route, the "builder" property, if non-null, is\n' |
| ' used.\n' |
| ' 2. Otherwise, the "routes" table is used, if it has an entry for\n' |
| ' the route.\n' |
| ' 3. Otherwise, onGenerateRoute is called. It should return a\n' |
| ' non-null value for any valid route not handled by "builder" and\n' |
| ' "routes".\n' |
| ' 4. Finally if all else fails onUnknownRoute is called.\n' |
| ' Unfortunately, onUnknownRoute was not set.\n', |
| ), |
| ); |
| }); |
| |
| testWidgets('Throws FlutterError when onUnknownRoute returns null', (WidgetTester tester) async { |
| final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>(); |
| await tester.pumpWidget( |
| CupertinoApp( |
| home: CupertinoTabView( |
| navigatorKey: key, |
| builder: (BuildContext context) => const Text('first route'), |
| onUnknownRoute: (_) => null, |
| ), |
| ), |
| ); |
| late FlutterError error; |
| try { |
| key.currentState!.pushNamed('/2'); |
| } on FlutterError catch (e) { |
| error = e; |
| } |
| expect(error, isNotNull); |
| expect( |
| error.toStringDeep(), |
| equalsIgnoringHashCodes( |
| 'FlutterError\n' |
| ' The onUnknownRoute callback returned null.\n' |
| ' When the _CupertinoTabViewState requested the route\n' |
| ' RouteSettings("/2", null) from its onUnknownRoute callback, the\n' |
| ' callback returned null. Such callbacks must never return null.\n', |
| ), |
| ); |
| }); |
| |
| testWidgets('Navigator of CupertinoTabView restores state', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| CupertinoApp( |
| restorationScopeId: 'app', |
| home: CupertinoTabView( |
| restorationScopeId: 'tab', |
| builder: (BuildContext context) => CupertinoButton( |
| child: const Text('home'), |
| onPressed: () { |
| Navigator.of(context).restorablePushNamed('/2'); |
| }, |
| ), |
| routes: <String, WidgetBuilder>{ |
| '/2' : (BuildContext context) => const Text('second route'), |
| }, |
| ), |
| ), |
| ); |
| |
| expect(find.text('home'), findsOneWidget); |
| await tester.tap(find.text('home')); |
| await tester.pumpAndSettle(); |
| |
| expect(find.text('home'), findsNothing); |
| expect(find.text('second route'), findsOneWidget); |
| |
| final TestRestorationData data = await tester.getRestorationData(); |
| |
| await tester.restartAndRestore(); |
| |
| expect(find.text('home'), findsNothing); |
| expect(find.text('second route'), findsOneWidget); |
| |
| Navigator.of(tester.element(find.text('second route'))).pop(); |
| await tester.pumpAndSettle(); |
| |
| expect(find.text('home'), findsOneWidget); |
| expect(find.text('second route'), findsNothing); |
| |
| await tester.restoreFrom(data); |
| |
| expect(find.text('home'), findsNothing); |
| expect(find.text('second route'), findsOneWidget); |
| |
| Navigator.of(tester.element(find.text('second route'))).pop(); |
| await tester.pumpAndSettle(); |
| |
| expect(find.text('home'), findsOneWidget); |
| expect(find.text('second route'), findsNothing); |
| }); |
| } |