lundi 14 septembre 2020

React testing library, firebase, mocked functions

I started studying integration testing and I am struggling with mocking. I have a signup form that onSubmit calls firebase.auth.createUserWithEmailAndPassword, after that it initializes a document with the returned user uid and initialize it with default values.

I managed to check if createCserWithEmailAndPassword is correctly called but when I try to check if the collection set has been called I receive as error:

    expect(received).toHaveBeenCalled()

    Matcher error: received value must be a mock or spy function

    Received has value: undefined

I am struggling here.

Here is my test implementation:

import React from "react";
import "@testing-library/jest-dom";
import { ThemeProvider } from "styled-components";
import { defaultTheme } from "../../styles";
import { createMemoryHistory } from "history";
import { Router, Switch, Route } from "react-router-dom";
import { render, fireEvent, wait } from "@testing-library/react";
import { SignUp } from "../../sections";
import { User } from "../../types";
import { auth, firestore } from "../../lib/api/firebase";
jest.mock("../../lib/api/firebase", () => {
  return {
    auth: {
      createUserWithEmailAndPassword: jest.fn(() => {
        return {
          user: {
            uid: "fakeuid",
          },
        };
      }),
      signOut: jest.fn(),
    },
    firestore: {
      collection: jest.fn(() => ({
        doc: jest.fn(() => ({
          collection: jest.fn(() => ({
            add: jest.fn(),
          })),
          set: jest.fn(),
        })),
      })),
    },
  };
});

const defaultUser: User = {
  isActive: false,
  accountName: "No balance",
  startingBalance: 0.0,
  monthlyBudget: 0.0,
};

const history = createMemoryHistory({ initialEntries: ["/signup"] });
const renderWithRouter = () =>
  render(
    <ThemeProvider theme={defaultTheme}>
      <Router history={history}>
        <Switch>
          <Route exact path="/signup">
            <SignUp />
          </Route>
          <Route exact path="/">
            <div data-testid="GenericComponent"></div>
          </Route>
        </Switch>
      </Router>
    </ThemeProvider>
  );

describe("<SignUp/>", () => {
  it("correctly renders the signup form", () => {
    const { getByTestId } = renderWithRouter();
    const form = getByTestId("SignupForm");
    expect(form).toBeInTheDocument();
  });
  it("correctly renders the signup form", () => {
    const { getByTestId } = renderWithRouter();
    const form = getByTestId("SignupForm");
    expect(form).toBeInTheDocument();
  });

  it("let user signup with valid credentials", async () => {
    const { getByPlaceholderText, getByTestId } = renderWithRouter();
    const emailField = getByPlaceholderText("yourname@company.com");
    const passwordField = getByPlaceholderText("Password");
    const confirmPasswordField = getByPlaceholderText("Confirm Password");
    const submitButton = getByTestId("Button");

    fireEvent.change(emailField, {
      target: { value: "test@test.com" },
    });

    fireEvent.change(passwordField, { target: { value: "Lampone01!" } });
    fireEvent.change(confirmPasswordField, {
      target: { value: "Lampone01!" },
    });
    fireEvent.click(submitButton);

    expect(submitButton).not.toBeDisabled();

    await wait(() => {
      expect(auth.createUserWithEmailAndPassword).toHaveBeenCalled();
      expect(
        firestore.collection("users").doc("fakeUid").set(defaultUser)
      ).toHaveBeenCalled();
      expect(history.location.pathname).toBe("/dashboard");
    });
  });
});

What am I doing wrong? Thanks guys.

Aucun commentaire:

Enregistrer un commentaire