yocontra / react-responsive

CSS media queries in react - for responsive design, and more.
https://contra.io/react-responsive
MIT License
7.04k stars 298 forks source link

[Question] Error occurred in useMediaQuery when running jest #283

Closed gsphyo91 closed 3 years ago

gsphyo91 commented 3 years ago

I am testing an application created with Create-React-App with Jest.

// Component
function Navigation() {
  const displayMenu = useMediaQuery({maxWidth: 650});
  ...
}

// Navigation.test.tsx
describe("Render Test Navigation", () => {  
  it("Navigation Component", () => {
    render(
        <Navigation />
    );
  });
});

However, in the useMediaQuery() part, the error Cannot read property 'width' of undefined occurs.

TypeError: Cannot read property 'width' of undefined

      31 |   // 라이브러리 hooks
      32 |   const history = useHistory();
    > 33 |   const displayDropdownMenu = useMediaQuery(
         |                               ^
      34 |     {
      35 |       maxWidth: 650,
      36 |     },

      at every (node_modules/react-responsive/dist/webpack:/dist/react-responsive.js:424:28)
          at Array.every (<anonymous>)
      at some (node_modules/react-responsive/dist/webpack:/dist/react-responsive.js:420:50)
          at Array.some (<anonymous>)
      at staticMatch (node_modules/react-responsive/dist/webpack:/dist/react-responsive.js:408:35)
      at new Mql (node_modules/react-responsive/dist/webpack:/dist/react-responsive.js:343:20)
      at Object.default (node_modules/react-responsive/dist/webpack:/dist/react-responsive.js:377:10)
      at getMatchMedia (node_modules/react-responsive/dist/webpack:/dist/react-responsive.js:137:64)
      at mountState (node_modules/react-dom/cjs/react-dom.development.js:15626:20)
      at Object.useState (node_modules/react-dom/cjs/react-dom.development.js:16248:16)
      at Object.useState (node_modules/react/cjs/react.development.js:1508:21)
      at useMatchMedia (node_modules/react-responsive/dist/webpack:/dist/react-responsive.js:138:30)
      at useMediaQuery (node_modules/react-responsive/dist/webpack:/dist/react-responsive.js:167:14)
      at Navigation (src/components/Navigation/Navigation.tsx:33:31)
      at renderWithHooks (node_modules/react-dom/cjs/react-dom.development.js:14985:18)
      at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:17811:13)
      at beginWork (node_modules/react-dom/cjs/react-dom.development.js:19049:16)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:3945:14)
      at HTMLUnknownElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:318:25)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
      at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:3994:16)
      at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:4056:31)
      at beginWork$1 (node_modules/react-dom/cjs/react-dom.development.js:23964:7)
      at performUnitOfWork (node_modules/react-dom/cjs/react-dom.development.js:22779:12)
      at workLoopSync (node_modules/react-dom/cjs/react-dom.development.js:22707:5)
      at renderRootSync (node_modules/react-dom/cjs/react-dom.development.js:22670:7)
      at performSyncWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:22293:18)
      at scheduleUpdateOnFiber (node_modules/react-dom/cjs/react-dom.development.js:21881:7)
      at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:25482:3)
      at node_modules/react-dom/cjs/react-dom.development.js:26021:7
      at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:22431:12)
      at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:26020:5)
      at Object.render (node_modules/react-dom/cjs/react-dom.development.js:26103:10)
      at node_modules/@testing-library/react/dist/pure.js:99:25
      at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:22380:12)
      at act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14)
      at render (node_modules/@testing-library/react/dist/pure.js:95:26)
      at Object.<anonymous> (src/test/Navigation.test.tsx:22:5)

I added matchMedia Object and modified it referring to https://github.com/contra/react-responsive#forcing-a-device-with-the-device-prop described in README.md of Github, but the same error occurs.

Here's my source:

// Component
function Navigation() {
  const displayDropdownMenu = useMediaQuery(
    { maxWidth: 650 },
    { deviceWidth: 650 }
  );

  ...
}

// Navigation.test.tsx
Object.defineProperty(window, "matchMedia", {
  writable: true,
  value: jest.fn().mockImplementation((query) => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(), // deprecated
    removeListener: jest.fn(), // deprecated
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })),
})

describe("Render Test Navigation", () => {  
  it("Navigation Component", () => {
    render(
      <ResponsiveContext.Provider
        value={{ type: "screen", width: 1200, height: 800 }}
      >
        <Navigation />
      </ResponsiveContext.Provider>
    );
  });
});

Is there any way to test useMediaQuery() without the above error?

gsphyo91 commented 3 years ago

I didn't type jest.mock('react-responsive').

Solved.