在 Cypress 中,如何与页面中新添加的元素进行交互?

Les*_*ody 0 cypress cypress-custom-commands

我想MutationObserver与 Cypress 一起使用,因为它感觉像是一种适当的机制,用于检测 DOM 发生的特定更改,然后与添加的元素进行交互。

假设我有一个包含 3 个按钮和一个div.new-elements-wrapper. 单击每个按钮会生成一个新div元素,按钮 A、B 和 C的属性div.new-elements-wrapper分别为 、 、和。这些元素可以随机插入,而不仅仅是附加到容器的末尾。data-typebutton-abutton-bbutton-cdiv.new-elements-wrapper

我想编写一个有效的测试:

  1. 单击按钮 A。
  2. 等待新元素添加到div.new-elements-wrapper区域。
  3. 当新元素出现在区域中时,验证它是否具有data-type属性并且其值为button-a

对按钮 B 和 C 重复上述操作。

对于步骤 2,我不想继续MutationObserver,直到配置为专门查看 的 adiv.new-elements-wrapper在突变的 中具有单个节点nodesAddedList。然后,在步骤 3 中,验证data-type属性为button-a

对于赛普拉斯的奇才们来说,你会怎么做呢?

编辑:请注意,添加的这些组件没有可用的唯一标识信息。如果有两个元素,两者都是button-a,那么知道添加了哪个元素的唯一方法是通过 a 通知MutationObserver

Suc*_*UKR 7

APIMutationObserver需要一个间谍或一个 Promise 才能在 Cypress 测试中可靠地工作,因为它会与测试异步调用其处理程序。

这就是我在 Cypress 中实现突变观察器的方式,使用*观察 DOM 元素和 jQuery 的所有后代.not()来查找差异。

Cypress.Commands.add('watchForMutation', (selector, action, options = {}) => {
  const domTree = cy.$$(`${selector} *`)
  let diff;
  return cy.wrap(action(), options)
    .should(() => {
      const newDomTree = cy.$$(`${selector} *`)
      diff = newDomTree.not(domTree)
      expect(diff.length).to.be.gt(0)             // retry until true or timeout
    })
    .then(() => diff)
})
Run Code Online (Sandbox Code Playgroud)

像这样使用

cy.watchForMutation('#container', () => {
  cy.get('button').click()
}, {timeout:6000})
.then(newElement => {
  ...
})
Run Code Online (Sandbox Code Playgroud)

笔记

  • 适用selector *于所有后代(如subTree:true选项)
  • 该子句在时间范围should()内等待新元素options.timeout
  • options.timeout如果未通过,则默认为 4000 毫秒的标准命令超时
  • .then(() => diff)回新元素


Wod*_*den 5

赛普拉斯已经通过普通命令做到了这一点。

这是一个示例页面,可以执行您所描述的操作

  • <div>将按钮连接到一个添加到的函数<body>
  • 是否异步添加
  • 给出新的<div>(可预测的)属性用于选择
<body>
  <button onclick="add()">a</button>
  <button onclick="add()">b</button>
  <button onclick="add()">c</button>
  <script>
    let id = 0
    function add() {
      setTimeout(() => {
        const div = document.createElement('div')
        div.innerText = `div ${id}`
        div.setAttribute('data-test-id', id++)
        const body = document.querySelector('body')
        body.appendChild(div)      
      }, 1000)
    }
  </script>
</body>
Run Code Online (Sandbox Code Playgroud)

这是 Cypress 观察 DOM 突变的方式

cy.contains('button', 'a').click()
cy.contains('[data-test-id="0"]', 'div 0')   // retries up to 4 seconds

cy.contains('button', 'b').click()
cy.contains('[data-test-id="1"]', 'div 1')   // retries up to 4 seconds

cy.contains('button', 'c').click()
cy.contains('[data-test-id="2"]', 'div 2')   // retries up to 4 seconds    
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


为什么不使用 MutationObserver

MutationObserver 不是必需的,并且会给您提供不稳定的测试,因为它是一个在 Cypress 主进程之外运行的事件处理程序。

好的测试依赖于运行者对发生的情况的控制,不同步发生的事情使测试变得不可预测