模拟 Windows 媒体以测试响应式挂钩。

huangapple go评论82阅读模式
英文:

Mock windows media to test responsive hook

问题

I'm here to help with the translation. Here's the code you provided in Chinese:

我正在尝试测试以下实现

import React from "react";
import { useMediaQuery } from "react-responsive";

const MyComponent = () => {
  const isSM = useMediaQuery({ maxWidth: 767 });
  const isMD = useMediaQuery({ minWidth: 768, maxWidth: 1023 });
  const isLG = useMediaQuery({ minWidth: 1024 });

  console.log(`isSM:${isSM} isMD:${isMD} isLG:${isLG}`);

  return <>{`isSM:${isSM} isMD:${isMD} isLG:${isLG}`}</>;
};

export default MyComponent;

如何模拟以使isLG可以设置为true?以及类似地,如何能够在其他测试中将isSM和isMD设置为true?

尝试了以下方法,但所有三个(isSM,isMD,isLG)始终为false。

function mockMatchMedia(query) {
    return Object.defineProperty(window, 'matchMedia', {
        writable: true,
        value: jest.fn().mockImplementation((mediaQuery) => ({
        matches: mediaQuery.includes(query),
        media: mediaQuery,
        onchange: null,
        addListener: jest.fn(), 
        removeListener: jest.fn(),
        addEventListener: jest.fn(),
        removeEventListener: jest.fn(),
        dispatchEvent: jest.fn(),
        })),
    });
}

test("渲染组件", () => {
    mockMatchMedia('min-width: 1024px');
    mount(<MyComponent />);

    // 组件中的控制台日志始终为false。
    // 预期isLG为true。

    // 断言
}

更新:

以下仍然对所有3个打印false。

import renderer from "react-test-renderer";
import { MatchMediaMock, create } from 'match-media-mock';

export const matchSnapshot = (reactElement: React.ReactElement) => {
  const instance = renderer.create(reactElement);
  const tree = instance.toJSON();

  expect(tree).toMatchSnapshot();
};

interface MockWindow extends Window {
    matchMedia: MatchMediaMock
}

test("渲染", () => {
    global.window.matchMedia = create();
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: 'screen',
      width: 700
    })
    matchSnapshot(
      <MyComponent />
    );
  });

如果需要进一步帮助,请告诉我。

英文:

I am trying to test the following implementation.

import React from &quot;react&quot;;
import { useMediaQuery } from &quot;react-responsive&quot;;

const MyComponent = () =&gt; {
  const isSM = useMediaQuery({ maxWidth: 767 });
  const isMD = useMediaQuery({ minWidth: 768, maxWidth: 1023 });
  const isLG = useMediaQuery({ minWidth: 1024 });

  console.log(`isSM:${isSM} isMD:${isMD} isLG:${isLG}`);

  return &lt;&gt;{`isSM:${isSM} isMD:${isMD} isLG:${isLG}`}&lt;/&gt;;
};

export default MyComponent;

How can I mock it so that isLG can be set to true?
And similarly to be able to set isSM and isMD to be true for other tests?

Tried the following but all 3 (isSM, isMD, isLG) are always false.

function mockMatchMedia(query) {
    return Object.defineProperty(window, &#39;matchMedia&#39;, {
        writable: true,
        value: jest.fn().mockImplementation((mediaQuery) =&gt; ({
        matches: mediaQuery.includes(query),
        media: mediaQuery,
        onchange: null,
        addListener: jest.fn(), 
        removeListener: jest.fn(),
        addEventListener: jest.fn(),
        removeEventListener: jest.fn(),
        dispatchEvent: jest.fn(),
        })),
    });
}

test(&quot;renders the component&quot;, () =&gt; {
    mockMatchMedia(&#39;min-width: 1024px&#39;);
    mount(&lt;MyComponent /&gt;);

    // the console log in component prints false for all wrongly. 
    // Was expecting isLG to be true.

    // assertions
}

UPDATE:

The following still prints out false for all 3.

import renderer from &quot;react-test-renderer&quot;;
import { MatchMediaMock, create } from &#39;match-media-mock&#39;;

export const matchSnapshot = (reactElement: React.ReactElement) =&gt; {
  const instance = renderer.create(reactElement);
  const tree = instance.toJSON();

  expect(tree).toMatchSnapshot();
};

interface MockWindow extends Window {
    matchMedia: MatchMediaMock
}

test(&quot;renders&quot;, () =&gt; {
    global.window.matchMedia = create();
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: &#39;screen&#39;,
      width: 700
    })
    matchSnapshot(
      &lt;MyComponent /&gt;
    );
  });

