Это часто встречается. У Cypress есть документация о том, что Команды не являются обещаниями . Я сделал запись, используя пользовательскую команду, чтобы заставить командную цепочку вести себя как обещание, но она все еще экспериментальна и имеет нюансы.
Сначала я приведу ваш пример почти дословно к тому, что вы пытаетесь достичь:
cy.url().should('include', '/home').then(() => {
cy.window().then(win => {
console.log(win) // The window of your app, not `window` which is the Cypress window object
})
})
Ваш пример может быть написан несколькими способами, но, возможно, объяснение немного, как работает Cypress, поможет больше.
У Cypress есть нечто, называемое «Команды», которые возвращают новые «Цепи». Это гибкий синтаксис, такой как JQuery:
// fill and submit form
cy
.get('#firstname')
.type('Nicholas')
.get('#lastname')
.type('Boll')
.get('#submit')
.click()
Вы можете (и должны) разбивать цепочки, чтобы больше походить на предложения:
// fill and submit form
cy.get('#firstname').type('Nicholas')
cy.get('#lastname').type('Boll')
cy.get('#submit').click()
Возможно, вы догадались, что все команды Cypress Chainer являются асинхронными. У них есть .then
, но на самом деле они не обещания. Cypress команды на самом деле поставить в очередь. Cypress перехватывает жизненный цикл мокко, чтобы убедиться, что блок before
, beforeEach
, it
, afterEach
, after
ждет, пока команды Cypress больше не будут помещены в очередь, прежде чем продолжить.
Давайте рассмотрим этот пример:
it('should enter the first name', () => {
cy.get('#firstname').type('Nicholas')
})
В действительности Cypress видит команду cy.get
и ставит в очередь команду get
с аргументом '#firstname'
. Это немедленно (синхронно) возвращает выполнение к тесту. Затем Cypress видит команду cy.type
с аргументом 'Nicholas'
и немедленно возвращается к тесту. На данный момент тест технически выполнен, поскольку обратного вызова done
нет и обещание не возвращено. Но Cypress перехватывает жизненный цикл мокко и не выпускает тест до тех пор, пока команды в очереди не будут выполнены.
Теперь, когда у нас есть две команды в очереди, и тест ожидает Cypress, чтобы выпустить тест, команда get
выталкивается из очереди. Cypress будет пытаться найти элемент на странице с идентификатором firstname
, пока не найдет его или не истечет время ожидания. Предполагая, что он найдет элемент, он установит переменную состояния с именем subject
(cy.state('subject')
, но не полагайтесь на это). Следующая введенная в очередь команда type
захватит предыдущий subject
и попытается набрать каждый ключ из строки 'Nicholas'
по одному с задержкой по умолчанию 50 мс, пока строка не будет завершена. Теперь больше нет команд в очереди, и Cypress отменил тест, и бегун продолжает следующий тест.
Это было немного упрощено - Cypress делает намного больше, чтобы убедиться, что .type
работает только на элементах, которые могут получить фокус и являются интерактивными и т. Д.
Теперь, зная это, вы можете написать свой пример немного проще:
cy.url().should('include', '/home')
// No need for `.then` chaining or async/await. This is an enqueued command
cy.window().then(win => {
console.log(win)
})