赛普拉斯中难以访问窗口对象

use*_*888 2 cypress

我试图通过以下方式在赛普拉斯中访问我的应用程序的窗口对象。

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

上面的方法对我不起作用,window返回为undefined

但是,此SO帖子中的答案如下:

或者,您可以使用cy.state('window')来同步返回窗口对象,但这是未记录的,将来可能会更改。

此方法确实成功返回窗口值。

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

正如答案所暗示的那样,cy.state('window')是未记录的,因此我还是想使用cy.window()。有什么原因会返回未定义?(我今天开始学习柏树。)

Nic*_*oll 7

这经常出现。赛普拉斯有一些文档说明“ 命令不是Promises”。我使用自定义命令进行了写操作,以强制命令链的行为像promise,但是它仍然是实验性和细微差别的。

首先,我将逐字逐句地给出您要达到的目标的示例:

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
  })
})
Run Code Online (Sandbox Code Playgroud)

您的示例可以用多种方式编写,但也许可以稍微解释一下赛普拉斯的工作方式会有所帮助。

赛普拉斯有一个叫做“命令”的东西,可以返回新的“ Chainers”。它是像JQuery这样的易变的语法:

// fill and submit form
cy
  .get('#firstname')
  .type('Nicholas')
  .get('#lastname')
  .type('Boll')
  .get('#submit')
  .click()
Run Code Online (Sandbox Code Playgroud)

您可以(并且应该)分解链条,使其更像句子:

// fill and submit form
cy.get('#firstname').type('Nicholas')
cy.get('#lastname').type('Boll')
cy.get('#submit').click()
Run Code Online (Sandbox Code Playgroud)

您可能已经猜到所有Cypress Chainer命令都是异步的。他们有一个.then,但实际上不是承诺。赛普拉斯命令实际上已入队。赛普拉斯挂接到摩卡的生命周期,以确保一个beforebeforeEachitafterEachafter块等待,直到赛普拉斯命令不再继续之前入队。

让我们来看这个例子:

it('should enter the first name', () => {
  cy.get('#firstname').type('Nicholas')
})
Run Code Online (Sandbox Code Playgroud)

实际发生的是Cypress看到cy.getCommand,并在get命令中加入了参数'#firstname'。立即(同步)将执行返回测试。然后,赛普拉斯将看到cy.type带有参数的命令,'Nicholas'并立即返回测试。由于没有done回调并且也没有返回Promise,因此在技​​术上该测试已完成。但是赛普拉斯陷入了摩卡咖啡的生命周期,直到排队的命令完成后才发布测试。

现在我们有了2个排队的命令,并且测试正在等待Cypress释放测试,该get命令从队列中弹出。赛普拉斯将尝试在页面上firstname查找ID为的元素,直到找到该元素或该元素超时。假设找到了元素,它将设置一个名为subjectcy.state('subject'),但不要依赖于此)的状态变量。下一个排队的命令type将抓住前一个命令,subject并尝试一次从字符串中'Nicholas'一次键入每个键,默认延迟为50ms,直到完成字符串为止。现在,不再有排队的命令,赛普拉斯将释放测试,跑步者将继续进行下一个测试。

这样做有点简化-赛普拉斯做了很多工作,以确保.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)
})
Run Code Online (Sandbox Code Playgroud)