【问题标题】:Cypress with stripe: elements height not loaded带条纹的赛普拉斯:未加载元素高度
【发布时间】:2021-04-01 10:15:14
【问题描述】:

我使用 cypress 一周以来,我成功地与条纹 iframe 进行了集成:我使用了以下代码:

cypress/support/command.js

Cypress.Commands.add('iframeLoaded', { prevSubject: 'element' }, $iframe => {
  const contentWindow = $iframe.prop('contentWindow')
  return new Promise(resolve => {
    if (contentWindow && contentWindow.document.readyState === 'complete') {
      resolve(contentWindow)
    } else {
      $iframe.on('load', () => {
        resolve(contentWindow)
      })
    }
  })
})

Cypress.Commands.add('getInDocument', { prevSubject: 'document' }, (document, selector) =>
  Cypress.$(selector, document),
)

cypress/integration/staging-web/web.test.js

    cy.get('iframe')
      .eq(1)
      .iframeLoaded()
      .its('document')
      .getInDocument('[name="cardnumber"]')
    
      .then($iframe => {
          if ($iframe.is(':visible')) {
              $iframe.type('4242424242424242')
          }
      })
    
  cy.get('iframe')
      .eq(1)
      .iframeLoaded()
      .its('document')
      .getInDocument('[name="exp-date"]')
    
      .then($iframe => {
          if ($iframe.is(':visible')) {
              $iframe.type('1225')
          }
      })
    
  cy.get('iframe')
      .eq(2)
      .iframeLoaded()
      .its('document')
      .getInDocument('[name="cvc"]')
    
          .then($iframe => {
              if ($iframe.is(':visible')) {
                  $iframe.type('123')
              }
          })
    
  cy.get('.mt1 > .relative > .input').type('utente')

我的问题是,在页面加载过程中,cypress 不会等到条带字段完全加载,并且因为发生这种情况而出现错误(对不起,不是英语,但这是一个屏幕截图):

这些行是:

  • 卡号
  • 有效期,密码
  • 第四行是持卡人

我试过.should('be.visibile'),但它什么也没做;另外我已经尝试过

cy.get('iframe')
    .eq(1)
    .iframeLoaded()
    .its('document')
    .getInDocument('[name="cardnumber"]')

    .then($iframe => {
        if ($iframe.is(':visible')) {
            $iframe.type('4242424242424242')
        }
    })

但没办法,它总是给我一个错误;在后一种情况下,它甚至不会给出错误,它只是在不填写字段的情况下继续运行,然后因为无法在测试中继续而停止。

如果我在web.test.js 中的代码之前添加cy.wait(800),它可以正常工作,但我不想使用wait,因为它基本上是错误的(如果它在5 秒后加载会发生什么?)。

有没有办法检查这些元素是否必须有高度? 请记住,他们在iframe 中(很遗憾)。

