Component Testing в Playwright

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

Playwright поддерживает Component Testing через интеграцию с фреймворками, такими как React, Vue и Angular. Основной принцип — запуск компонента в виртуальном контейнере с эмуляцией браузера, что позволяет использовать привычные селекторы, события и ассерты.


Настройка Component Testing

Для начала необходимо установить пакет @playwright/experimental-ct, который обеспечивает функциональность компонентного тестирования:

npm install -D @playwright/experimental-ct

Далее настраивается конфигурация Playwright в файле playwright.config.js:

import { defineConfig, devices } from '@playwright/experimental-ct-react';

export default defineConfig({
  testDir: './tests',
  use: {
    viewport: { width: 1280, height: 720 },
    ctPort: 3100, 
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],
});

Здесь ctPort указывает порт, на котором будет запускаться изолированный контейнер для компонента. Настройка проектов позволяет тестировать компонент в разных браузерах.


Создание тестов компонентов

Тест компонента в Playwright создаётся аналогично обычному тесту, с использованием объекта mount, который рендерит компонент в тестовом контейнере.

Пример для React:

import { test, expect } from '@playwright/experimental-ct-react';
import { Button } from '../src/components/Button';

test('кнопка отображает текст и реагирует на клик', async ({ mount }) => {
  const component = await mount(<Button label="Нажми меня" />);
  
  await expect(component).toHaveText('Нажми меня');
  
  await component.click();
  await expect(component).toHaveClass(/clicked/);
});

Ключевые моменты:

  • mount(<Component />) — монтирует компонент в виртуальном DOM.
  • Ассерты toHaveText, toHaveClass, toBeVisible проверяют состояние компонента.
  • Взаимодействия с компонентом (клик, ввод текста, hover) полностью поддерживаются.

Работа с состоянием и пропсами

Component Testing позволяет передавать пропсы и управлять состоянием компонента без необходимости запускать всё приложение. Это особенно удобно для тестирования:

  • Валидации форм
  • Динамического отображения элементов
  • Событий и колбеков

Пример передачи пропсов:

test('форма отправки отображает ошибку при пустом поле', async ({ mount }) => {
  const form = await mount(<Form initialValues={{ email: '' }} />);
  
  await form.locator('button[type="submit"]').click();
  await expect(form.locator('.error')).toHaveText('Поле email обязательно');
});

Интеграция с глобальными провайдерами

Для компонентов, использующих контекст (Redux, React Context, Vuex), Playwright позволяет оборачивать их в провайдеры:

import { test, expect } from '@playwright/experimental-ct-react';
import { Provider } from 'react-redux';
import { store } from '../src/store';
import { TodoList } from '../src/components/TodoList';

test('список задач отображает задачи из стора', async ({ mount }) => {
  const component = await mount(
    <Provider store={store}>
      <TodoList />
    </Provider>
  );

  await expect(component.locator('.todo-item')).toHaveCount(3);
});

Такой подход позволяет тестировать компонент в контексте приложения без запуска полноценной страницы.


Асинхронные компоненты и загрузка данных

Компоненты, которые подгружают данные асинхронно, требуют использования await для ожидания рендеринга и обновления DOM:

test('список пользователей отображается после загрузки', async ({ mount }) => {
  const Users = await mount(<UserList />);
  
  await expect(Users.locator('.loading')).toBeVisible();
  await Users.waitForSelector('.user-item');
  await expect(Users.locator('.user-item')).toHaveCount(5);
});

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


Взаимодействие с элементами и события

Component Testing поддерживает все стандартные события браузера:

  • click()
  • fill()
  • hover()
  • press()

Можно комбинировать события для тестирования сложной логики интерфейса:

test('интерактивная кнопка меняет текст при клике', async ({ mount }) => {
  const button = await mount(<ToggleButton initialState="Включено" />);
  
  await button.click();
  await expect(button).toHaveText('Выключено');
  
  await button.click();
  await expect(button).toHaveText('Включено');
});

Советы по эффективному Component Testing

  • Изоляция: тестировать компонент отдельно от всей страницы или приложения. Любые зависимости следует мокать.
  • Минимализм пропсов: передавать только необходимые данные для теста.
  • Асинхронность: всегда ожидать рендер и DOM-обновления перед проверками.
  • Масштабирование: для крупных приложений можно создавать отдельные директории components с тестами рядом с кодом компонента.

Поддержка нескольких фреймворков

Playwright CT поддерживает:

  • React через @playwright/experimental-ct-react
  • Vue через @playwright/experimental-ct-vue
  • Angular через @playwright/experimental-ct-angular

Каждый адаптер предоставляет собственный mount и интеграцию с системой рендеринга фреймворка, сохраняя одинаковый API тестов.


Отладка компонентных тестов

Playwright предоставляет возможность запуска теста в интерактивном режиме:

npx playwright test --ui

В UI можно:

  • Ставить брейкпойнты
  • Просматривать DOM компонента
  • Выполнять тест пошагово

Это ускоряет диагностику ошибок в компонентах с динамическим поведением.


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