vendredi 11 décembre 2020

I want to mock a functional component and run a uinit test

I'm trying to run unit tests for an app. I'm building with React+TypeScript+firebase, but when the component I'm testing interacts with Firebase in some way, the tests don't go well and I get a FirebaseError.

FirebaseError: projectId must be a string in FirebaseApp.options

After doing some research on testing, I realized that when testing an application that communicates with APIs, etc., it would be a good idea to mock the component and describe in advance what kind of data will be returned in the test code.

However, even though I have done a lot of research, I have not been able to write a test code that works well, probably due to my lack of understanding, so I would like to ask a question.

Here is my source code.

Login.tsx

export default function Login() {
  const classes = useStyles();
  const emailRef = useRef();
  const passwordRef = useRef();
  const { login }: any = useAuth();
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const history = useHistory();

  const inputEmail = useCallback(
    (event) => {
      setEmail(event.target.value);
    },
    [setEmail]
  );

  const inputPassword = useCallback(
    (event) => {
      setPassword(event.target.value);
    },
    [setPassword]
  );

  async function handleSubmit(e: any) {
    e.preventDefault();

    setError("");
    setLoading(true);
    return login(email, password)
      .then(() => {
        history.push("/");
      })
      .catch((error: any) => {
        setError("failed!!");
      })
      .finally(() => {
        setLoading(false);
      });
  }

  const onClickGuestButton = () => {
    setError("");
    setLoading(true);
    return login("guest@example.com", "password")
      .then(() => {
        history.push("/");
      })
      .catch((error: any) => {
        setError("failed!!");
      })
      .finally(() => {
        setLoading(false);
      });
  };

  return(
  {/*....*/}
  )

Login.test.tsx

import * as React from "react";
import Login from "../Login";
import { configure, mount, shallow } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
// import { Login as mockLogin } from "../Login";
import ReactDOM from "react-dom";

configure({ adapter: new Adapter() });

jest.mock("../Login", () => {
  return login("fake@example.com", "password"){
    return Promise.resolve(fakeUser)
  }
});

describe("Login", () => {
  it("should return currect user", () => {
    // const wrapper = shallow(<Login />);
    // expect(wrapper.find("button").length).toBe(2);
    const fakeUser = {
      username: "FakeMan",
      email: "fake@example.com",
      uid: "KN8qXkuYmPf2i9kvzC2mQylZQPo1",
    };
    jest.spyOn(global, "fetch").mockImplementation((): any =>
      Promise.resolve({
        json: () => Promise.resolve(fakeUser),
      })
    );
  });
});

I understand that it is possible to mock components and functions using jest.mock(), but I don't know how to do it in this case. Also, when I tried to run the test with a component that does not communicate with Firebase, I did not get a FirebaseError (of course) and the test passed normally.

To summarize, what I want to achieve is to be able to perform various tests within a function component that contains a handler that communicates with firebase.

Let me know if you have any good ideas.

Thank you!

Aucun commentaire:

Enregistrer un commentaire