Skip to content

Тестирование ​

responsive-media/testing заменяет window.matchMedia управляемым вьюпортом, так что тест может менять ширину, переключать пользовательское предпочтение и смотреть, как реагируют ваши компоненты — в Vitest или Jest с jsdom, у которого собственного matchMedia нет.

ts
import { createViewportMock } from 'responsive-media/testing'

Мок вьюпорта ​

createViewportMock(options?)

ViewportMock

Создаёт мок. Пока вы не вызовете install(), ничего не меняется.

ts
import { beforeEach, afterEach, it, expect } from 'vitest'
import { createResponsiveState } from 'responsive-media'
import { createViewportMock } from 'responsive-media/testing'

const viewport = createViewportMock({ width: 1280, height: 800 })

beforeEach(() => viewport.install())
afterEach(() => viewport.uninstall())

it('следует за вьюпортом', () => {
  const state = createResponsiveState({
    mobile: [{ type: 'max-width', value: 600 }],
    desktop: [{ type: 'min-width', value: 601 }],
  })
  expect(state.getState()).toEqual({ mobile: false, desktop: true })

  viewport.setViewport({ width: 500 })
  expect(state.getState()).toEqual({ mobile: true, desktop: false })
})
  • width, height — number · по умолчанию: 1280 и 800. Начальный размер.
  • features — Record<string, string> · по умолчанию: нет. Начальные значения пользовательских предпочтений.

Методы ​

  • install() — ставит мок на window.matchMedia и задаёт window.innerWidth и window.innerHeight.
  • uninstall() — восстанавливает matchMedia и размер окна и возвращает мок к начальному размеру и признакам, так что один мок можно использовать во всех тестах.
  • setViewport({ width?, height? }) — меняет размер, обновляет window.innerWidth и window.innerHeight, вызывает change у каждого запроса, который переключился, и отправляет событие resize, поэтому subscribeViewportSize() и useViewportSize() тоже следуют за размером.
  • setFeature(name, value) — меняет пользовательское предпочтение, например setFeature('prefers-color-scheme', 'dark'), и вызывает change у запросов, которые переключились.
  • getViewport() — текущий { width, height }.

Поддерживаемые запросы ​

Мок вычисляет media query, которые компонент скорее всего использует:

  • Размер — width, height и aspect-ratio с префиксами min- и max-, orientation и синтаксис диапазонов: (width <= 850px), (600px <= width <= 900px).
  • Комбинации — and, , (или), not, only и типы all, screen и print (print ложен, пока вы не задали setFeature('media-type', 'print')).
  • Пользовательские предпочтения — prefers-color-scheme, prefers-reduced-motion, prefers-contrast, hover, any-hover, pointer, any-pointer, forced-colors, display-mode со значениями десктопного браузера по умолчанию (светлая тема, без предпочтений, hover: hover, pointer: fine).

evaluateMediaQuery(query, size, features?)

boolean

Сам вычислитель — для быстрой проверки запроса на размере.

ts
import { evaluateMediaQuery } from 'responsive-media/testing'

evaluateMediaQuery('(width <= 850px)', { width: 800, height: 600 }) // true

Что он не мокает ​

ResizeObserver не мокается, поэтому состоянию контейнера нужна ваша собственная заглушка — пример есть в тестах самого пакета.