Media devices

Cypress предоставляет мощные возможности для тестирования веб-приложений, взаимодействующих с медиапристройствами — камерами, микрофонами и экранами. Правильная организация тестов с медиадоступом критически важна для приложений, реализующих видеозвонки, запись аудио, стриминг и другие функции реального времени.

Настройка доступа к медиапристройствам

По умолчанию браузеры требуют явного разрешения пользователя для использования камеры и микрофона. В тестах Cypress необходимо обходить эти ограничения с помощью конфигурации браузера.

Для Chrome и Chromium-подобных браузеров можно использовать флаги:

// cypress.config.js
const { defineConfig } = require('cypress');

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      // здесь можно добавить плагины
    },
    chromeWebSecurity: false,
    defaultCommandTimeout: 10000,
    viewportWidth: 1280,
    viewportHeight: 720,
  },
  env: {
    mediaPermissions: true
  }
});

При запуске тестов можно указать флаги браузера для автоматического предоставления разрешений:

cypress open --browser chrome --config video=false

В тестах можно использовать cy.visit() с параметрами, эмулирующими разрешение доступа к камере и микрофону.

Эмуляция медиапотоков

Для тестирования функционала без реальных устройств удобно использовать фиктивные медиапотоки. В браузерах Chromium это реализуется через флаги:

--use-fake-ui-for-media-stream
--use-fake-device-for-media-stream

Эти флаги позволяют:

  • Игнорировать диалоги разрешений.
  • Использовать заранее заданные видео и аудио потоки.
  • Поддерживать стабильные тесты без физического оборудования.

Пример запуска Cypress с этими флагами через Node:

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      on('before:browser:launch', (browser = {}, launchOptions) => {
        if (browser.family === 'chromium') {
          launchOptions.args.push('--use-fake-ui-for-media-stream');
          launchOptions.args.push('--use-fake-device-for-media-stream');
        }
        return launchOptions;
      });
    }
  }
});

Проверка работы медиапристроек

Для тестирования доступа к камере и микрофону необходимо проверять наличие и активность медиапотоков. Cypress позволяет делать это через команду cy.window(), получая объект navigator.mediaDevices:

cy.window().then((win) => {
  return win.navigator.mediaDevices.getUserMedia({ video: true, audio: true });
}).then((stream) => {
  // Проверка, что поток содержит треки
  expect(stream.getVideoTracks()).to.have.length.greaterThan(0);
  expect(stream.getAudioTracks()).to.have.length.greaterThan(0);
});

Также полезно проверять события остановки и включения треков:

stream.getVideoTracks()[0].stop();
expect(stream.getVideoTracks()[0].readyState).to.eq('ended');

Интеграция с элементами DOM

Видео и аудио элементы на странице должны корректно получать медиапотоки:

cy.get('video#localVideo').then(($video) => {
  cy.window().then((win) => {
    win.navigator.mediaDevices.getUserMedia({ video: true, audio: true })
      .then((stream) => {
        $video[0].srcObject = stream;
        $video[0].play();
      });
  });
});

Важно убедиться, что тесты корректно ожидают воспроизведение медиапотоков, используя проверки readyState или события onplaying:

cy.get('video#localVideo').should(($video) => {
  expect($video[0].readyState).to.be.greaterThan(2); // HAVE_CURRENT_DATA
});

Симуляция различных условий

Тестирование медиапристроек должно включать сценарии с:

  • Недоступными устройствами.
  • Одновременным подключением нескольких камер или микрофонов.
  • Прерываниями потоков и изменением состояния треков.

Для эмуляции можно использовать мок getUserMedia:

cy.window().then((win) => {
  cy.stub(win.navigator.mediaDevices, 'getUserMedia').callsFake(() => {
    return Promise.resolve({
      getVideoTracks: () => [{ kind: 'video', stop: () => {} }],
      getAudioTracks: () => [{ kind: 'audio', stop: () => {} }]
    });
  });
});

Логирование и отладка медиатестов

Cypress позволяет добавлять подробное логирование состояния медиапотоков:

  • Текущее состояние треков (readyState, muted, enabled).
  • Количество аудио и видео треков.
  • Ошибки получения доступа (NotAllowedError, NotFoundError).
cy.window().then((win) => {
  win.navigator.mediaDevices.getUserMedia({ video: true, audio: true })
    .then((stream) => {
      stream.getTracks().forEach(track => {
        console.log(track.kind, track.enabled, track.readyState);
      });
    }).catch((err) => console.error('Media error:', err));
});

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

Для приложений с видеозвонками важно тестировать подключение peer-to-peer:

  • Проверка создания RTCPeerConnection.
  • Эмуляция добавления и удаления треков через addTrack и removeTrack.
  • Слежение за событиями ontrack, onicecandidate, connectionstatechange.

Cypress позволяет интегрировать эти проверки через команды cy.window() и взаимодействие с элементами DOM, содержащими видеопотоки.

Практические рекомендации

  • Всегда использовать флаги эмуляции устройств для стабильных тестов CI/CD.
  • Проверять наличие треков перед взаимодействием с DOM-элементами.
  • Мокировать getUserMedia для негативных сценариев.
  • Разделять тесты на блоки: доступ к устройствам, отображение на странице, обработка ошибок.
  • Логировать состояние треков и события WebRTC для диагностики проблем.

Эффективное тестирование медиапристроек обеспечивает стабильность приложений с аудио- и видеофункционалом, позволяет выявлять ошибки на ранних этапах разработки и гарантирует корректное поведение при любых условиях доступа к устройствам.