From 8623c5c903732b5f90c2ced6d4189785d71c7d7c Mon Sep 17 00:00:00 2001 From: Bas Rops Date: Wed, 22 Nov 2023 11:58:17 +0100 Subject: [PATCH] fix: Updates for Flutter 3.16.0/Dart 3.2 (#65) * MockNavigator.canPop() is now stubbed automatically - Default `false` * Mock OverlayState during hackOverlays to control `mounted` * Fixed failing test * Set flutter to `>=3.16.0` in pubspec.yaml * Removed default stubbing of `canPop` * Fixed failing example tests --------- Co-authored-by: Bas Rops --- README.md | 1 + example/test/ui/home_screen_test.dart | 1 + example/test/ui/pincode_screen_test.dart | 1 + example/test/ui/quiz_dialog_test.dart | 1 + lib/src/mock_navigator.dart | 13 ++++++++++++- pubspec.yaml | 2 +- test/src/example_test.dart | 1 + test/src/mock_navigator_test.dart | 3 +++ 8 files changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5c9ca1c..62352a2 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ class MySettingsPage extends StatelessWidget { void main() { testWidgets('pushes SettingsPage when TextButton is tapped', (tester) async { final navigator = MockNavigator(); + when(navigator.canPop).thenReturn(true); when(() => navigator.push(any())).thenAnswer((_) async {}); await tester.pumpWidget( diff --git a/example/test/ui/home_screen_test.dart b/example/test/ui/home_screen_test.dart index 79c7857..a42617c 100644 --- a/example/test/ui/home_screen_test.dart +++ b/example/test/ui/home_screen_test.dart @@ -24,6 +24,7 @@ void main() { setUp(() { navigator = MockNavigator(); + when(() => navigator.canPop()).thenReturn(true); when(() => navigator.push(any())).thenAnswer((_) async => null); when( () => navigator.push(any()), diff --git a/example/test/ui/pincode_screen_test.dart b/example/test/ui/pincode_screen_test.dart index c4affdf..80a8442 100644 --- a/example/test/ui/pincode_screen_test.dart +++ b/example/test/ui/pincode_screen_test.dart @@ -14,6 +14,7 @@ void main() { setUp(() { navigator = MockNavigator(); + when(() => navigator.canPop()).thenReturn(true); }); testWidgets('.route renders PincodeScreen', (tester) async { diff --git a/example/test/ui/quiz_dialog_test.dart b/example/test/ui/quiz_dialog_test.dart index f322950..2e9a731 100644 --- a/example/test/ui/quiz_dialog_test.dart +++ b/example/test/ui/quiz_dialog_test.dart @@ -14,6 +14,7 @@ void main() { setUp(() { navigator = MockNavigator(); + when(() => navigator.canPop()).thenReturn(true); }); testWidgets('.show opens dialog', (tester) async { diff --git a/lib/src/mock_navigator.dart b/lib/src/mock_navigator.dart index 6b4aa63..ad31c4c 100644 --- a/lib/src/mock_navigator.dart +++ b/lib/src/mock_navigator.dart @@ -6,7 +6,8 @@ class _MockMaterialPageRoute extends MaterialPageRoute { void hackOverlays() { for (var i = 0; i < overlayEntries.length; i++) { - final state = OverlayState(); + // Entry can only be inserted when the state is mounted + final state = _MockOverlayState().._mounted = true; final entry = OverlayEntry(builder: (_) => const SizedBox()); try { // We need to call insert since that is the only way to populate the @@ -17,11 +18,21 @@ class _MockMaterialPageRoute extends MaterialPageRoute { // so we just ignore the error and the hack will do its job. state.insert(entry); } catch (_) {} + // Set mounted back to false to make sure the state doesn't get + // marked as dirty during OverlayEntry.remove(). + state._mounted = false; overlayEntries[i] = entry; } } } +class _MockOverlayState extends OverlayState { + late bool _mounted; + + @override + bool get mounted => _mounted; +} + class _FakeRoute extends Fake implements Route {} /// {@template mock_navigator_provider} diff --git a/pubspec.yaml b/pubspec.yaml index 8c27ed4..be45726 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ homepage: https://github.com/VeryGoodOpenSource/mockingjay environment: sdk: ">=2.18.0 <4.0.0" - flutter: ">=3.7.3" + flutter: ">=3.16.0" dependencies: flutter: diff --git a/test/src/example_test.dart b/test/src/example_test.dart index 77881df..dd3b7fb 100644 --- a/test/src/example_test.dart +++ b/test/src/example_test.dart @@ -35,6 +35,7 @@ class MySettingsPage extends StatelessWidget { void main() { testWidgets('pushes SettingsPage when TextButton is tapped', (tester) async { final navigator = MockNavigator(); + when(navigator.canPop).thenReturn(true); when(() => navigator.push(any())).thenAnswer((_) async {}); await tester.pumpWidget( diff --git a/test/src/mock_navigator_test.dart b/test/src/mock_navigator_test.dart index b9db451..80610ef 100644 --- a/test/src/mock_navigator_test.dart +++ b/test/src/mock_navigator_test.dart @@ -45,6 +45,7 @@ void main() { setUp(() { navigator = MockNavigator(); + when(() => navigator.canPop()).thenReturn(true); }); test('toString returns normally', () { @@ -198,6 +199,8 @@ void main() { ), ); + // Called by NavigatorState.didChangeDependencies initially + verify(() => navigator.canPop()).called(1); await tester.tap(find.byType(TextButton)); verify(() => navigator.canPop()).called(1); });