【问题标题】:What are aliases (`.as`) in cypress?柏树中的别名(`.as`)是什么?
【发布时间】:2021-10-15 13:32:24
【问题描述】:

我有以下代码:

cy.get('input:checkbox').first().as('firstCheckbox').then(() => {

    cy.get('@firstCheckbox').should('be.checked').click()
    cy.get('.globalMessage-display > :nth-child(1) > .alert').should('be.visible')
    cy.get('.globalMessage-display > :nth-child(1) > .alert').should('not.exist')
    cy.get('@firstCheckbox').should('not.be.checked').click()
    cy.get('.globalMessage-display > :nth-child(1) > .alert').should('be.visible')
    cy.get('.globalMessage-display > :nth-child(1) > .alert').should('not.exist')
    cy.get('@firstCheckbox').should('be.checked')

})

cy.get('@firstCheckbox').should('be.checked').click() 之后,复选框被移动到最后一个索引位置而不是第一个。 根据我对别名的理解,这应该无关紧要,因为我用('@') 引用它,它在哪个位置并不重要。不幸的是,下一个cy.get('@firstCheckbox') 访问的是新的第一个元素,而不是我最初引用的那个。我也无法从文档中弄清楚。 错误在哪里?

https://docs.cypress.io/guides/core-concepts/variables-and-aliases

https://docs.cypress.io/api/commands/as

@agoff 更新:

它似乎与您的代码配合得更好,但我注意到新代码存在一个新问题。 如果您取消选中该复选框,则该类将使用 js 重新加载,导致它从 dom 中短暂消失。之后它再也找不到它并且测试中止。 我也尝试过重新加载,但它再也找不到元素了。如何处理?

选中的复选框类的名称为custom-control-input ng-untouched ng-pristine ng-valid。在取消选中类名更改为custom-control-input.ng-untouched.ng-valid.ng-dirty 之后,元素被删除并重新加载到具有类名custom-control-input ng-untouched ng-pristine ng-valid 的DOM。问题出在第二个cy.wrap($el) 尝试找到元素custom-control-input.ng-untouched.ng-valid.ng-dirty,尽管搜索并找到了类custom-control-input ng-untouched ng-pristine ng-valid 的初始元素。那是我不明白的另一件事。

【问题讨论】:

  • 这行the checkbox is moved to the last index position instead of the first.是什么意思?
  • 如果我取消选中该复选框,则元素的索引将从 0 更改为最后一个位置。所以它被编码在我们的网站上。

标签: javascript jquery cypress


【解决方案1】:

如果在单击事件期间应用程序删除输入并在末尾附加一个新输入,则会发生这种情况。那么你的别名是无效的,因为它指向一个不再在 DOM 中的元素。

如果我移动点击处理程序中的元素,您的代码就可以工作。

如果我克隆点击处理程序中的元素,您的代码将失败。

怎么办?

点击后刷新你的别名

cy.get('input:checkbox').first().as('myCheckbox').then(() => {

  cy.get('@myCheckbox').should('be.checked').click()
    .then(() => cy.get('input:checkbox').last().as('myCheckbox'))  // it's last now!

  cy.get('.globalMessage-display > :nth-child(1) > .alert').should('be.visible')
  cy.get('.globalMessage-display > :nth-child(1) > .alert').should('not.exist')

  cy.get('@myCheckbox').should('not.be.checked').click()
    .then(() => cy.get('input:checkbox').last().as('myCheckbox'))

  cy.get('.globalMessage-display > :nth-child(1) > .alert').should('be.visible')
  cy.get('.globalMessage-display > :nth-child(1) > .alert').should('not.exist')

  cy.get('@myCheckbox').should('be.checked')
})

alias 命令还有另一个技巧。

如果元素被克隆和替换,原始元素将从 DOM 中分离

cy.get('@alias') 检测分离的元素并重播原始命令以自动刷新。

它不适用于.first(),因为元素改变了位置。

但如果您使用data-cy 属性而不是.first(),您的代码将可以工作。

cy.get('input:checkbox[data-cy="first-checkbox"]')
  .as('myCheckbox').then(() => {

  cy.get('@myCheckbox')
    .should('be.checked').click()    // cloned and moved to another position

  ...

  cy.get('@myCheckbox')                 // detached by previous click
    .should('not.be.checked').click()   // so alias replays original get
                                        // with [data-cy="first-checkbox"]
  ...
  cy.get('@myCheckbox').should('be.checked')  // as above
})

这是执行此操作的 Cypress 代码

let { subject, alias, command } = aliasObj

const resolveAlias = () => {
  
  if ($dom.isElement(subject)) {          // if this is a DOM element

    const replay = () => {
      cy.replayCommandsFrom(command)
      return undefined
    }

    if ($dom.isDetached(subject)) {     // is it detached?

      subject = subject.filter((index, el) => $dom.isAttached(el))  // all detached?

      if (!subject.length) {
        return replay()                // perform the replay
      }
    }

【讨论】:

  • 效果很好!泰伴侣
  • 不客气。
【解决方案2】:

我认为您在混淆和滥用别名。当您使用.then() 时,您已经生成了找到的元素。因此,您可以直接引用对象(在包装之后),而不是使用别名。我相信这样的事情应该可以解决您的问题...

cy.get('input:checkbox').then(($el) => {
  cy.wrap($el).should('be.checked').click()
              .and('not.be.checked').click()
              .and('be.checked')
})

【讨论】:

  • 更新了我最初的问题
  • 更新了我的答案——你也许可以通过链接应该(现在写为and())而不是重新包装元素来绕过它?
  • 可以,但是如果我想在clicks 之间运行其他代码怎么办?然后不幸的是代码不起作用。而且不是很稳定。有时它有效,有时它在clicks 之后中断,因为它太快了。 .wait 也没有帮助
  • 你到底想做什么?我的回答是响应提供的代码,并模仿了确切的行为。从头到尾,我想我对你到底想做什么有点困惑。
  • 抱歉给您带来了困惑。我认为上面的简化代码足以获得解决方案。我已对其进行了更新,以便可以看到测试的全部范围。
猜你喜欢
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
  • 2021-01-27
  • 2021-06-04
  • 1970-01-01
  • 2018-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多