Во время тестирования, фронтенд тестируемого приложения, почти наверняка, взаимодействует с бекендом для отправки форм и запроса данных. В некоторых случая, когда тестируется приложение целиком, это не составляет проблемы, но иногда, приложение тестируется в изоляции, либо часть запросов не может быть выполнена и их нужно каким-то образом подменить.
В Playwright можно легко создавать mock API, что позволяет тестировать ваше приложение в контролируемой среде без реального взаимодействия с внешними сервисами. Это особенно полезно, когда вы хотите проверить поведение вашего приложения при различных ответах от сервера, например, при успешном ответе, ошибке или таймауте.
Mock APIs
Mock API в Playwright работает через перехват запросов. Вы можете настроить свой тестовый сценарий так, чтобы он перехватывал запросы к определённому URL и отвечал на них данными, которые вы определяете вручную. Это делается с помощью метода page.route().
Предположим, у вас есть приложение, которое делает запрос к API для получения списка пользователей при загрузке страницы. Вот пример того, как вы можете замокировать этот запрос в Playwright:
import { test, expect } from '@playwright/test'
test('mock API example', async ({ page }) => {
  // Создаём mock для запроса
  // */** - позволяет не указывать домен
  await page.route('*/**/users', (route) => {
    // Ответ, который будет отправлен вместо реального запроса
    const json = [
      { id: 1, firstName: 'Alice', lastName: 'Johnson', email: 'alicejohnson@email.com' },
      { id: 2, firstName: 'Bob', lastName: 'Smith', email: 'bobsmith@email.com' },
    ]
    // Ответить mock данными с кодом 200 (успех)
    route.fulfill({ json })
  })
  // Открываем страницу, которая делает запрос к API
  await page.goto('https://http.hexlet.app/js-playwright/users-list')
  // Проверяем, что mock данные правильно отобразились на странице
  const userNames = await page.getByRole('listitem').allTextContents()
  await expect(userNames).toEqual(['Alice Johnson alicejohnson@email.com', 'Bob Smith bobsmith@email.com'])
})
Создание мока происходит до выполнения действия, которое выполняет запрос иначе мок не сработает. Сам запрос перехватывается и на сервер ничего не уходит, но приложение об этом ничего не знает, для него запрос проходит успешно и возвращает какие-то данные. Дальше все работает как обычно.
Мок (mock) в Playwright работает, в рамках одного теста, до тех пор, пока вы не снимете его вручную или не завершите тест. Иными словами, каждый раз, когда приложение отправляет запрос, соответствующий маршруту, который вы перехватили с помощью page.route, Playwright будет использовать ваш мок.
Если нужно снять мок в середине теста, это можно сделать с помощью метода page.unroute():
await page.unroute('https://*/**/users')
В Playwright вы можете имитировать любой HTTP-ответ, включая ошибки, такие как 403 Forbidden. Это полезно для тестирования, как ваше приложение будет вести себя при получении отказа в доступе от сервера.
import { test, expect } from '@playwright/test'
test('mock API with 403 response', async ({ page }) => {
  // Создаём mock для ответа с кодом 403
  await page.route('https://http.hexlet.app/js-playwright/users/', (route) => {
    route.fulfill({
      status: 403,
    })
  })
  // Переходим на страницу, которая делает запрос на https://http.hexlet.app/js-playwright/users/
  await page.goto('https://http.hexlet.app/js-playwright/users-list')
  // Проверяем, что на странице отображается сообщение об ошибке доступа
  const header = await page.getByRole('heading', { name: 'Доступ ограничен' })
  await expect(header).toBeVisible()
})
Изменение ответа
Если вам нужно изменить ответ от реального сервера, а не просто замокировать его, в Playwright можно сначала позволить запросу пройти на сервер, а затем модифицировать полученный ответ перед тем, как он будет передан в приложение.
import { test, expect } from '@playwright/test'
test('mock API example', async ({ page }) => {
  await page.route('*/**/users', (route) => {
    // Ответ, который будет отправлен вместо реального запроса
    const data = [
      { id: 1, firstName: 'Alice', lastName: 'Johnson', email: 'aliceJohnson@email.com' },
      { id: 2, firstName: 'Bob', lastName: 'Smith', email: 'bobsmith@email.com' },
    ]
    const response = await route.fetch()
    const json = await response.json()
    json.push(...data)
    // Оригинальный ответ передается как response
    await route.fulfill({ response, json })
  })
  await page.goto('https://http.hexlet.app/js-playwright/users-list/')
  const userNames = await page.getByRole('listitem').allTextContents()
  await expect(userNames).toEqual(['Some Name From Server', 'Alice Johnson alicejohnson@email.com', 'Bob Smith bobsmith@email.com'])
})
Таким образом, этот подход позволяет вам работать с реальными данными, которые возвращает сервер, и при этом менять их по необходимости для тестирования различных сценариев.
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.