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

时间:2018-10-30 04:56:22

标签: cypress

我正尝试通过以下方式访问Cypress中我的应用程序的窗口对象。

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

上述方法对我不起作用,因为window返回为undefined

不过,this SO post中的答案如下:

  

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

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

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

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

2 个答案:

答案 0 :(得分:2)

这经常出现。赛普拉斯有一些说明Commands are not 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
  })
})

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

赛普拉斯有一个叫做“命令”的东西,可以返回新的“ Chainers”。它是像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,但实际上不是承诺。赛普拉斯命令实际上已入队。赛普拉斯了解了mocha的生命周期,以确保beforebeforeEachitafterEachafter块等待,直到Cypress命令不再排队,然后再继续。

让我们看看这个例子:

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

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

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

这有点简化-赛普拉斯做了很多工作,以确保'Nicholas'仅在可以获得焦点并且可以交互的元素上运行。

现在,知道了这一点,您可以更简单地编写示例:

.type

答案 1 :(得分:0)

对我来说,the accepted answer 很好,但并没有真正向我展示什么是必要的。

对我来说,一切都是同步的,你可以做这样的事情,真是太棒了


let bg1 = null;

// simply store the value of a global object in the DOM
cy.window().then((win) => {
  bg1 = win.myPreciousGlobalObj.color;
});

// Do something that changes a global object
cy.get('a.dropdown-toggle').contains('File').click();

cy.window().then((win) => {
  const bg2 = win.myPreciousGlobalObj.color;
  // check if nodes and edges are loaded
  expect(bg1 != bg2).to.eq(true);
});

这里有趣的是,甚至 then 块内的东西都是同步的。这太有用了。