E2E тестирование

E2E (End-to-End) тестирование предназначено для проверки функциональности приложения в условиях, максимально приближенных к реальным. В контексте использования Radix UI это означает проверку работы интерактивных компонентов, таких как модальные окна, выпадающие списки, селекты и табы, во всей цепочке пользовательских действий — от взаимодействия с элементами до изменения состояния приложения.

Настройка окружения

Для E2E тестирования JavaScript-приложений с Radix UI чаще всего используют Cypress или Playwright. Основные шаги настройки включают:

  1. Установка библиотеки для E2E тестирования:
npm install --save-dev cypress
# или для Playwright
npm install --save-dev @playwright/test
  1. Инициализация конфигурации:
npx cypress open
# или
npx playwright test --init
  1. Настройка базового URL приложения и путей к тестовым файлам.

Важно помнить, что Radix UI строится на базе Headless UI компонентов, поэтому для тестирования требуется доступ к реальным DOM-элементам и управление состояниями компонентов через реальные события, такие как клики, фокус и изменение значений.

Тестирование модальных окон (Dialog)

Radix Dialog является полностью контролируемым компонентом. Основные сценарии для E2E:

  • Открытие модального окна при клике на триггер.
  • Проверка видимости контента модального окна.
  • Закрытие окна через крестик, кнопку или нажатие на overlay.
  • Сохранение состояния при взаимодействии с формой внутри диалога.

Пример Cypress-теста:

describe('Dialog component', () => {
  it('открывает и закрывает диалог', () => {
    cy.visit('/');
    cy.get('[data-testid="open-dialog"]').click();
    cy.get('[data-radix-dialog-content]').should('be.visible');
    cy.get('[data-testid="close-dialog"]').click();
    cy.get('[data-radix-dialog-content]').should('not.exist');
  });
});

Ключевое внимание уделяется атрибутам data-radix-*, которые Radix добавляет к элементам, облегчая их выбор для тестов.

Тестирование выпадающих списков (Dropdown Menu, Sel ect)

В E2E тестах необходимо проверять следующие аспекты:

  • Корректное открытие и закрытие меню.
  • Выбор элемента и обновление состояния.
  • Навигацию с клавиатуры (ArrowUp, ArrowDown, Enter, Escape).

Пример Playwright-теста для Radix Select:

import { test, expect } fr om '@playwright/test';

test('Select component работает корректно', async ({ page }) => {
  await page.goto('/');
  await page.click('[data-testid="select-trigger"]');
  await expect(page.locator('[data-radix-select-content]')).toBeVisible();
  await page.click('[data-radix-select-item="Option 2"]');
  await expect(page.locator('[data-testid="select-trigger"]')).toHaveText('Option 2');
});

Обращение к data-radix-select-item и проверка текста триггера позволяет убедиться в корректности работы компонента.

Тестирование табов (Tabs)

Для Radix Tabs важны следующие сценарии:

  • Переключение между вкладками.
  • Корректная активация контента соответствующей вкладки.
  • Проверка атрибутов aria-selected и aria-controls для доступности.

Пример Cypress-теста:

describe('Tabs component', () => {
  it('переключает вкладки и отображает правильный контент', () => {
    cy.visit('/');
    cy.get('[data-testid="tab-1"]').click().should('have.attr', 'aria-selected', 'true');
    cy.get('[data-testid="tab-content-1"]').should('be.visible');
    cy.get('[data-testid="tab-2"]').click().should('have.attr', 'aria-selected', 'true');
    cy.get('[data-testid="tab-content-2"]').should('be.visible');
  });
});

Особое внимание стоит уделять ARIA-атрибутам, так как Radix UI активно использует их для доступности, и неправильное управление ими может привести к неожиданным багам при тестировании.

Тестирование интерактивных состояний

Radix UI компоненты часто имеют сложные состояния:

  • Focus / Blur — важны для форм, селектов и радиокнопок.
  • Open / Close — модальные окна, меню и popover.
  • Disabled / ReadOnly — кнопки и интерактивные элементы.

Пример тестирования состояния focus для Popover:

cy.get('[data-testid="popover-trigger"]').focus();
cy.get('[data-radix-popover-content]').should('be.visible');
cy.get('[data-testid="popover-trigger"]').blur();
cy.get('[data-radix-popover-content]').should('not.exist');

Интеграция с CI/CD

Для стабильного E2E тестирования компонентов Radix UI рекомендуется:

  1. Настроить headless режим запуска (Cypress cypress run --headless или Playwright npx playwright test --headed=false).
  2. Использовать стабильные селекторы (data-testid или data-radix-*) вместо классов.
  3. Добавлять ожидания для асинхронных анимаций или рендеринга.
  4. Параллелить тесты для ускорения выполнения.

Практические советы

  • Использовать cy.findByRole или Playwright getByRole там, где это возможно, чтобы тесты были более доступными и независимыми от структуры DOM.
  • Избегать проверок внутренних стилей, лучше ориентироваться на видимость и наличие элементов.
  • Регулярно обновлять тесты при изменении структуры компонентов, так как Radix UI активно развивается и добавляет новые атрибуты и состояния.

E2E тестирование с Radix UI требует точного управления DOM-событиями, внимательного использования встроенных атрибутов и проверки интерактивных состояний, что позволяет создавать стабильные, надежные тесты для сложных интерфейсов.