0

Here is the function that I wanna test, it takes a token and a description as props. Normally in React code, I can get token from useContext.

export const updateUserProfileAbout = async (
  token,
  description
) => {
  const dataUpdateTemplateDescriptionRes = await patchData(`me/`, token, {
    about:description,
  });
  const dataUpdateTemplateDescriptionJson  = await dataUpdateTemplateDescriptionRes.json();
  return dataUpdateTemplateDescriptionJson;
};

And here is my custom patchData function:

const patchData = async (urn, token, data = "") => {
  const headers = {
    "Content-Type": "application/json",
    Authorization: `Bearer ${token.access}`,
  };
  const body = data ? JSON.stringify(data) : null;
  let response;
  if (body) {
    response = await fetch(`${host}/api/${urn}`, {
      method: "PATCH",
      headers,
      body,
    });
  } else {
    response = await fetch(`${host}/api/${urn}`, {
      method: "PATCH",
      headers,
    });
  }
  if (!response.ok) throw new Error(response.status);
  return response;
};
Michael Nguyen
  • 83
  • 2
  • 4
  • 11
  • Have you heard of Mock API (for example Mock Axios)? – Tan Nguyen Dec 18 '21 at 17:42
  • @TanNguyen yes I did some research on mock API with Axios and Fetch API. However, I don't know how to mock API with token or using React ContextAPI in jest. – Michael Nguyen Dec 19 '21 at 02:36
  • Try Googling with your keyword "ReactContext", "Jest", found some: https://stackoverflow.com/questions/54292298/jest-mock-react-context – Tan Nguyen Dec 19 '21 at 06:41

2 Answers2

1

You are right. You don't need the token. All you need to do for mocking the fetch is the following:

jest.spyOn(global, 'fetch').mockImplementationOnce(
jest.fn(() => Promise.resolve()) as jest.Mock);

If you want to retrieve a specific object from a json response, you can use:

jest.spyOn(global, 'fetch').mockImplementationOnce(
jest.fn(() => Promise.resolve({ ok: true, json: () => Promise.resolve({ myObject }) })) as jest.Mock);

You can also reject it to trigger the error catch:

jest.spyOn(global, 'fetch').mockImplementationOnce(
jest.fn(() => Promise.reject()) as jest.Mock);

If you want to return something multiple times, change the mockImplementationOnce to whatever you need (maybe mockImplementation, for returning it every time you call it).

If you also want to expect the call of the fetch just add a constant:

const myFetch = jest.spyOn(global, 'fetch').mockImplementationOnce(
jest.fn(() => Promise.reject()) as jest.Mock);

You can then expect it via: expect(myFetch).toBecalledTimes(1);

Henrik
  • 53
  • 6
0

After one more day of researching, I might be wrong though but I don't think I have to care about token or authorization when unit testing for front-end. All I need is jest.fn() to mock function and jest.spyOn(global, "fetch") to track fetch API.

For more information, here are some references that I read:

https://codewithhugo.com/jest-fn-spyon-stub-mock/

https://dev.to/qmenoret/mocks-and-spies-with-jest-32gf

https://www.pluralsight.com/guides/how-does-jest.fn()-work

https://www.loupetestware.com/post/mocking-api-calls-with-jest

Michael Nguyen
  • 83
  • 2
  • 4
  • 11
  • 2
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 21 '21 at 06:49
  • 1
    Hello, could you please post the updated code? – Amanda Koster Jan 18 '22 at 17:43