Зарегистрируйтесь, чтобы продолжить обучение

Мок HTTP-запросов Тестирование с Playwright

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

В 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'])
})

Таким образом, этот подход позволяет вам работать с реальными данными, которые возвращает сервер, и при этом менять их по необходимости для тестирования различных сценариев.


Дополнительные материалы

  1. Официальная документация

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff