javascript - Hur man testar matchMedia med react-testing-library/jest


Kod nedan som jag behöver testa -

  const [item, setItem] = useState(() => {
    let initialItem = 'both';

    if (typeof window !== 'undefined') {
      if (window.matchMedia('(max-width: 1012px)').matches) {
        initialItem = 'signup';
      } else if (window.matchMedia('(max-width: 1460px)').matches) {
        initialItem = 'info';
      }
    }

    return initialItem;
  });

  if (typeof window !== 'undefined') {
    window.matchMedia('(max-width: 1012px)').addEventListener('change', (event) => {
      if (event.matches) {
        setItem('signup');
      }
    });

    window.matchMedia('(max-width: 1460px)').addEventListener('change', (event) => {
      if (event.matches) {
        setItem('info');
      }
    });

    window.matchMedia('(min-width: 1460px)').addEventListener('change', (event) => {
      if (event.matches) {
        setItem('both');
      }
    });
  }

Jag har svårt att testa detta. Detta är vad jag har just nu -

test('should update layout on window resize', () => {
    window.matchMedia = jest.fn().mockImplementation((query) => ({
      matches: query !== '(max-width: 1011px)',
      media: '',
      onchange: null,
      addEventListener: jest.fn(),
      removeListener: jest.fn(),
    }));

    globalThis.innerWidth = 1500;
    renderTestComponent();
    expect(screen.getByTestId('item')).toHaveTextContent('both');
    

    // Resize the window to small
    globalThis.innerWidth = 1000;
    globalThis.dispatchEvent(new Event('change'));
    expect(screen.getByTestId('item')).toHaveTextContent('box');

Hur kan jag testa att rätt objekt visas när skärmen ändrar storlek, särskilt när jag använder matchMedia?

Svar #1

Prova detta

const mediaListeners: (() => void)[] = [];
// mock matchMedia
Object.defineProperty(window, "matchMedia", {
  writable: true,
  value: vi.fn().mockImplementation((query: string) => ({
    matches: query.includes(window.media),
    media: query,
    onchange() {
      this.matches = query.includes(window.media);
      mediaListeners.forEach(listener => listener());
    },
    addEventListener: (_: string, listener: () => void) => mediaListeners.push(listener),
    removeEventListener: (_: string, listener: () => void) =>
      mediaListeners.splice(mediaListeners.indexOf(listener), 1),
    dispatchEvent: vi.fn(),
  })),
});

Relaterade artiklar