route
Используйте cy.route() для управления поведением сетевых запросов.
⚠️
cy.server()иcy.route()устарели в Cypress 6.0.0. В будущих релизах поддержкаcy.server()иcy.route()будет удалена. Рассмотрите использованиеcy.intercept()вместо этого. См. наше руководство по миграцииcy.route()кcy.intercept()
⚠️
cy.route()иcy.server()поддерживают только перехват XMLHttpRequests. Запросы, использующие API Fetch и другие типы сетевых запросов, такие как загрузка страниц и<script>теги, не будут перехватыватьсяcy.route()иcy.server().Для поддержки запросов, использующих API Fetch, вы можете использовать одно из решений ниже:
- Используйте
cy.intercept(), которое поддерживает запросы, использующие API Fetch, и другие типы сетевых запросов, такие как загрузка страниц. См.cy.intercept().- Используйте полифилл
window.fetchдля слежки за запросами и подстановки ответов, использующихcy.route()иcy.server()путём включенияexperimentalFetchPolyfill. См. #95 для более подробной информации и временных решений.
Синтаксис
cy.route(url)
cy.route(url, response)
cy.route(method, url)
cy.route(method, url, response)
cy.route(callbackFn)
cy.route(options)
Использование
Правильное использование
cy.route('/users/**')
Аргументы
url (Строка, Шаблон, Регулярное выражение)
Прослушивает маршрут, соответствующий определённому URL.
response (Строка, Объект, Массив)
Предоставляет ответ body для моделирования на совпадающем маршруте.
method (Строка)
Сопоставляет маршрут со специфическим методом (GET, POST, PUT, и т.д.).
Если метод не определён, Cypress по умолчанию будет сопоставлять запросы
GET.
callbackFn (Функция)
Прослушивает маршрут, соответствующий возвращаемому объекту из функции обратного вызова. Функции, возвращающие Promise , будут автоматически ожидать завершения.
options (Объект)
Передайте объект опций, чтобы изменить стандартное поведение cy.route(). По умолчанию cy.route() наследует свои опции от cy.server().
| Опция | Значение по умолчанию | Описание |
|---|---|---|
delay |
0 |
Задержка для смоделированных ответов (в мс) |
force404 |
false |
Принудительно отправляет статус 404, когда XHR не соответствует ни одному существующему cy.route(). |
headers |
null |
Заголовки ответа для смоделированных маршрутов |
method |
GET |
Метод для сопоставления с запросами |
onAbort |
null |
Функция обратного вызова, срабатывающая при прерывании XHR |
onRequest |
null |
Функция обратного вызова при отправке запроса |
onResponse |
null |
Функция обратного вызова при возвращении ответа |
response |
null |
Тело ответа при моделировании маршрутов |
status |
200 |
Код статуса ответа при моделировании маршрутов |
url |
null |
Строка или регулярное выражение URL для сопоставления с URL запросов |
Вы также можете установить опции для всех cy.wait() по умолчанию requestTimeout и responseTimeout в конфигурации, чтобы управлять временем ожидания запроса и ответа предоставленного маршрута.
Возвращаемые значения
-
cy.route()возвращаетnull. -
cy.route()может быть переименован, но в дальнейшем не может быть использован в цепочке.
Примеры
Без моделирования
Если вы не передаёте response в маршрут, Cypress пропустит запрос без моделирования. Мы всё равно можем ожидать разрешения запроса позже.
Ожидание XHR GET запроса, соответствующего url
cy.server()
cy.route('**/users').as('getUsers')
cy.visit('/users')
cy.wait('@getUsers')
Ожидание XHR, соответствующих method и url
cy.server()
cy.route('POST', '**/users').as('postUser')
cy.visit('/users')
cy.get('#first-name').type('Julius{enter}')
cy.wait('@postUser')
Настройка маршрута POST для входа в систему
Посмотрите наш пример рецепта использования
cy.route()для POST-запроса входа в HTML-формы
Ожидание url, соответствующего шаблону
Внутри Cypress используется minimatch для сопоставления шаблонов glob url.
Это означает, что вы можете воспользоваться поддержкой * и ** шаблонов glob. Это значительно упрощает маршрутизацию по динамическим сегментам без необходимости создания сложной RegExp.
Мы предоставляем Cypress.minimatch как функцию, которую вы можете использовать в своём консоли для тестирования маршрутов.
Сопоставление маршрута с любым UserId
cy.server()
cy.route('**/users/*/comments')
// https://localhost:7777/users/123/comments <-- matches
// https://localhost:7777/users/123/comments/465 <-- does not match
Использование шаблона glob для сопоставления всех сегментов
cy.server()
cy.route('**/posts/**')
// https://localhost:7777/posts/1 <-- matches
// https://localhost:7777/posts/foo/bar/baz <-- matches
// https://localhost:7777/posts/quuz?a=b&1=2 <-- matches
Переопределение url опций сопоставления шаблонов glob
При проверке glob шаблонов с помощью minimatch, по умолчанию Cypress устанавливает matchBase в true. Вы можете переопределить эту опцию в опциях cy.server().
Если вы хотите постоянно переопределить эти опции, вы можете сделать это, установив Cypress.Server.defaults().
cy.server({
urlMatchingOptions: { matchBase: false, dot: true }
})
cy.route(...)
С моделированием
Если вы передаёте response в cy.route(), Cypress смоделирует ответ на запрос.
url как строка
При передаче string как url, URL XHR должен точно соответствовать вашей записи. Вам необходимо использовать декодированную строку и не включать хеш-кодирование (то есть используйте @ вместо %40).
cy.server()
cy.route('https://localhost:7777/surveys/customer?email=john@doe.com', [
{
id: 1,
name: 'john',
},
])
url как регулярное выражение
При передаче регулярного выражения как url, URL XHR будет проверен на соответствие регулярному выражению, если пройдёт проверку.
cy.server()
cy.route(/users\/\d+/, { id: 1, name: 'Phoebe' })
// Application Code
$.get('https://localhost:7777/users/1337', (data) => {
console.log(data) // => {id: 1, name: "Phoebe"}
})
Функции ответа
Вы также можете использовать функцию в качестве ответа, что позволит вам добавить логику, относящуюся к ответу.
Функции, возвращающие Promise , будут автоматически ожидать завершения.
const commentsResponse = (routeData) => {
//routeData is a reference to the current route's information
return {
data: someOtherFunction(routeData),
}
}
cy.route('POST', '**/comments', commentsResponse)
Сопоставление запросов и маршрутов
Любой запрос, соответствующий method и url маршрута, будет обработаться в соответствии с его конфигурацией.
GET— это метод HTTP по умолчанию для сопоставления маршрутов. Если вы хотите смоделировать маршрут с другим методом HTTP, например,POST, то вам необходимо явно указать метод.
Если запрос не соответствует ни одному маршруту, поведение зависит от значения опции
force404вcy.server():
- если
force404равноfalse(по умолчанию), то запрос будет передан серверу.- если
force404равноtrue, то ответ будет 404.Вы можете узнать больше об этом поведении здесь.
Указание метода
В следующем примере все запросы DELETE на "/users" моделируют ответ с пустым JSON-объектом.
cy.server()
cy.route('DELETE', '**/users/*', {})
Отправка нескольких запросов на один и тот же маршрут
Вы можете тестировать маршрут несколько раз с уникальными объектами ответов, используя алиасы и cy.wait(). Каждый раз, когда мы используем cy.wait() для алиаса, Cypress ожидает следующего n-го совпадающего запроса.
cy.server()
cy.route('/beetles', []).as('getBeetles')
cy.get('#search').type('Weevil')
// wait for the first response to finish
cy.wait('@getBeetles')
// the results should be empty because we
// responded with an empty array first
cy.get('#beetle-results').should('be.empty')
// now re-define the /beetles response
cy.route('/beetles', [{ name: 'Geotrupidae' }])
cy.get('#search').type('Geotrupidae')
// now when we wait for 'getBeetles' again, Cypress will
// automatically know to wait for the 2nd response
cy.wait('@getBeetles')
// we responded with 1 beetle item so now we should
// have one result
cy.get('#beetle-results').should('have.length', 1)
Фикстуры
Вместо написания ответа непосредственно вы можете автоматически подключить ответ с помощью cy.fixture().
cy.server()
cy.route('**/posts/*', 'fixture:logo.png').as('getLogo')
cy.route('**/users', 'fixture:users/all.json').as('getUsers')
cy.route('**/admin', 'fx:users/admin.json').as('getAdmin')
Вы можете определить cy.route() после получения фикстуры и работы с её данными.
cy.fixture('user').then((user) => {
user.firstName = 'Jane'
// work with the users array here
cy.route('GET', '**/user/123', user)
})
cy.visit('/users')
cy.get('.user').should('include', 'Jane')
Вы также можете ссылаться на фикстуры как на строки напрямую в ответе, передавая алиасированные фикстуры с @.
cy.fixture('user').as('fxUser')
cy.route('POST', '**/users', '@fxUser')
Опции
Передача объекта опций
cy.server()
cy.route({
method: 'DELETE',
url: '**/user/*',
status: 412,
response: {
rolesCount: 2,
},
delay: 500,
headers: {
'X-Token': null,
},
onRequest: (xhr) => {
// do something with the
// raw XHR object when the
// request initially goes out
},
onResponse: (xhr) => {
// do something with the
// raw XHR object when the
// response comes back
},
})
Моделирование перенаправления сервера
Ниже мы моделируем возврат сервера 503 со stubbed пустым JSON ответом.
cy.route({
method: 'POST',
url: '**/login',
response: {
// simulate a redirect to another page
redirect: '/error',
},
})
Настройка маршрута для ошибки при POST на вход в систему
Изменение headers
По умолчанию Cypress автоматически устанавливает Content-Type и Content-Length на основе того, как выглядит ваш response body.
Если вы хотите переопределить это, явно передайте headers в виде объекта.
cy.route({
url: '**/user-image.png',
response: 'fx:logo.png,binary', // binary encoding
headers: {
// set content-type headers
'content-type': 'binary/octet-stream',
},
})
Использование задержек для ответов
Вы можете передать параметр delay, который вызывает задержку (в мс) для response для совпадающих запросов. Приведенный ниже пример приведет к задержке ответа на 3 секунды. Это может быть полезно для тестирования состояний загрузки, таких как загрузка спиннеров, в DOM перед ответом на запрос.
cy.route({
method: 'PATCH',
url: '**/activities/*',
response: {},
delay: 3000,
})
Функция
Установка параметров маршрутизации с помощью функции обратного вызова
cy.route(() => {
// ...do some custom logic here..
// and return an appropriate routing object here
return {
method: 'POST',
url: '**/users/*/comments',
response: this.commentsFixture,
}
})
Функции, возвращающие промисы, ожидают их выполнения
cy.route(() => {
// a silly example of async return
return new Cypress.Promise((resolve) => {
// resolve this promise after 1 second
setTimeout(() => {
resolve({
method: 'PUT',
url: '**/posts/**',
response: '@postFixture',
})
}, 1000)
})
})
Примечания
Отладка
Понимание различия между подставленными и обычными XHR
Cypress указывает, был ли XHR возвращен подставленным ответом или действительно отправлен на сервер в журнале команд.
XHR, которые отображают (XHR STUB) в журнале команд, были подставлены, и их ответ, статус, заголовки и задержка контролировались соответствующим cy.route().
XHR, которые отображают (XHR) в журнале команд, не были подставлены и были переданы непосредственно на сервер.
Cypress также записывает в консоль, был ли XHR подставлен или нет, когда вы нажимаете на команду в журнале команд. Это укажет, был ли запрос подставленным, какой URL он сопоставил или что он не сопоставил ни одного маршрута.
Также включен Initiator, который представляет собой стек вызовов, вызвавший отправку XHR.
cy.route() нельзя отлаживать с помощью cy.request()
cy.request() отправляет запросы на фактические конечные точки, минуя те, которые определены с использованием cy.route()
Целью cy.request() является проверка конечных точек на фактическом работающем сервере без необходимости запуска приложения на стороне клиента.
Соответствия
Сопоставление доменов и URL без указания домена
При сопоставлении Cypress исходящего запроса XHR с cy.route(), он фактически пытается сопоставить его как с полным URL, так и без указания домена URL.
cy.route('**/users/*')
Следующие XHR, которые были xhr.open(...) с этими URL, будут:
Совпадают:
/users/1http://localhost:2020/users/2https://google.com/users/3
Не совпадают:
/users/4/foohttp://localhost:2020/users/5/foo
Отсутствие соответствий
Запросы, не соответствующие ни одному маршруту
Вы можете заставить запросы, которые не соответствуют маршруту, возвращать статус 404 и пустое тело, передав параметр в cy.server() следующим образом:
cy.server({ force404: true })
Вы можете прочитать больше об этом здесь.
Правила
Требования
-
cy.route()требует быть привязанным кcy.
Ассерции
-
cy.route()не может содержать связанных ассерций.
Таймауты
-
cy.route()не может иметь таймауты.
Журнал команд
cy.server()
cy.route(/accounts/).as('accountsGet')
cy.route(/company/, 'fixtures:company').as('companyGet')
cy.route(/teams/, 'fixtures:teams').as('teamsGet')
Всякий раз, когда вы запускаете сервер и добавляете маршруты, Cypress отобразит новую панель инструментов под названием «Маршруты». Она будет отображать таблицу маршрутизации на панели инструментов, включая method, сопоставленный шаблон URL, stubbed, alias и количество сопоставленных запросов:
При выполнении XHR Cypress будет регистрировать их в журнале команд и указывать, соответствуют ли они псевдониму маршрутизации:
Круговой индикатор заполнен, если запрос был отправлен на целевой сервер, но не заполнен, если запрос был подставлен с ответом.
Дополнительная информация о регистрации запросов в Cypress.
История
| Версия | Изменения |
|---|---|
| 6.0.0 | Команда cy.route() устарела |
См. также
© 2017 Cypress.io
Licensed under the MIT License.
https://docs.cypress.io/api/commands/route