Перейти до основного вмісту

Імітації та шпигуни запитів

WebdriverIO має вбудовану підтримку для модифікації мережевих відповідей, що дозволяє зосередитися на тестуванні вашого фронтенд-додатку без необхідності налаштовувати бекенд або сервер-імітатор. Ви можете визначати власні відповіді для веб-ресурсів, таких як запити REST API у вашому тесті, та динамічно їх змінювати.

інфо

Зверніть увагу, що використання команди mock вимагає підтримки протоколу Chrome DevTools. Ця підтримка надається, якщо ви запускаєте тести локально в браузері на основі Chromium, через Selenium Grid v4 або вище, або через хмарного постачальника з підтримкою протоколу Chrome DevTools (наприклад, SauceLabs, BrowserStack, TestMu AI (Раніше LambdaTest)). Повна кросбраузерна підтримка буде доступна, коли необхідні примітиви будуть реалізовані в Webdriver Bidi та будуть впроваджені у відповідних браузерах.

Створення імітації

Перш ніж ви зможете модифікувати будь-які відповіді, вам потрібно спочатку визначити імітацію. Ця імітація описується URL-адресою ресурсу і може бути відфільтрована за методом запиту або заголовками. Ресурс підтримує глобальні вирази за допомогою minimatch:

// імітація всіх ресурсів, що закінчуються на "/users/list"
const userListMock = await browser.mock('**/users/list')

// або ви можете вказати імітацію, фільтруючи ресурси за заголовками або
// кодом статусу, імітувати тільки успішні запити до json ресурсів
const strictMock = await browser.mock('**', {
// імітувати всі json відповіді
requestHeaders: { 'Content-Type': 'application/json' },
// які були успішними
statusCode: 200
})

Визначення користувацьких відповідей

Після того, як ви визначили імітацію, ви можете визначити для неї користувацькі відповіді. Ці користувацькі відповіді можуть бути об'єктом для відповіді у форматі JSON, локальним файлом для відповіді з користувацьким шаблоном або веб-ресурсом для заміни відповіді ресурсом з інтернету.

Імітація API запитів

Щоб імітувати API запити, де ви очікуєте відповідь JSON, все, що вам потрібно зробити, це викликати respond на об'єкті імітації з довільним об'єктом, який ви хочете повернути, наприклад:

const mock = await browser.mock('https://todo-backend-express-knex.herokuapp.com/')

mock.respond([{
title: 'Injected (non) completed Todo',
order: null,
completed: false
}, {
title: 'Injected completed Todo',
order: null,
completed: true
}], {
headers: {
'Access-Control-Allow-Origin': '*'
},
fetchResponse: false
})

await browser.url('https://todobackend.com/client/index.html?https://todo-backend-express-knex.herokuapp.com/')

await $('#todo-list li').waitForExist()
console.log(await $$('#todo-list li').map(el => el.getText()))
// виводить: "[ 'Injected (non) completed Todo', 'Injected completed Todo' ]"

Ви також можете модифікувати заголовки відповіді, а також код статусу, передавши деякі параметри імітації відповіді наступним чином:

mock.respond({ ... }, {
// відповідати з кодом статусу 404
statusCode: 404,
// об'єднати заголовки відповіді з наступними заголовками
headers: { 'x-custom-header': 'foobar' }
})

Якщо ви не хочете, щоб імітація взагалі викликала бекенд, ви можете передати false для прапора fetchResponse.

mock.respond({ ... }, {
// не викликати справжній бекенд
fetchResponse: false
})

Рекомендується зберігати користувацькі відповіді у файлах шаблонів, щоб ви могли просто підключати їх у ваш тест наступним чином:

// потрібен Node.js v16.14.0 або вище для підтримки JSON import assertions
import responseFixture from './__fixtures__/apiResponse.json' assert { type: 'json' }
mock.respond(responseFixture)

Імітація текстових ресурсів