答案1

得分: 1

以下是翻译好的内容:

"The match-media-mock package can help you to create the mock for window.matchMedia easily.

例如:

jest.setup.js

import matchMediaMock from 'match-media-mock';

global.window.matchMedia = matchMediaMock.create();

jest.config.js

module.exports = {
  preset: 'ts-jest/presets/js-with-ts',
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['jest-extended', './jest.setup.js']
};

index.tsx

import React from "react";
import { useMediaQuery } from "react-responsive";

const MyComponent = () => {
  const isSM = useMediaQuery({ maxWidth: 767 });
  const isMD = useMediaQuery({ minWidth: 768, maxWidth: 1023 });
  const isLG = useMediaQuery({ minWidth: 1024 });

  console.log(`isSM:${isSM} isMD:${isMD} isLG:${isLG}`);

  return <>{`isSM:${isSM} isMD:${isMD} isLG:${isLG}`}</>;
};

export default MyComponent;

1. 使用RTL进行测试的示例

index.test.tsx

import React from 'react';
import { render } from '@testing-library/react';
import { MatchMediaMock } from 'match-media-mock';
import MyComponent from '.';

interface MockWindow extends Window {
  matchMedia: MatchMediaMock
}

describe('76305067', () => {
  test('应该是sm', () => {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: 'screen',
      width: 700,
    })
    render(<MyComponent />)
  })
  test('应该是md', () => {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: 'screen',
      width: 1000,
    })
    render(<MyComponent />)
  })
  test('应该是lg', () => {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: 'screen',
      width: 1200,
    })
    render(<MyComponent />)
  })
})

测试结果:

 PASS  stackoverflow/76305067/index.test.tsx (18.06 s)
  76305067
    ✓ 应该是sm (54 ms)
    ✓ 应该是md (7 ms)
    ✓ 应该是lg (5 ms)

  console.log
    isSM:true isMD:false isLG:false

      at MyComponent (stackoverflow/76305067/index.tsx:9:11)

  console.log
    isSM:false isMD:true isLG:false

      at MyComponent (stackoverflow/76305067/index.tsx:9:11)

  console.log
    isSM:false isMD:false isLG:true

      at MyComponent (stackoverflow/76305067/index.tsx:9:11)

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        19.631 s, estimated 24 s

2. 使用react-dom进行测试的示例

import React from 'react';
import { unmountComponentAtNode, render } from 'react-dom';
import { MatchMediaMock } from 'match-media-mock';
import MyComponent from '.';

interface MockWindow extends Window {
  matchMedia: MatchMediaMock
}

describe('76305067', () => {
  let container: HTMLDivElement | null = null;
  beforeEach(() => {
    container = document.createElement("div");
    document.body.appendChild(container);
  });

  afterEach(() => {
    if (container) {
      unmountComponentAtNode(container);
      container.remove();
      container = null;
    }
  });

  test('应该是sm', () => {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: 'screen',
      width: 700,
    })
    render(<MyComponent />, container)
  })
  test('应该是md', () => {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: 'screen',
      width: 1000,
    })
    render(<MyComponent />, container)
  })
  test('应该是lg', () => {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: 'screen',
      width: 1200,
    })
    render(<MyComponent />, container)
  })
})

包版本:

"react-responsive": "^9.0.2",
"match-media-mock": "^0.1.1",
"jest": "^26.6.3",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"@testing-library/react": "^11.2.7",
英文:

The match-media-mock package can help you to create the mock for window.matchMedia easily.

E.g.

jest.setup.js:

import matchMediaMock from &#39;match-media-mock&#39;;

global.window.matchMedia = matchMediaMock.create();

jest.config.js:

module.exports = {
  preset: &#39;ts-jest/presets/js-with-ts&#39;,
  testEnvironment: &#39;jsdom&#39;,
  setupFilesAfterEnv: [&#39;jest-extended&#39;, &#39;./jest.setup.js&#39;]
};

index.tsx:

import React from &quot;react&quot;;
import { useMediaQuery } from &quot;react-responsive&quot;;

const MyComponent = () =&gt; {
  const isSM = useMediaQuery({ maxWidth: 767 });
  const isMD = useMediaQuery({ minWidth: 768, maxWidth: 1023 });
  const isLG = useMediaQuery({ minWidth: 1024 });

  console.log(`isSM:${isSM} isMD:${isMD} isLG:${isLG}`);

  return &lt;&gt;{`isSM:${isSM} isMD:${isMD} isLG:${isLG}`}&lt;/&gt;;
};

export default MyComponent;

1. Testing recipe using RTL:

index.test.tsx:

import React from &#39;react&#39;;
import { render } from &#39;@testing-library/react&#39;;
import { MatchMediaMock } from &#39;match-media-mock&#39;;
import MyComponent from &#39;.&#39;;

interface MockWindow extends Window {
  matchMedia: MatchMediaMock
}

describe(&#39;76305067&#39;, () =&gt; {
  test(&#39;should be sm&#39;, () =&gt; {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: &#39;screen&#39;,
      width: 700,
    })
    render(&lt;MyComponent /&gt;)
  })
  test(&#39;should be md&#39;, () =&gt; {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: &#39;screen&#39;,
      width: 1000,
    })
    render(&lt;MyComponent /&gt;)
  })
  test(&#39;should be lg&#39;, () =&gt; {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: &#39;screen&#39;,
      width: 1200,
    })
    render(&lt;MyComponent /&gt;)
  })
})

Test result:

 PASS  stackoverflow/76305067/index.test.tsx (18.06 s)
  76305067
    ✓ should be sm (54 ms)
    ✓ should be md (7 ms)
    ✓ should be lg (5 ms)

  console.log
    isSM:true isMD:false isLG:false

      at MyComponent (stackoverflow/76305067/index.tsx:9:11)

  console.log
    isSM:false isMD:true isLG:false

      at MyComponent (stackoverflow/76305067/index.tsx:9:11)

  console.log
    isSM:false isMD:false isLG:true

      at MyComponent (stackoverflow/76305067/index.tsx:9:11)

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        19.631 s, estimated 24 s

2. Testing recipe using react-dom:

import React from &#39;react&#39;;
import { unmountComponentAtNode, render } from &#39;react-dom&#39;;
import { MatchMediaMock } from &#39;match-media-mock&#39;;
import MyComponent from &#39;.&#39;;

interface MockWindow extends Window {
  matchMedia: MatchMediaMock
}

describe(&#39;76305067&#39;, () =&gt; {
  let container: HTMLDivElement | null = null;
  beforeEach(() =&gt; {
    container = document.createElement(&quot;div&quot;);
    document.body.appendChild(container);
  });

  afterEach(() =&gt; {
    if (container) {
      unmountComponentAtNode(container);
      container.remove();
      container = null;
    }
  });

  test(&#39;should be sm&#39;, () =&gt; {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: &#39;screen&#39;,
      width: 700,
    })
    render(&lt;MyComponent /&gt;, container)
  })
  test(&#39;should be md&#39;, () =&gt; {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: &#39;screen&#39;,
      width: 1000,
    })
    render(&lt;MyComponent /&gt;, container)
  })
  test(&#39;should be lg&#39;, () =&gt; {
    (window as unknown as MockWindow).matchMedia.setConfig({
      type: &#39;screen&#39;,
      width: 1200,
    })
    render(&lt;MyComponent /&gt;, container)
  })
})

package versions:

&quot;react-responsive&quot;: &quot;^9.0.2&quot;,
&quot;match-media-mock&quot;: &quot;^0.1.1&quot;,
&quot;jest&quot;: &quot;^26.6.3&quot;,
&quot;react&quot;: &quot;^16.14.0&quot;,
&quot;react-dom&quot;: &quot;^16.14.0&quot;,
&quot;@testing-library/react&quot;: &quot;^11.2.7&quot;,

huangapple
  • 本文由 发表于 2023年5月22日 18:06:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76305067.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定