Хотя модульные тесты дают разработчикам определенную степень уверенности, модульные и компонентные тесты ограничены в своих возможностях по обеспечению целостного покрытия приложения при его развертывании в production. E2E-тесты обеспечивают покрытие, пожалуй, самого важного аспекта приложения: того, что происходит, когда пользователи используют ваши приложения.
Простыми словами: функциональное тестирование проверяет как себя ведет приложение в браузере при эмуляции действий пользователя.
Где списать пока не нашёл, будем писать по официальной доке
E2e тесты лежат в каталоге ./site/e2e/ (т.к. относятся не к какому-то одному компоненту, а ко всему приложению)
Перед запуском тестов нужно настроить используемые браузеры в настройках ./site/playwright.config.js
Я отключил в секции projects браузеры firefox и webkit (нам для учебных целей хватит и одного)
import { test, expect } from '@playwright/test'
test('На странице есть блюда', async ({ page }) => {
await page.goto('/')
await expect(page.locator('.item')).toHaveCount(3)
})
await page.goto('/') - переходим на главную страницу (у нас она одна, а в многостраничных приложениях урлы могут быть разные)await expect(page.locator('.item')).toHaveCount(3)
locator аналог find из vitest - ищет на странице элементы (в нашем случае с классом item)toHaveCount проверяет количество найденных элементовДля закпуска теста выполните команду npm run test:e2e (если Playwright был установлен при создании приложения. Если добавляете тесты в уже существующее приложение, то сначала установите Playwright, а тесты можно запустить командой playwright test)
npm run test:e2e
> site@0.0.0 test:e2e
> playwright test
Running 1 test using 1 worker
1 passed (1.9s)
To open last HTML report run:
npx playwright show-report
В консоли не очень наглядно какие тесты выполнялись, в конце написано, что для формирования HTML-отчета нужно запустить команду npx playwright show-report
При запуске команды запускается http-сервер и появляется приглашение открыть страницу
npx playwright show-report
Serving HTML report at http://localhost:9323. Press Ctrl+C to quit.
Найдем на странице компонент с определённым блюдом и кликнем по кнопке с ценой. Убедимся, что на окне появилась корзина и итог корзины.
test('На странице есть блюдо "Салат" и при клике по нему появляется корзина', async ({ page }) => {
await page.goto('/')
const salat = page.getByText('Салат')
expect(salat).toBeTruthy()
const salatButton = salat
.locator('xpath=..')
.getByRole('button')
expect(salatButton).toBeTruthy()
await salatButton.click()
const cart = page.locator('.cart')
expect(cart).toBeTruthy()
expect(cart.getByText('Итого: 100')).toBeTruthy()
})
Разберёмся что тут понаписано:
Первым шагом ищем элемент с текстом "Салат":
const salat = page.getByText('Салат')`
И убеждаемся что он существует
expect(salat).toBeTruthy()
Теперь мы должны кликнуть по кнопке найденного компонента, но в предыдущем шаге мы нашли не весь компонент, а только его название
Напомню структуру компонента:
<div class="item">
<img />
<div>Салат</div>
<button>
</div>
Нам, чтобы найти элемент button нужно искать не у элемента salat, а у его родителя:
const salatButton = salat
.locator('xpath=..')
.getByRole('button')
Метод getByRole ищет в родительском элементе кнопку (роль это не тег, а текстовый алиас, со списком ролей можно познакомиться в доке)
На последнем шаге кликаем по найденной кнопке (дожидаясь перерисовки)
await salatButton.click()
И ищем элемент с классом cart и в нём текст с итогом
const cart = page.locator('.cart')
expect(cart).toBeTruthy()
expect(cart.getByText('Итого: 100')).toBeTruthy()
По предыдущему тесту видно, что иногда для поиска элемента нужно прилагать усилия (поиск от родителя). Для упрощения поиска можно добавить в компонент аттрибут data-testid и искать по нему. Например:
<div
class="item"
data-testid="Салат"
>
<img />
<div>Салат</div>
<button>
</div>
Тут я для простоты вписал просто название блюда, но в реальных проектах лучше использовать id блюда из базы.
И теперь поиск делается легло и просто:
const element = page.getByTestId('Салат')