Javascript Cypress-如何在iframe中的元素之间切换
我试图与cypress的iframe中的一些元素进行交互。 如果我在中对每个测试只使用一个元素,那么一切都很好Javascript Cypress-如何在iframe中的元素之间切换,javascript,testing,iframe,automated-tests,cypress,Javascript,Testing,Iframe,Automated Tests,Cypress,我试图与cypress的iframe中的一些元素进行交互。 如果我在中对每个测试只使用一个元素,那么一切都很好 # commands.js Cypress.Commands.add( 'iframe', { prevSubject: 'element' }, ($iframe) => { return new Cypress.Promise(resolve => { $iframe.on('load', () =>
# commands.js
Cypress.Commands.add(
'iframe',
{ prevSubject: 'element' },
($iframe) => {
return new Cypress.Promise(resolve => {
$iframe.on('load', () => {
resolve($iframe.contents().find('body'))
})
})
})
# landing_page.spec.js
cy.get('iframe').iframe().find('#happybutton').should('be.visible')
但是,我希望查找多个元素,单击它们,并检查它们是否正确呈现,但是如果我将iframe内容分配给一个变量并重用它来定位另一个元素(例如,按钮),cypress将尝试从第一个元素定位第二个元素(例如,菜单)(该按钮注定会失败,因为该按钮不包含菜单)
每次我想与不同的元素交互时,我都尝试使用不同的变量,或者直接调用cy.get('iframe').iframe()
,但cypress被困在无限循环中,测试永远不会结束(但不会产生错误或警告)
有人知道避免这种无限循环的方法吗?因为我想复制一系列步骤来构建一个测试用例,所以不可能在不同的测试中隔离每个交互
或者有人知道一个更适合使用iframe的框架吗?问题是
$iframe.on('load'),
只触发一次,因此您不能调用cy.get('iframe').iframe()
两次,这两个.find()
命令都在有效地执行
让iframeContent=cy.get('iframe')。iframe()
不存储iframe主体,它存储一个“链接器”,它被视为函数或getter
“无限循环”是Cypress在等待第二次promise resolve()调用,而这从未发生过
因此,可以像这样嵌套命令
cy.get('iframe').iframe().then(body => {
cy.wrap(body).find('#happybutton').should('be.visible')
cy.wrap(body).find('#myMenu').should('be.visible')
});
或者,您可以通过在load事件激发时添加标记来增强该命令
Cypress.Commands.add('iframe', { prevSubject: 'element' }, ($iframe) => {
return $iframe._hasloaded
? $iframe.contents().find('body')
: new Cypress.Promise(resolve => {
$iframe.on('load', () => {
$iframe._hasloaded = true;
resolve($iframe.contents().find('body'))
})
})
})
多亏了Marion的回答,我找到了一种重构代码的方法,现在它可以工作了! 注意:
iframe()
函数保持不变
# commands.js
Cypress.Commands.add(
'iframe',
{ prevSubject: 'element' },
($iframe) => {
return new Cypress.Promise(resolve => {
$iframe.on('load', () => {
resolve($iframe.contents().find('body'))
})
})
})
# landing_page.spec.js
cy.get('iframe').iframe().as('iframeContent')
cy.get('@iframeContent').then((iframeContent) => {
cy.get(iframeContent).find('#happybutton').click()
cy.get(iframeContent).find('#myMenu')
cy.get(iframeContent).find('#anotherElement').should('be.visible')
})
看看哪种方法使用嵌套来运行多个命令。好吧,这是可行的-但是将
.as('iframeContent')
直接跟在cy.get('@iframeContent')
后面只会让人费劲。
# commands.js
Cypress.Commands.add(
'iframe',
{ prevSubject: 'element' },
($iframe) => {
return new Cypress.Promise(resolve => {
$iframe.on('load', () => {
resolve($iframe.contents().find('body'))
})
})
})
# landing_page.spec.js
cy.get('iframe').iframe().as('iframeContent')
cy.get('@iframeContent').then((iframeContent) => {
cy.get(iframeContent).find('#happybutton').click()
cy.get(iframeContent).find('#myMenu')
cy.get(iframeContent).find('#anotherElement').should('be.visible')
})