Трудность доступа к объекту окна в Cypress - PullRequest
0 голосов
/ 30 октября 2018

Я пытаюсь получить доступ к объекту окна моего приложения в Cypress следующим образом.

cy.url().should('include', '/home').then(async () => {
    const window = await cy.window();
    console.log(window);
});

Вышеуказанный метод не работает для меня, так как window возвращается как undefined.

Однако, ответ в этом SO сообщении гласит следующее:

Или вы можете использовать cy.state ('window'), который возвращает объект окна синхронно, но это недокументировано и может измениться в будущем.

Этот метод действительно возвращает значение окна успешно.

cy.url().should('include', '/home').then(async () => {
    const window = cy.state('window');
    console.log(window);
});

Как следует из ответа, cy.state («окно») недокументировано, поэтому я все равно предпочел бы использовать cy.window (). Есть ли какая-то причина, почему он возвращает undefined? (Я начал изучать кипарис сегодня.)

1 Ответ

0 голосов
/ 30 октября 2018

Это часто встречается. У 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)
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...