0

I'm using jest with react testing library to provide basic testing for my React app. I have mocked the REST calls with msw.

Unfortunately one of the 3rd party libraries I'm using doesn't seem to render output properly in those tests and as I am more interesting in testing the whole flow than precise results I've decided to mock it and replace with a dummy implementation.

The library is react-photo-album, and I'm importing it in my component as:

import PhotoAlbum from "react-photo-album";

My test looks like:

it('loads photos', async () => {

 //mocking goes here

  const { container } = render(<MemoryRouter><Gallery /></MemoryRouter>);
  
  screen.debug();

  await waitFor(() => {
      expect(container.getElementsByClassName('mockedComponent').length).toBe(1);
   });
});

I'm mostly interested in the result after msw responds to the rest calls providing actual data, but for now I'd be happy to at least see the PhotoAlbum component replaced at all in the debug view. Yet, it doesn't seem to be affected at all. Instead original component is rendered.

Now, what I've tried for mocking (already dropping any fancy logic):

  jest.doMock('react-photo-album', () => ({
    PhotoAlbum: () => <div className="mockedComponent" />,
  }));

  jest.mock('react-photo-album', () => ({
    __esModule: true,
    PhotoAlbum: () => <div className="mockedComponent" />,
  }));

  jest.mock('react-photo-album', () => ({
    __esModule: true,
    default: () => <div className="mockedComponent" />,
  }));

  jest.mock('PhotoAlbum', () => (props) => {
    return <div className="mockedComponent" />;
  });

plus multiple variations of those, including mock and doMock and even simply:

  jest.mock('react-photo-album');

But my component seems to be untouched!. With mock method I mostly get error of:

The module factory of jest.mock() is not allowed to reference any out-of-scope variables. Invalid variable access: _jsxFileName

but doMock seems to solve this problem.

So what am I doing wrong? I feel like I'm missing some detail. For the record neither React or jest are the tools I'm normally used to work with. I've also seen answers like: How to mock a third party React component using Jest?, but it just doesn't seem to work.

mikus
  • 3,042
  • 1
  • 30
  • 40

1 Answers1

0

The error you are experiencing is probably specific to your environment / project setup as one of the mock options that you mentioned in your question actually works.

Here is a working example:

import { render } from "@testing-library/react";
import Gallery from "../src/Gallery";

jest.mock("react-photo-album", () => ({
    __esModule: true,
    default: () => <div className="mockedComponent" />,
}));

describe("Gallery", () => {
    it("loads photos", () => {
        const { container } = render(<Gallery />);

        expect(container.getElementsByClassName("mockedComponent").length).toBe(1);
    });
});

Now, if you want to address the original issue of PhotoAlbum not rendering in jest tests, you can fix it by mocking the PhotoAlbum's container <div> clientWidth:

import { render } from "@testing-library/react";
import Gallery from "../src/Gallery";

// mock PhotoAlbum container clientWidth
jest
    .spyOn(Element.prototype, "clientWidth", "get")
    .mockImplementation(function () {
        return (this.className || "").split(" ").includes("react-photo-album")
            ? 800
            : 0;
    });

describe("Gallery", () => {
    it("loads photos", () => {
        const { container } = render(<Gallery />);

        // test PhotoAlbum rendered 3 photos
        expect(
            container.getElementsByClassName("react-photo-album--photo").length
        ).toBe(3);
    });
});

You can find minimal working example in the following sandbox.

https://codesandbox.io/p/sandbox/stackoverflow-75817885-fs9y5m?file=%2Ftest%2FGalleryMock.spec.jsx

Igor Danchenko
  • 1,980
  • 1
  • 3
  • 13