【问题讨论】:

    标签: javascript stripe-payments cypress


    【解决方案1】:

    如果我添加 cy.wait(800) ... 它工作正常

    这是因为您没有在 getInDocument() 中使用带有自动重试功能的赛普拉斯命令。

    Cypress.$(selector)是jQuery,它只是尝试抓取元素,不会重试异步加载,找不到时不会测试失败。

    应该使用适当的重试命令,比如

    Cypress.Commands.add('getInDocument', { prevSubject: 'document' }, (document, selector) =>
      cy.wrap(document).find(selector)
    )
    

    或者你可能需要在body工作

    Cypress.Commands.add('getInDocument', { prevSubject: 'document' }, (document, selector) =>
      cy.wrap(document).its('body')
        .find(selector)
        .should('be.visible')
    )
    

    如果没有测试系统,我不确定哪一个是正确的语法,但你明白了。


    另外,自定义命令太多。你总是跟着.iframeLoaded().its('document'),所以只需将它全部封装在iframeLoaded 自定义命令中。

    事实上,resolve(contentWindow.document.body) 因为链接.find(selector) 更好。


    这是我对 Stripe 演示页面的测试,

    Cypress.Commands.add('iframeLoaded', { prevSubject: 'element' }, $iframe => {
      const contentWindow = $iframe.prop('contentWindow')
      return new Promise(resolve => {
        if (contentWindow && contentWindow.document.readyState === 'complete') {
          resolve(contentWindow.document.body)
        } else {
          $iframe.on('load', () => {
            resolve(contentWindow.document.body)
          })
        }
      })
    })
    
    it('finds card number', () => {
    
      cy.viewport(1000, 1000)
      cy.visit('https://stripe-payments-demo.appspot.com/')
      cy.get('iframe')
        .should('have.length.gt', 1)  // sometimes 2nd iframe is slow to load
        .eq(1)
        .iframeLoaded()
        .find('input[name="cardnumber"]')
        .should('be.visible')
    })
    

    【讨论】:

    • 非常感谢!我完全忽略了 .wrap() 的存在,这对我理解 cypress =) 有很大帮助但是,我的问题也是如果页面显示为上面的屏幕截图,我完全不知道为什么,但它不再加载内容;我应该做一个 cy.reload(),但我不知道把它放在哪里:/我尝试了一个 if,但它应该包含类似“如果它已经尝试过并且它是未定义的 - 或者高度小于 5px - ,重新加载页面”
    • 看起来有一些动画/过渡正在进行,名称为“cardnumber”的元素存在,但处于过渡前阶段。只是猜测,尝试将.should('be.visible') 添加到查找中。 (见上文)
    • 好吧,当我使用 cy.wrap(document).its('body').find(selector).should('be.visible') 时,它会显示 -find [name="cardnumber"] expected <input> to be visibleThis element <input> is not visible because it has CSS property: opacity: 0 ,但是如果我在测试结束时使用 chrome 工具检查元素,则 css 设置为 @987654336 @...我快生气了
    • 我做了一些可怕的事情,我使用了cy.wrap(document).its('body').find(selector),然后在主测试中启动了这个:const ADD_MS = 200 function checkAgainStripe() { let waitForMillisecs = 500 cy.get('.btn').scrollIntoView().should('be.visible').click() cy.get('iframe') .eq(1) .then($elem => { cy.wait(waitForMillisecs) waitForMillisecs = waitForMillisecs + ADD_MS if (!$elem[0] || !$elem[0].offsetHeight || $elem[0].offsetHeight < 19) { console.log('entered in if') cy.reload() return checkAgainStripe() } }) }
    • 我认为添加显式等待是可以的,它肯定是有效的,你只等待几百毫秒。我不知道您为什么无法克服 .should() 的转换问题,我无法在 Stripe 演示页面上重现它(请参阅上面的测试)。
    【解决方案2】:

    @Nanker Phelge 顺便说一下我用这种方式更新了我的函数,我把它贴在这里是因为 cmets 中没有空间:

    更新:我把 waitForMillisecs 放在函数里面 -_- 它必须留在外面!已更正。

    const ADD_MS = 200
    const STACK_LIMIT = 15
    let stackNumber = 0
    let waitForMillisecs = 500
    
        function checkAgainStripe() {  
          stackNumber++
        
          if (stackNumber >= STACK_LIMIT) {
            throw new Error('Error: too many tries on Stripe iframe. Limit reached is', STACK_LIMIT)
          }
        
          cy.get('.btn').scrollIntoView().should('be.visible').click()
          cy.get('iframe')
            .eq(1)
            .then($elem => {
              //console.log($elem[0].offsetHeight)
              //console.log($elem[0])
              cy.log('now wait for ' + waitForMillisecs + '; stack number is ' + stackNumber)
              cy.wait(waitForMillisecs)
              waitForMillisecs = waitForMillisecs + ADD_MS
              if (!$elem[0] || !$elem[0].offsetHeight || $elem[0].offsetHeight < 19) {
                console.log('entered in if')
                cy.reload()
                return checkAgainStripe()
              }
            })
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-02
      • 1970-01-01
      • 2022-10-02
      • 2022-01-07
      • 1970-01-01
      • 2022-07-22
      相关资源
      最近更新 更多