赛普拉斯:使用轮询检查 table 中单元格的值

Cypress: check the value of a cell in a table using polling

我有一个有状态栏的 table,我想检查第一行(最后一栏)的状态。一段时间后(最多 5 分钟),状态从“进行中”变为完成;

这里是 DOM:

<tbody>
   <tr>
      <td>...</td>
      <td> ... </td>
      <td> in progress / complete </td> //status => want to check this cell.
  </tr>
   <tr>
      <td>...</td>
      <td> ... </td>
      <td> ... </td> //status
  </tr>
   <tr>
      <td>...</td>
      <td> ... </td>
      <td> ... </td> //status
  </tr>
</tbody>

如何到达我想要的单元格并使用轮询机制查看状态是否已完成?

感谢您的帮助

在赛普拉斯中选择行和列的模式是

cy.get('tbody tr').eq(0)          // first row
  .find('td').eq(2)               // third col
  .should('contain', 'complete')  // criteria to check 

这会等待 defaultCommandTimeout 设置,即 4000 毫秒。要延长至 5 分钟,请添加 300000 超时。

cy.get('tbody tr').eq(0)              
  .find('td').eq(2, {timeout:300000})  
  .should('contain', 'complete')      // on fail retry above up to 5 minutes

但是根据状态更新后 DOM 中的变化,您可能会遇到此错误。如果使用新副本刷新行或 table,您可能需要将这些步骤合并到一个选择器中。

cy.get('tbody tr:nth-child(1) td:nth-child(3)', {timeout:300000})           
  .should('contain', 'complete') 

并不总是清楚当 .should() 失败时命令链中的哪些步骤将被重复。

您也可以使用 within 进入第一个 tr 并等待文本 complete 出现所需的时间。像这样:

对于精确的文本匹配:

cy.get('tbody')
  .find('tr')
  .eq(0)
  .within(() => {
    //eq(0) gets the first tr
    cy.get('td', {timeout: 300000}).eq(2).should('have.text', 'complete') //Exact text match
  })

对于部分文本匹配:

cy.get('tbody')
  .find('tr')
  .eq(0)
  .within(() => {
    //eq(0) gets the first tr
    cy.get('td', {timeout: 300000}).eq(2).should('contain.text', 'complete') //partial text match
  })

Cypress 具有 built-in 轮询,无需编写特殊例程。

这就是您所需要的!

cy.contains('tbody tr:nth-of-type(1) td:nth-of-type(3)', 'complete', {timeout:300000})

不需要 .find().within(),选择器 'tbody tr:nth-of-type(1) td:nth-of-type(3)' 负责搜索 table 层次结构。

cy.contains() 命令断言文本 "complete" 应该在该单元格中,超时自动轮询 5 分钟。

状态越早变化越早通过

注意 使用 .within() 如果整行在状态更改时被替换,则可能会出现“与 DOM 分离”错误。

我会先检查“进行中”状态以确保顺序正确。

cy.contains('tbody tr:eq(0)', 'in progress')
cy.contains('tbody tr:eq(0)', 'complete', {timeout:300000})

不清楚您 table 中的单元格是如何更新的。是否间隔发送请求或仅在首次加载页面时发送请求?

如果是前者,就这么简单

// assuming only table on page and last cell of first row is always the cell you want
cy.get('tbody')
  .should('be.visible') // check table is fully loading in case
  .find('tr')
  .first() // same as .eq(0), just more readable
  .find('td')
  .last() // same as .eq(3), jut more readable
  .should('be.visible')
  .and('match.text', /complete/i) // can update command timeout

如果您处理的是后者,则必须在每次重新加载页面后使用递归进行检查。建议使用 cypress-recurse

import { recurse } from 'cypress-recurse'

recurse ({
  () => {
    return cy.get('tbody tr:nth-child(0) td:nth-child(3)') // eq to above
    .should('be.visible')
  },
  ($el) => expect($el).to.have.text('complete'),
  {
    // can alter configurations
    timeout: 30_000,
    delay: 3_000,
    post: { cy.reload() }
  }
)