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 diff --git a/go_router/test/go_router_test.dart b/go_router/test/go_router_test.dart index 98f7c4d6..5b9ddc89 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(); +} 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..8734fe46 --- /dev/null +++ b/go_router/test/src/custom_transition_page_test.dart @@ -0,0 +1,53 @@ +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() { + 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); + 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(); +} 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); + }); +} 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..b5722003 --- /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(); +} 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(); +} 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(); +} 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(); +} 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(); +} 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..aa1bcca1 --- /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(); +}