难以访问 Cypress 中的 window 对象
Difficulty accessing window object in Cypress
我正在尝试通过以下方式在 Cypress 中访问我的应用程序的 window 对象。
cy.url().should('include', '/home').then(async () => {
const window = await cy.window();
console.log(window);
});
上述方法对我不起作用,因为 window
被 return 编辑为 undefined
。
但是, 中的答案如下:
Or you can use cy.state('window') which returns the window object
synchronously, but this is undocumented and may change in the future.
此方法 return window 值成功。
cy.url().should('include', '/home').then(async () => {
const window = cy.state('window');
console.log(window);
});
如答案所示,cy.state('window') 没有记录,所以我还是宁愿使用 cy.window()。它 return 未定义有什么原因吗? (我今天开始学习cypress。)
这经常出现。赛普拉斯有一些文档说明 Commands are not Promises。我写了一篇使用自定义命令强制命令链表现得像一个承诺的文章,但它仍然是实验性的和微妙的。
首先,我将几乎逐字逐句地给出您要完成的示例:
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 有一个叫做 "Commands" 的东西 return 是新的 "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
,但实际上并不是承诺。赛普拉斯命令实际上是排队的。 Cypress 挂钩到 mocha 的生命周期以确保 before
、beforeEach
、it
、afterEach
、after
块在继续之前等待 Cypress 命令不再排队。
我们来看这个例子:
it('should enter the first name', () => {
cy.get('#firstname').type('Nicholas')
})
实际发生的是 Cypress 看到 cy.get
命令并将带有参数 '#firstname'
的 get
命令排队。这立即(同步)returns 执行到测试。然后,赛普拉斯立即看到带有参数 'Nicholas'
和 return 的 cy.type
命令进行测试。由于没有 done
回调并且没有 return 编辑 Promise,因此测试在此时已在技术上完成。但是 Cypress 挂钩到 mocha 的生命周期中,并且在排队的命令完成之前不会发布测试。
现在我们有 2 个排队的命令并且测试正在等待 Cypress 发布测试,get
命令从队列中弹出。 Cypress 将尝试在页面上查找 id 为 firstname
的元素,直到找到或超时。假设它找到了元素,它将设置一个名为 subject
的状态变量(cy.state('subject')
,但不要依赖它)。下一个排队的命令 type
将获取前一个 subject
并尝试一次键入字符串 'Nicholas'
中的每个键,默认延迟为 50 毫秒,直到字符串完成。现在没有更多的排队命令,赛普拉斯释放测试,运行器继续下一个测试。
这有点简化 - 赛普拉斯做了很多工作来确保 .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)
})
对我来说, 很好,但并没有真正告诉我什么是必要的。
对我来说,一切都是同步的真是太棒了,你可以做这样的事情
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
块中的东西也是同步的。这太有用了。
我正在尝试通过以下方式在 Cypress 中访问我的应用程序的 window 对象。
cy.url().should('include', '/home').then(async () => {
const window = await cy.window();
console.log(window);
});
上述方法对我不起作用,因为 window
被 return 编辑为 undefined
。
但是,
Or you can use cy.state('window') which returns the window object synchronously, but this is undocumented and may change in the future.
此方法 return window 值成功。
cy.url().should('include', '/home').then(async () => {
const window = cy.state('window');
console.log(window);
});
如答案所示,cy.state('window') 没有记录,所以我还是宁愿使用 cy.window()。它 return 未定义有什么原因吗? (我今天开始学习cypress。)
这经常出现。赛普拉斯有一些文档说明 Commands are not Promises。我写了一篇使用自定义命令强制命令链表现得像一个承诺的文章,但它仍然是实验性的和微妙的。
首先,我将几乎逐字逐句地给出您要完成的示例:
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 有一个叫做 "Commands" 的东西 return 是新的 "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
,但实际上并不是承诺。赛普拉斯命令实际上是排队的。 Cypress 挂钩到 mocha 的生命周期以确保 before
、beforeEach
、it
、afterEach
、after
块在继续之前等待 Cypress 命令不再排队。
我们来看这个例子:
it('should enter the first name', () => {
cy.get('#firstname').type('Nicholas')
})
实际发生的是 Cypress 看到 cy.get
命令并将带有参数 '#firstname'
的 get
命令排队。这立即(同步)returns 执行到测试。然后,赛普拉斯立即看到带有参数 'Nicholas'
和 return 的 cy.type
命令进行测试。由于没有 done
回调并且没有 return 编辑 Promise,因此测试在此时已在技术上完成。但是 Cypress 挂钩到 mocha 的生命周期中,并且在排队的命令完成之前不会发布测试。
现在我们有 2 个排队的命令并且测试正在等待 Cypress 发布测试,get
命令从队列中弹出。 Cypress 将尝试在页面上查找 id 为 firstname
的元素,直到找到或超时。假设它找到了元素,它将设置一个名为 subject
的状态变量(cy.state('subject')
,但不要依赖它)。下一个排队的命令 type
将获取前一个 subject
并尝试一次键入字符串 'Nicholas'
中的每个键,默认延迟为 50 毫秒,直到字符串完成。现在没有更多的排队命令,赛普拉斯释放测试,运行器继续下一个测试。
这有点简化 - 赛普拉斯做了很多工作来确保 .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)
})
对我来说,
对我来说,一切都是同步的真是太棒了,你可以做这样的事情
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
块中的东西也是同步的。这太有用了。