Как бы вы протестировали адаптивную логику в JavaScript? - PullRequest
0 голосов
/ 23 декабря 2019

Я пишу пользовательский обработчик React, который имеет следующую логику (немного упрощенную):

function useResponsive<T>(options: Array<[string, T]>) {
  for (const [mediaQuery, result] of options)
    if (window.matchMedia(mediaQuery).matches) return result

  return undefined
}

Теперь я проверяю это, высмеивая window.matchMedia перед каждым тестовым примером, подобным этому:

// simulate small screen window
window.matchMedia = mediaQuery => ({matches: mediaQuery === '(min-width: 320px)'}) // small screen
// run test then undo mocking

// simulate medium screen window
window.matchMedia = mediaQuery => ({matches: mediaQuery === '(min-width: 480px)'})
// run test then undo mocking

Я использую Jest и JSDOM, и window.matchMedia там не реализован, JSDOM не выполняет фактическую прорисовку.

Я бы хотел протестировать это сквозное без всяких насмешек , просто установив размеры окна, чтобы убедиться, что мой useResponsive хук работает должным образом.

Должен ли я выбрать какую-нибудь библиотеку тестирования e2e? Какой простой? Или есть другой вариант?

Обновление: исходный код для моих тестов atm

1 Ответ

1 голос
/ 23 декабря 2019

Вот решение для модульного тестирования:

useResponsive.ts:

export default function useResponsive<T>(options: Array<[string, T]>) {
  for (const [mediaQuery, result] of options) {
    if (window.matchMedia(mediaQuery).matches) {
      return result;
    }
  }

  return undefined;
}

useResponsive.spec.ts:

import useResponsive from './useResponsive';

describe('useResponsive', () => {
  afterEach(() => {
    jest.resetAllMocks();
  });
  it('should match media', () => {
    const mMediaQueryList = [];
    window.matchMedia = jest.fn().mockReturnValueOnce({ matches: mMediaQueryList });
    const options: Array<[string, string]> = [['(min-width: 400px)', 'some result']];
    const actual = useResponsive(options);
    expect(actual).toBe('some result');
  });

  it('should not match media', () => {
    window.matchMedia = jest.fn().mockReturnValueOnce({ matches: undefined });
    const options: Array<[string, string]> = [['(min-width: 400px)', 'some result']];
    const actual = useResponsive(options);
    expect(actual).toBeUndefined();
  });
});

jest.config.js:

module.exports = {
  preset: 'ts-jest/presets/js-with-ts',
};

Результат модульного теста со 100% покрытием:

 PASS  src/stackoverflow/59448015/useResponsive.spec.ts
  useResponsive
    ✓ should match media (5ms)
    ✓ should not match media (2ms)

------------------|----------|----------|----------|----------|-------------------|
File              |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------------|----------|----------|----------|----------|-------------------|
All files         |      100 |      100 |      100 |      100 |                   |
 useResponsive.ts |      100 |      100 |      100 |      100 |                   |
------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        3.578s

Исходный код: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59448015

...