From e71dbbf3d82137ad9e55f57501948a27ee77b531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Fri, 18 Feb 2022 23:10:47 -0300 Subject: [PATCH 01/12] test: adds `GoRouterHelper` tests --- go_router/test/go_router_test.dart | 247 ++++++++++++++++++++++++++++- 1 file changed, 246 insertions(+), 1 deletion(-) diff --git a/go_router/test/go_router_test.dart b/go_router/test/go_router_test.dart index 98f7c4d6..eb52c9db 100644 --- a/go_router/test/go_router_test.dart +++ b/go_router/test/go_router_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/src/foundation/diagnostics.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:go_router/go_router.dart'; import 'package:go_router/src/go_route_match.dart'; @@ -1396,6 +1395,240 @@ void main() { }); }); }); + + group('GoRouterHelper', () { + final key = GlobalKey<_DummyStatefulWidgetState>(); + final routes = [ + GoRoute( + path: '/', + name: 'home', + builder: (context, state) => DummyStatefulWidget(key: key), + ), + GoRoute( + path: '/page1', + name: 'page1', + builder: (context, state) => const Page1Screen(), + ), + ]; + + const name = 'page1'; + final params = { + 'a-param-key': 'a-param-value', + }; + final queryParams = {'a-query-key': 'a-query-value'}; + const location = '/page1'; + const extra = 'Hello'; + + testWidgets('calls `namedLocation` on closest GoRouter ', (tester) async { + final router = GoRouterNamedLocationSpy(routes: routes); + await tester.pumpWidget( + MaterialApp.router( + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + key.currentContext!.namedLocation( + name, + params: params, + queryParams: queryParams, + ); + expect(router.name, router.name); + expect(router.params, params); + expect(router.queryParams, queryParams); + }); + + testWidgets('calls `go` on closest GoRouter ', (tester) async { + final router = GoRouterGoSpy(routes: routes); + await tester.pumpWidget( + MaterialApp.router( + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + key.currentContext!.go( + location, + extra: extra, + ); + expect(router.myLocation, location); + expect(router.extra, extra); + }); + + testWidgets('calls `goNamed` on closest GoRouter ', (tester) async { + final router = GoRouterGoNamedSpy(routes: routes); + await tester.pumpWidget( + MaterialApp.router( + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + key.currentContext!.goNamed( + name, + params: params, + queryParams: queryParams, + extra: extra, + ); + expect(router.name, name); + expect(router.params, params); + expect(router.queryParams, queryParams); + expect(router.extra, extra); + }); + + testWidgets('calls `push` on closest GoRouter ', (tester) async { + final router = GoRouterPushSpy(routes: routes); + await tester.pumpWidget( + MaterialApp.router( + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + key.currentContext!.push( + location, + extra: extra, + ); + expect(router.myLocation, location); + expect(router.extra, extra); + }); + + testWidgets('calls `pushNamed` on closest GoRouter ', (tester) async { + final router = GoRouterPushNamedSpy(routes: routes); + await tester.pumpWidget( + MaterialApp.router( + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + key.currentContext!.pushNamed( + name, + params: params, + queryParams: queryParams, + extra: extra, + ); + expect(router.name, name); + expect(router.params, params); + expect(router.queryParams, queryParams); + expect(router.extra, extra); + }); + + testWidgets('calls `pop` on closest GoRouter ', (tester) async { + final router = GoRouterPopSpy(routes: routes); + await tester.pumpWidget( + MaterialApp.router( + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + key.currentContext!.pop(); + expect(router.popped, true); + }); + }); +} + +class GoRouterNamedLocationSpy extends GoRouter { + GoRouterNamedLocationSpy({required List routes}) + : super(routes: routes); + + String? name; + Map? params; + Map? queryParams; + + @override + String namedLocation( + String name, { + Map params = const {}, + Map queryParams = const {}, + }) { + this.name = name; + this.params = params; + this.queryParams = queryParams; + return ''; + } +} + +class GoRouterGoSpy extends GoRouter { + GoRouterGoSpy({required List routes}) : super(routes: routes); + + String? myLocation; + Object? extra; + + @override + void go(String location, {Object? extra}) { + myLocation = location; + this.extra = extra; + } +} + +class GoRouterGoNamedSpy extends GoRouter { + GoRouterGoNamedSpy({required List routes}) : super(routes: routes); + + String? name; + Map? params; + Map? queryParams; + Object? extra; + + @override + void goNamed( + String name, { + Map params = const {}, + Map queryParams = const {}, + Object? extra, + }) { + this.name = name; + this.params = params; + this.queryParams = queryParams; + this.extra = extra; + } +} + +class GoRouterPushSpy extends GoRouter { + GoRouterPushSpy({required List routes}) : super(routes: routes); + + String? myLocation; + Object? extra; + + @override + void push(String location, {Object? extra}) { + myLocation = location; + this.extra = extra; + } +} + +class GoRouterPushNamedSpy extends GoRouter { + GoRouterPushNamedSpy({required List routes}) : super(routes: routes); + + String? name; + Map? params; + Map? queryParams; + Object? extra; + + @override + void pushNamed( + String name, { + Map params = const {}, + Map queryParams = const {}, + Object? extra, + }) { + this.name = name; + this.params = params; + this.queryParams = queryParams; + this.extra = extra; + } +} + +class GoRouterPopSpy extends GoRouter { + GoRouterPopSpy({required List routes}) : super(routes: routes); + + bool popped = false; + + @override + void pop() { + popped = true; + } } class MockGoRouterRefreshStream extends GoRouterRefreshStream { @@ -1563,3 +1796,15 @@ class DummyBuildContext implements BuildContext { @override Widget get widget => throw UnimplementedError(); } + +class DummyStatefulWidget extends StatefulWidget { + const DummyStatefulWidget({Key? key}) : super(key: key); + + @override + State createState() => _DummyStatefulWidgetState(); +} + +class _DummyStatefulWidgetState extends State { + @override + Widget build(BuildContext context) => Container(); +} From 1f282e7cb16841e7b2803ec86da23f171d44a12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Fri, 18 Feb 2022 23:25:55 -0300 Subject: [PATCH 02/12] test: adds `InheritedGoRouter` tests --- .../test/src/inherited_go_router_test.dart | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 go_router/test/src/inherited_go_router_test.dart diff --git a/go_router/test/src/inherited_go_router_test.dart b/go_router/test/src/inherited_go_router_test.dart new file mode 100644 index 00000000..d0d44fea --- /dev/null +++ b/go_router/test/src/inherited_go_router_test.dart @@ -0,0 +1,68 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; +import 'package:go_router/src/inherited_go_router.dart'; + +void main() { + test('does not update on changes', () { + final oldGoRouter = GoRouter(routes: [ + GoRoute( + path: '/', + builder: (context, state) => const Page1(), + ), + ]); + final newGoRouter = GoRouter(routes: [ + GoRoute( + path: '/', + builder: (context, state) => const Page2(), + ), + ]); + final oldInheritedGoRouter = InheritedGoRouter( + goRouter: oldGoRouter, + child: Container(), + ); + final newInheritedGoRouter = InheritedGoRouter( + goRouter: newGoRouter, + child: Container(), + ); + final shouldNotify = newInheritedGoRouter.updateShouldNotify( + oldInheritedGoRouter, + ); + expect(shouldNotify, false); + }); + + test('adds `goRouter` as a diagnostics property', () { + final goRouter = GoRouter( + routes: [ + GoRoute( + path: '/', + builder: (context, state) => const Page1(), + ), + ], + ); + final inheritedGoRouter = InheritedGoRouter( + goRouter: goRouter, + child: Container(), + ); + final properties = DiagnosticPropertiesBuilder(); + inheritedGoRouter.debugFillProperties(properties); + expect(properties.properties.length, 1); + expect(properties.properties.first, isA>()); + expect(properties.properties.first.value, goRouter); + }); +} + +class Page1 extends StatelessWidget { + const Page1({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) => Container(); +} + +class Page2 extends StatelessWidget { + const Page2({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) => Container(); +} From d1f42231b23edb2f11298ffd9edd787ce4c0f5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sat, 19 Feb 2022 00:14:21 -0300 Subject: [PATCH 03/12] test: adds cupertino related tests --- .../test/src/go_router_cupertino_test.dart | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 go_router/test/src/go_router_cupertino_test.dart diff --git a/go_router/test/src/go_router_cupertino_test.dart b/go_router/test/src/go_router_cupertino_test.dart new file mode 100644 index 00000000..9729a97a --- /dev/null +++ b/go_router/test/src/go_router_cupertino_test.dart @@ -0,0 +1,105 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; +import 'package:go_router/src/go_router_cupertino.dart'; + +void main() { + group('isCupertinoApp', () { + testWidgets('returns `true` when CupertinoApp is present', (tester) async { + final key = GlobalKey<_DummyStatefulWidgetState>(); + await tester.pumpWidget( + CupertinoApp( + home: DummyStatefulWidget(key: key), + ), + ); + final isCupertino = isCupertinoApp(key.currentContext! as Element); + expect(isCupertino, true); + }); + + testWidgets('returns `false` when MaterialApp is present', (tester) async { + final key = GlobalKey<_DummyStatefulWidgetState>(); + await tester.pumpWidget( + MaterialApp( + home: DummyStatefulWidget(key: key), + ), + ); + final isCupertino = isCupertinoApp(key.currentContext! as Element); + expect(isCupertino, false); + }); + }); + + test('pageBuilderForCupertinoApp creates a `CupertinoPage` accordingly', () { + final key = UniqueKey(); + const name = 'name'; + const arguments = 'arguments'; + const restorationId = 'restorationId'; + const child = DummyStatefulWidget(); + final page = pageBuilderForCupertinoApp( + key: key, + name: name, + arguments: arguments, + restorationId: restorationId, + child: child, + ); + expect(page.key, key); + expect(page.name, name); + expect(page.arguments, arguments); + expect(page.restorationId, restorationId); + expect(page.child, child); + }); + + group('GoRouterCupertinoErrorScreen', () { + testWidgets('shows "page not found" by default', (tester) async { + await tester.pumpWidget(const CupertinoApp( + home: GoRouterCupertinoErrorScreen(null), + )); + expect(find.text('page not found'), findsOneWidget); + }); + + testWidgets('shows the exception message when provided', (tester) async { + final error = Exception('Something went wrong!'); + await tester.pumpWidget(CupertinoApp( + home: GoRouterCupertinoErrorScreen(error), + )); + expect(find.text('$error'), findsOneWidget); + }); + + testWidgets('clicking the CupertinoButton should redirect to /', + (tester) async { + final router = GoRouter( + initialLocation: '/error', + routes: [ + GoRoute(path: '/', builder: (_, __) => const DummyStatefulWidget()), + GoRoute( + path: '/error', + builder: (_, __) => const GoRouterCupertinoErrorScreen(null), + ), + ], + ); + await tester.pumpWidget( + CupertinoApp.router( + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + final cupertinoButton = find.byType(CupertinoButton); + await tester.tap(cupertinoButton); + await tester.pumpAndSettle(); + expect(find.byType(DummyStatefulWidget), findsOneWidget); + }); + }); +} + +class DummyStatefulWidget extends StatefulWidget { + const DummyStatefulWidget({Key? key}) : super(key: key); + + @override + State createState() => _DummyStatefulWidgetState(); +} + +class _DummyStatefulWidgetState extends State { + @override + Widget build(BuildContext context) => Container(); +} From 2831e76d85c8f3bd3f0982bc17be3a0acfae92ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sat, 19 Feb 2022 10:27:07 -0300 Subject: [PATCH 04/12] fix: switches from backticks to square brackets Because vscode test runner doesn't like it. xD --- go_router/test/go_router_test.dart | 12 ++++++------ go_router/test/src/go_router_cupertino_test.dart | 6 +++--- go_router/test/src/inherited_go_router_test.dart | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go_router/test/go_router_test.dart b/go_router/test/go_router_test.dart index eb52c9db..5b9ddc89 100644 --- a/go_router/test/go_router_test.dart +++ b/go_router/test/go_router_test.dart @@ -1419,7 +1419,7 @@ void main() { const location = '/page1'; const extra = 'Hello'; - testWidgets('calls `namedLocation` on closest GoRouter ', (tester) async { + testWidgets('calls [namedLocation] on closest GoRouter', (tester) async { final router = GoRouterNamedLocationSpy(routes: routes); await tester.pumpWidget( MaterialApp.router( @@ -1438,7 +1438,7 @@ void main() { expect(router.queryParams, queryParams); }); - testWidgets('calls `go` on closest GoRouter ', (tester) async { + testWidgets('calls [go] on closest GoRouter', (tester) async { final router = GoRouterGoSpy(routes: routes); await tester.pumpWidget( MaterialApp.router( @@ -1455,7 +1455,7 @@ void main() { expect(router.extra, extra); }); - testWidgets('calls `goNamed` on closest GoRouter ', (tester) async { + testWidgets('calls [goNamed] on closest GoRouter', (tester) async { final router = GoRouterGoNamedSpy(routes: routes); await tester.pumpWidget( MaterialApp.router( @@ -1476,7 +1476,7 @@ void main() { expect(router.extra, extra); }); - testWidgets('calls `push` on closest GoRouter ', (tester) async { + testWidgets('calls [push] on closest GoRouter', (tester) async { final router = GoRouterPushSpy(routes: routes); await tester.pumpWidget( MaterialApp.router( @@ -1493,7 +1493,7 @@ void main() { expect(router.extra, extra); }); - testWidgets('calls `pushNamed` on closest GoRouter ', (tester) async { + testWidgets('calls [pushNamed] on closest GoRouter', (tester) async { final router = GoRouterPushNamedSpy(routes: routes); await tester.pumpWidget( MaterialApp.router( @@ -1514,7 +1514,7 @@ void main() { expect(router.extra, extra); }); - testWidgets('calls `pop` on closest GoRouter ', (tester) async { + testWidgets('calls [pop] on closest GoRouter', (tester) async { final router = GoRouterPopSpy(routes: routes); await tester.pumpWidget( MaterialApp.router( diff --git a/go_router/test/src/go_router_cupertino_test.dart b/go_router/test/src/go_router_cupertino_test.dart index 9729a97a..b5722003 100644 --- a/go_router/test/src/go_router_cupertino_test.dart +++ b/go_router/test/src/go_router_cupertino_test.dart @@ -6,7 +6,7 @@ import 'package:go_router/src/go_router_cupertino.dart'; void main() { group('isCupertinoApp', () { - testWidgets('returns `true` when CupertinoApp is present', (tester) async { + testWidgets('returns [true] when CupertinoApp is present', (tester) async { final key = GlobalKey<_DummyStatefulWidgetState>(); await tester.pumpWidget( CupertinoApp( @@ -17,7 +17,7 @@ void main() { expect(isCupertino, true); }); - testWidgets('returns `false` when MaterialApp is present', (tester) async { + testWidgets('returns [false] when MaterialApp is present', (tester) async { final key = GlobalKey<_DummyStatefulWidgetState>(); await tester.pumpWidget( MaterialApp( @@ -29,7 +29,7 @@ void main() { }); }); - test('pageBuilderForCupertinoApp creates a `CupertinoPage` accordingly', () { + test('pageBuilderForCupertinoApp creates a [CupertinoPage] accordingly', () { final key = UniqueKey(); const name = 'name'; const arguments = 'arguments'; diff --git a/go_router/test/src/inherited_go_router_test.dart b/go_router/test/src/inherited_go_router_test.dart index d0d44fea..aa1bcca1 100644 --- a/go_router/test/src/inherited_go_router_test.dart +++ b/go_router/test/src/inherited_go_router_test.dart @@ -32,7 +32,7 @@ void main() { expect(shouldNotify, false); }); - test('adds `goRouter` as a diagnostics property', () { + test('adds [goRouter] as a diagnostics property', () { final goRouter = GoRouter( routes: [ GoRoute( From d3f8188e3bd034550f44aa2403fa37e75b47a10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sat, 19 Feb 2022 10:57:45 -0300 Subject: [PATCH 05/12] test: adds material related tests --- .../test/src/go_router_material_test.dart | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 go_router/test/src/go_router_material_test.dart diff --git a/go_router/test/src/go_router_material_test.dart b/go_router/test/src/go_router_material_test.dart new file mode 100644 index 00000000..a4da3e9d --- /dev/null +++ b/go_router/test/src/go_router_material_test.dart @@ -0,0 +1,104 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; +import 'package:go_router/src/go_router_material.dart'; + +void main() { + group('isMaterialApp', () { + testWidgets('returns [true] when MaterialApp is present', (tester) async { + final key = GlobalKey<_DummyStatefulWidgetState>(); + await tester.pumpWidget( + MaterialApp( + home: DummyStatefulWidget(key: key), + ), + ); + final isMaterial = isMaterialApp(key.currentContext! as Element); + expect(isMaterial, true); + }); + + testWidgets('returns [false] when CupertinoApp is present', (tester) async { + final key = GlobalKey<_DummyStatefulWidgetState>(); + await tester.pumpWidget( + CupertinoApp( + home: DummyStatefulWidget(key: key), + ), + ); + final isMaterial = isMaterialApp(key.currentContext! as Element); + expect(isMaterial, false); + }); + }); + + test('pageBuilderForMaterialApp creates a [MaterialPage] accordingly', () { + final key = UniqueKey(); + const name = 'name'; + const arguments = 'arguments'; + const restorationId = 'restorationId'; + const child = DummyStatefulWidget(); + final page = pageBuilderForMaterialApp( + key: key, + name: name, + arguments: arguments, + restorationId: restorationId, + child: child, + ); + expect(page.key, key); + expect(page.name, name); + expect(page.arguments, arguments); + expect(page.restorationId, restorationId); + expect(page.child, child); + }); + + group('GoRouterMaterialErrorScreen', () { + testWidgets('shows "page not found" by default', (tester) async { + await tester.pumpWidget(const MaterialApp( + home: GoRouterMaterialErrorScreen(null), + )); + expect(find.text('page not found'), findsOneWidget); + }); + + testWidgets('shows the exception message when provided', (tester) async { + final error = Exception('Something went wrong!'); + await tester.pumpWidget(MaterialApp( + home: GoRouterMaterialErrorScreen(error), + )); + expect(find.text('$error'), findsOneWidget); + }); + + testWidgets('clicking the TextButton should redirect to /', (tester) async { + final router = GoRouter( + initialLocation: '/error', + routes: [ + GoRoute(path: '/', builder: (_, __) => const DummyStatefulWidget()), + GoRoute( + path: '/error', + builder: (_, __) => const GoRouterMaterialErrorScreen(null), + ), + ], + ); + await tester.pumpWidget( + MaterialApp.router( + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + final textButton = find.byType(TextButton); + await tester.tap(textButton); + await tester.pumpAndSettle(); + expect(find.byType(DummyStatefulWidget), findsOneWidget); + }); + }); +} + +class DummyStatefulWidget extends StatefulWidget { + const DummyStatefulWidget({Key? key}) : super(key: key); + + @override + State createState() => _DummyStatefulWidgetState(); +} + +class _DummyStatefulWidgetState extends State { + @override + Widget build(BuildContext context) => Container(); +} From c5563aa081e18ccdae0cd546bfc7a4b039a2e799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sat, 19 Feb 2022 11:26:02 -0300 Subject: [PATCH 06/12] test: adds `GoRouterErrorScreen` tests --- .../test/src/go_router_error_page_test.dart | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 go_router/test/src/go_router_error_page_test.dart diff --git a/go_router/test/src/go_router_error_page_test.dart b/go_router/test/src/go_router_error_page_test.dart new file mode 100644 index 00000000..f28b2df1 --- /dev/null +++ b/go_router/test/src/go_router_error_page_test.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; +import 'package:go_router/src/go_router_error_page.dart'; + +void main() { + testWidgets('shows "page not found" by default', (tester) async { + await tester.pumpWidget(const MaterialApp( + color: Color(0xFFFFFFFF), + home: GoRouterErrorScreen(null), + )); + expect(find.text('page not found'), findsOneWidget); + }); + + testWidgets('shows the exception message when provided', (tester) async { + final error = Exception('Something went wrong!'); + await tester.pumpWidget(MaterialApp( + color: const Color(0xFFFFFFFF), + home: GoRouterErrorScreen(error), + )); + expect(find.text('$error'), findsOneWidget); + }); + + testWidgets('clicking the button should redirect to /', (tester) async { + final router = GoRouter( + initialLocation: '/error', + routes: [ + GoRoute(path: '/', builder: (_, __) => const DummyStatefulWidget()), + GoRoute( + path: '/error', + builder: (_, __) => const GoRouterErrorScreen(null), + ), + ], + ); + await tester.pumpWidget( + MaterialApp.router( + color: const Color(0xFFFFFFFF), + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + final button = + find.byWidgetPredicate((widget) => widget is GestureDetector); + await tester.tap(button); + await tester.pumpAndSettle(); + expect(find.byType(DummyStatefulWidget), findsOneWidget); + }); +} + +class DummyStatefulWidget extends StatefulWidget { + const DummyStatefulWidget({Key? key}) : super(key: key); + + @override + State createState() => _DummyStatefulWidgetState(); +} + +class _DummyStatefulWidgetState extends State { + @override + Widget build(BuildContext context) => Container(); +} From 5336d0d25190dbb451f9ed539543c4d7d0029fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sat, 19 Feb 2022 11:39:55 -0300 Subject: [PATCH 07/12] test: adds transitions related tests --- .../test/src/custom_transition_page_test.dart | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 go_router/test/src/custom_transition_page_test.dart diff --git a/go_router/test/src/custom_transition_page_test.dart b/go_router/test/src/custom_transition_page_test.dart new file mode 100644 index 00000000..8b574277 --- /dev/null +++ b/go_router/test/src/custom_transition_page_test.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; + +import '../go_router_test.dart'; + +void main() { + test('NoTransitionPage does not apply any transition', () { + const homeScreen = HomeScreen(); + const page = NoTransitionPage(child: homeScreen); + const primaryAnimation = AlwaysStoppedAnimation(0); + const secondaryAnimation = AlwaysStoppedAnimation(1); + final widget = page.transitionsBuilder( + DummyBuildContext(), + primaryAnimation, + secondaryAnimation, + homeScreen, + ); + expect(widget, homeScreen); + }); +} + +class HomeScreen extends StatelessWidget { + const HomeScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) => Container(); +} From bb31f9ddf6559ea900c3d8ce98fc3c38af652d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sat, 19 Feb 2022 12:48:56 -0300 Subject: [PATCH 08/12] test: adds `GoRouterDelegate` tests --- .../test/src/go_router_delegate_test.dart | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 go_router/test/src/go_router_delegate_test.dart diff --git a/go_router/test/src/go_router_delegate_test.dart b/go_router/test/src/go_router_delegate_test.dart new file mode 100644 index 00000000..811938c5 --- /dev/null +++ b/go_router/test/src/go_router_delegate_test.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; +import 'package:go_router/src/go_router_delegate.dart'; +import 'package:go_router/src/go_router_error_page.dart'; + +GoRouterDelegate createGoRouterDelegate({ + Listenable? refreshListenable, +}) { + final router = GoRouter( + initialLocation: '/', + routes: [ + GoRoute(path: '/', builder: (_, __) => const DummyStatefulWidget()), + GoRoute( + path: '/error', + builder: (_, __) => const GoRouterErrorScreen(null), + ), + ], + refreshListenable: refreshListenable, + ); + return router.routerDelegate; +} + +void main() { + group('pop', () { + test('removes the last element', () { + final delegate = createGoRouterDelegate() + ..push('/error') + ..addListener(expectAsync0(() {})); + final last = delegate.matches.last; + delegate.pop(); + expect(delegate.matches.length, 1); + expect(delegate.matches.contains(last), false); + }); + + test('throws when it pops more than matches count', () { + final delegate = createGoRouterDelegate()..push('/error'); + expect( + () => delegate + ..pop() + ..pop(), + throwsException, + ); + }); + }); + + test('on dispose unsubscribes from refreshListenable', () { + final refreshListenable = FakeRefreshListenable(); + createGoRouterDelegate(refreshListenable: refreshListenable).dispose(); + expect(refreshListenable.unsubscribed, true); + }); +} + +class FakeRefreshListenable extends ChangeNotifier { + bool unsubscribed = false; + @override + void removeListener(VoidCallback listener) { + unsubscribed = true; + super.removeListener(listener); + } +} + +class DummyStatefulWidget extends StatefulWidget { + const DummyStatefulWidget({Key? key}) : super(key: key); + + @override + State createState() => _DummyStatefulWidgetState(); +} + +class _DummyStatefulWidgetState extends State { + @override + Widget build(BuildContext context) => Container(); +} From e5810c94a1b7f89a10e805cde047a060b7f511c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sat, 19 Feb 2022 13:29:40 -0300 Subject: [PATCH 09/12] test: adds `GoRouter` tests --- go_router/test/src/go_router_test.dart | 106 +++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 go_router/test/src/go_router_test.dart diff --git a/go_router/test/src/go_router_test.dart b/go_router/test/src/go_router_test.dart new file mode 100644 index 00000000..fddabdfc --- /dev/null +++ b/go_router/test/src/go_router_test.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; +import 'package:go_router/src/go_router_error_page.dart'; +import 'package:go_router/src/typedefs.dart'; + +import '../go_router_test.dart'; + +GoRouter createGoRouter({ + GoRouterNavigatorBuilder? navigatorBuilder, +}) => + GoRouter( + initialLocation: '/', + routes: [ + GoRoute(path: '/', builder: (_, __) => const DummyStatefulWidget()), + GoRoute( + path: '/error', + builder: (_, __) => const GoRouterErrorScreen(null), + ), + ], + navigatorBuilder: navigatorBuilder, + ); + +void main() { + test('pop triggers pop on routerDelegate', () { + final router = createGoRouter()..push('/error'); + router.routerDelegate.addListener(expectAsync0(() {})); + router.pop(); + }); + + test('refresh triggers refresh on routerDelegate', () { + final router = createGoRouter(); + router.routerDelegate.addListener(expectAsync0(() {})); + router.refresh(); + }); + + test('didPush notifies listeners', () { + createGoRouter() + ..addListener(expectAsync0(() {})) + ..didPush( + MaterialPageRoute(builder: (_) => const Text('Current route')), + MaterialPageRoute(builder: (_) => const Text('Previous route')), + ); + }); + + test('didPop notifies listeners', () { + createGoRouter() + ..addListener(expectAsync0(() {})) + ..didPop( + MaterialPageRoute(builder: (_) => const Text('Current route')), + MaterialPageRoute(builder: (_) => const Text('Previous route')), + ); + }); + + test('didRemove notifies listeners', () { + createGoRouter() + ..addListener(expectAsync0(() {})) + ..didRemove( + MaterialPageRoute(builder: (_) => const Text('Current route')), + MaterialPageRoute(builder: (_) => const Text('Previous route')), + ); + }); + + test('didReplace notifies listeners', () { + createGoRouter() + ..addListener(expectAsync0(() {})) + ..didReplace( + newRoute: MaterialPageRoute( + builder: (_) => const Text('Current route'), + ), + oldRoute: MaterialPageRoute( + builder: (_) => const Text('Previous route'), + ), + ); + }); + + test('uses navigatorBuilder when provided', () { + final navigationBuilder = expectAsync3(fakeNavigationBuilder); + final router = createGoRouter(navigatorBuilder: navigationBuilder); + final delegate = router.routerDelegate; + delegate.builderWithNav( + DummyBuildContext(), + GoRouterState(delegate, location: '/foo', subloc: '/bar', name: 'baz'), + const Navigator(), + ); + }); +} + +Widget fakeNavigationBuilder( + BuildContext context, + GoRouterState state, + Widget child, +) => + child; + +class DummyStatefulWidget extends StatefulWidget { + const DummyStatefulWidget({Key? key}) : super(key: key); + + @override + State createState() => _DummyStatefulWidgetState(); +} + +class _DummyStatefulWidgetState extends State { + @override + Widget build(BuildContext context) => Container(); +} From b2a1a92647f29d374756230eaf02b1b8ef906c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sat, 19 Feb 2022 15:17:06 -0300 Subject: [PATCH 10/12] test: adds `GoRoute` tests --- go_router/test/src/go_route_test.dart | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 go_router/test/src/go_route_test.dart diff --git a/go_router/test/src/go_route_test.dart b/go_router/test/src/go_route_test.dart new file mode 100644 index 00000000..fc2dadbb --- /dev/null +++ b/go_router/test/src/go_route_test.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; +import 'package:go_router/src/go_router_delegate.dart'; + +import '../go_router_test.dart'; + +GoRouterDelegate createGoRouterDelegate() => GoRouter( + initialLocation: '/', + routes: [ + GoRoute(path: '/', builder: (_, __) => Container()), + ], + ).routerDelegate; + +void main() { + test('throws when a builder is not set', () { + final delegate = createGoRouterDelegate(); + final route = GoRoute(path: '/'); + void build() => route.builder( + DummyBuildContext(), + GoRouterState( + delegate, + location: '/foo', + subloc: '/bar', + name: 'baz', + ), + ); + expect(build, throwsException); + }); +} From 1d310a6a3f8a1521a22b186cf09c2376fafa4087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sun, 20 Feb 2022 13:27:34 -0300 Subject: [PATCH 11/12] test: adds more transitions related tests --- .../test/src/custom_transition_page_test.dart | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/go_router/test/src/custom_transition_page_test.dart b/go_router/test/src/custom_transition_page_test.dart index 8b574277..8734fe46 100644 --- a/go_router/test/src/custom_transition_page_test.dart +++ b/go_router/test/src/custom_transition_page_test.dart @@ -5,6 +5,31 @@ import 'package:go_router/go_router.dart'; import '../go_router_test.dart'; void main() { + testWidgets('CustomTransitionPage builds its child using transitionsBuilder', + (tester) async { + const child = HomeScreen(); + final transition = CustomTransitionPage( + transitionsBuilder: expectAsync4((_, __, ___, child) => child), + child: child, + ); + final router = GoRouter( + routes: [ + GoRoute( + path: '/', + pageBuilder: (_, __) => transition, + ), + ], + ); + await tester.pumpWidget( + MaterialApp.router( + routeInformationParser: router.routeInformationParser, + routerDelegate: router.routerDelegate, + title: 'GoRouter Example', + ), + ); + expect(find.byWidget(child), findsOneWidget); + }); + test('NoTransitionPage does not apply any transition', () { const homeScreen = HomeScreen(); const page = NoTransitionPage(child: homeScreen); From 99c3887368ae5778bf33c49b20c3312d49cf1c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio=20Sanderson?= Date: Sun, 20 Feb 2022 13:50:13 -0300 Subject: [PATCH 12/12] docs: updates changelog --- go_router/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/go_router/CHANGELOG.md b/go_router/CHANGELOG.md index bff37eea..98e130cd 100644 --- a/go_router/CHANGELOG.md +++ b/go_router/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### 3.0.2 + +- Improves coverage to 92.9%. + ### 3.0.1 - pass along the error to the `navigatorBuilder` to allow for different