Якщо ви хочете модифікувати текстові ресурси, такі як файли JavaScript, CSS або інші текстові ресурси, ви можете просто передати шлях до файлу, і WebdriverIO замінить оригінальний ресурс ним, наприклад:

const scriptMock = await browser.mock('**/script.min.js')
scriptMock.respond('./tests/fixtures/script.js')

// або відповісти вашим власним JS
scriptMock.respond('alert("I am a mocked resource")')

Перенаправлення веб-ресурсів

Ви також можете просто замінити веб-ресурс іншим веб-ресурсом, якщо ваша бажана відповідь вже розміщена в інтернеті. Це працює як з окремими ресурсами сторінки, так і з самою веб-сторінкою, наприклад:

const pageMock = await browser.mock('https://google.com/')
await pageMock.respond('https://webdriver.io')
await browser.url('https://google.com')
console.log(await browser.getTitle()) // повертає "WebdriverIO · Next-gen browser and mobile automation test framework for Node.js"

Динамічні відповіді

Якщо ваша імітаційна відповідь залежить від відповіді оригінального ресурсу, ви також можете динамічно модифікувати ресурс, передавши функцію, яка отримує оригінальну відповідь як параметр і встановлює імітацію на основі повернутого значення, наприклад:

const mock = await browser.mock('https://todo-backend-express-knex.herokuapp.com/', {
method: 'get'
})

mock.respond((req) => {
// замінити вміст todo на їх номер у списку
return req.body.map((item, i) => ({ ...item, title: i }))
})

await browser.url('https://todobackend.com/client/index.html?https://todo-backend-express-knex.herokuapp.com/')

await $('#todo-list li').waitForExist()
console.log(await $$('#todo-list li label').map((el) => el.getText()))
// повертає
// [
// '0', '1', '2', '19', '20',
// '21', '3', '4', '5', '6',
// '7', '8', '9', '10', '11',
// '12', '13', '14', '15', '16',
// '17', '18', '22'
// ]

Переривання імітацій

Замість повернення користувацької відповіді ви також можете просто перервати запит з однією з наступних HTTP помилок:

  • Failed
  • Aborted
  • TimedOut
  • AccessDenied
  • ConnectionClosed
  • ConnectionReset
  • ConnectionRefused
  • ConnectionAborted
  • ConnectionFailed
  • NameNotResolved
  • InternetDisconnected
  • AddressUnreachable
  • BlockedByClient
  • BlockedByResponse

Це дуже корисно, якщо ви хочете заблокувати сторонні скрипти з вашої сторінки, які мають негативний вплив на ваш функціональний тест. Ви можете перервати імітацію, просто викликавши abort або abortOnce, наприклад:

const mock = await browser.mock('https://www.google-analytics.com/**')
mock.abort('Failed')

Шпигуни

Кожна імітація автоматично є шпигуном, який підраховує кількість запитів, які браузер зробив до цього ресурсу. Якщо ви не застосовуєте користувацьку відповідь або причину переривання до імітації, вона продовжується з стандартною відповіддю, яку ви зазвичай отримали б. Це дозволяє вам перевірити, скільки разів браузер зробив запит, наприклад, до певної кінцевої точки API.

const mock = await browser.mock('**/user', { method: 'post' })
console.log(mock.calls.length) // повертає 0

// зареєструвати користувача
await $('#username').setValue('randomUser')
await $('password').setValue('password123')
await $('password_repeat').setValue('password123')
await $('button[type="submit"]').click()

// перевірити, чи був зроблений API запит
expect(mock.calls.length).toBe(1)

// перевірити відповідь
expect(mock.calls[0].body).toEqual({ success: true })

Якщо вам потрібно дочекатися, поки на відповідний запит буде отримано відповідь, використовуйте mock.waitForResponse(options). Дивіться API-довідник: waitForResponse.

Welcome! How can I help?

WebdriverIO AI Copilot