dimanche 6 décembre 2020

Flutter pushReplacementNamed does not pass tests

I have two screens (log in and sign up) which have buttons linking to each other respectively. For the log in page a button triggers pushReplacementNamed to navigate to the sign up page. Similarly in the sign up page a different button triggers pushReplacementNamed to navigate to the log in page.

login_screen.dart:

SecondaryButton(
  onPressed: () {
    Navigator.pushReplacementNamed(context, SignupScreen.id);
  },
  key: LoginScreen.signupBtnKey,
  child: Text('Sign Up'),
),

signup_screen.dart:

SecondaryButton(
  onPressed: () {
    Navigator.pushReplacementNamed(context, LoginScreen.id);
  },
  key: SignupScreen.loginBtnKey,
  child: Text('Log In'),
)

When testing on the emulator both buttons seem to work fine but when trying to run automated tests it doesn't work for the sign up screen.

login_screen_test.dart

class MockNavigatorObserver extends Mock implements NavigatorObserver {}

void main() {

  group('Login Screen Widget Tests', () {

    NavigatorObserver mockObserver;

    setUp(() {
      mockObserver = MockNavigatorObserver();
    });

    Widget createLoginScreen() {
      return MaterialApp(
        initialRoute: LoginScreen.id,
        routes: {
          LoginScreen.id: (context) => LoginScreen(),
          SignupScreen.id: (context) => SignupScreen(),
        },
        navigatorObservers: [mockObserver],
      );
    }

    testWidgets(
      'Testing if sign up button shows up and triggers navigation after tapped',
      (tester) async {
        await tester.pumpWidget(createLoginScreen());
        expect(find.byKey(LoginScreen.signupBtnKey), findsOneWidget);
        await tester.tap(find.byKey(LoginScreen.signupBtnKey));
        await tester.pumpAndSettle();
        verify(
          mockObserver.didReplace(
            oldRoute: anyNamed('oldRoute'),
            newRoute: anyNamed('newRoute'),
          ),
        );
        expect(find.byType(SignupScreen), findsOneWidget);
        expect(find.byType(LoginScreen), findsNothing);
      },
    );
  });
}

signup_screen_test.dart

class MockNavigatorObserver extends Mock implements NavigatorObserver {}

void main() {

  group('Signup Screen Widget Tests', () {

    NavigatorObserver mockObserver;

    setUp(() {
      mockObserver = MockNavigatorObserver();
    });

    Widget createSignupScreen() {
      return MaterialApp(
        initialRoute: SignupScreen.id,
        routes: {
          LoginScreen.id: (context) => LoginScreen(),
          SignupScreen.id: (context) => SignupScreen(),
        },
        navigatorObservers: [mockObserver],
      );
    }

    testWidgets(
      'Testing if log in button shows up and triggers navigation after tapped',
      (tester) async {
        await tester.pumpWidget(createSignupScreen());
        expect(find.byKey(SignupScreen.loginBtnKey), findsOneWidget);
        await tester.tap(find.byKey(SignupScreen.loginBtnKey));
        await tester.pumpAndSettle();
        verify(
          mockObserver.didReplace(
            oldRoute: anyNamed('oldRoute'),
            newRoute: anyNamed('newRoute'),
          ),
        );
        expect(find.byType(LoginScreen), findsOneWidget);
        expect(find.byType(SignupScreen), findsNothing);
      },
    );
  });
}

This fails with the following exception:

The following TestFailure object was thrown running a test:
  No matching calls. All calls: MockNavigatorObserver.navigator,
MockNavigatorObserver._navigator==NavigatorState#03a3a(tickers: tracking 1 ticker),
MockNavigatorObserver.didPush(MaterialPageRoute<dynamic>(RouteSettings("/signup", null), animation:
AnimationController#9b7dc(⏭ 1.000; paused; for MaterialPageRoute<dynamic>(/signup))), null)

Which suggests that the didReplace() method isn't being triggered. The code is almost identical on each page and so I can't understand why one would pass but the other one fail.

Would appreciate any insight, might be something obvious!

Aucun commentaire:

Enregistrer un commentaire