Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Cypress-如何在iframe中的元素之间切换_Javascript_Testing_Iframe_Automated Tests_Cypress - Fatal编程技术网

Javascript 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', () =>

我试图与cypress的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().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')
})