react-hook-form submit does not pick up changeText from jest test

Viewed 515

I have the following react-native-form:

const { register, handleSubmit, setValue, errors } = useForm();

const onSubmit = (data) => {
  console.log(data);
  return firebase
    .auth()
    .signInWithEmailAndPassword(data.email, data.password)
    .then((info) => {
      console.log(info.additionalUserInfo.profile);
    })
    .catch((err) => {
      console.error(err);
    });
};

  <View>
    <TextInput
      placeholder="Email"
      testID="email-input"
      onChangeText={(t) => setValue("email", t)}
      style={styles.loginTextInput}
    ></TextInput>
    <TextInput
      secureTextEntry={true}
      testID="password-input"
      placeholder="Password (min. 8 characters)"
      onChangeText={(t) => setValue("password", t)}
      style={styles.loginTextInput}
    ></TextInput>
    <TouchableOpacity
      onPress={handleSubmit(onSubmit)}
      testID={"login-email-button"}
      style={[styles.loginButton, styles.loginEmailButton]}
    >
      <Text style={styles.buttonText}>Login with Email</Text>
    </TouchableOpacity>
  </View>

I am testing the submission and the call to firebase.auth().signInWithEmailAndPassword using jest in the following test:

test("submit works", async () => {
  const { getByPlaceholderText, getByTestId, getByText } = render(
    <EmailLogin />
  );
  const emailInput = getByTestId("email-input");
  const passwordInput = getByTestId("password-input");
  const submitButton = getByTestId("login-email-button");

  const email = "foo@email.com";
  const password = "password";
  fireEvent.changeText(emailInput, email);
  fireEvent.changeText(passwordInput, password);
  fireEvent.press(submitButton);

  expect(firebase.auth().signInWithEmailAndPassword).toHaveBeenCalledWith(
    email,
    password
  );
});

where I've mocked out signInWithEmailAndPassword as a jest.fn().

When I run this test, it fails with:

expect(jest.fn()).toHaveBeenCalledWith(...expected)

Expected: "foo@email.com", "password"
Received: undefined, undefined

And I noticed the console.log(data) I have in my onSubmit function prints out:

console.log
  {}

which means no text was picked up.

How do I go about testing this form?

1 Answers

I think the reason why it returns undefined for you is that you are trying to test asynchronous behaviour in a sync way. I would suggest using Promises in your onSubmit method to wait for the firebase auth call to finish.

Something like this could work

const onSubmit = async (data) => {
  console.log(data);
  return await firebase
    .auth()
    .signInWithEmailAndPassword(data.email, data.password)
    .then((info) => {
      console.log(info.additionalUserInfo.profile);
    })
    .catch((err) => {
      console.error(err);
    });
};

This would then ensure that you are waiting for the sign in to happen.

In your test, I would mock the firebase to something like this

jest.mock('firebase', () => ({
    auth: jest.fn().mockReturnThis(),
    signInWithEmailAndPassword: jest.fn(),
   })
);

And then in your test, you would also need to use waitFor() to wait for the sign in to happen so then you can check your results. Something like this could work

await waitFor(() => expect(firebase.auth().signInWithEmailAndPassword).toHaveBeenCalledWith(
    email,
    password
  ););

I haven't tested it myself but try the idea of using async and Promises and let me know if that works.

Related