如何在 cypress 测试中避免 cy.wait()

问题描述 投票:0回答:2

嗨,我是赛普拉斯的新手,我尽量避免在我的测试中使用
wait()
功能..


我知道,根据官方文档,Cypress 是异步工作的,我们不需要使用

wait()
函数,尤其是
visit()
命令处理它,因为它加载页面然后继续移动。

在我的测试用例中,我想做 2 件导致问题的主要事情:

  1. 打开下拉菜单(在左侧导航菜单上,有 5 个菜单,我想要第二个
  2. 点击一个选项转到另一个页面
it("clicks on the 'Front End' and navigates to the correct page", () => {
  visit(path, {
    timeout: 120000,
    pageLoadTimeout: 120000,
  });

  cy.get(selectors.CATEGORIES)
    .eq(2)
    // i use 'within', because i want to search **inside the selectors.CATEGORIES.eq(2) and not on the whole DOM**
    .within(() => {
      cy.get(dataCySelector("gridRow")).then(($optionsWrapper) => {
        const parentEl = $optionsWrapper.parent();
        const isMenuOpen = parentEl.css("display");

        // if i dont add the wait(), it selects the 1st 'menu options' instead of the **3rd**
        cy.wait(3000);

        if (isMenuOpen === "none") {
          console.log("*MENU IS CLOSE I OPEN*");
          cy.contains("category").click(); // OPEN THE MENU
          cy.contains("Front End").should("be.visible").click(); // click on the 'front end'
        } else {
          console.log("*MENU IS OPEN I DONT CLICK ON IT*");
          cy.contains("Front End").should("be.visible").click(); // JUST click on the 'front end'
        }

        cy.url().then(() => {
          cy.urlIncludes("/path/to/menu/option");
          cy.wait(3000);
          cy.contains(dataCySelector("AN_ELEMENT"));
        });
      });
    });
});

所以我的流程如下:


  1. 访问我想要的页面
  2. 获取
    CATEGORIES
    选择器(左侧导航栏上有5个菜单)
  3. 获得第三名
  4. 使用
    within
    深入了解它的孩子(我替换了
    then
    因为它搜索了整个 DOM)!!
  5. 我得到'gridRow'的父级并查看是否
    display=none
  6. !如果我不添加
    wait(3000)
    parentEl
    是第一个菜单包装器!!
  7. 比对后点击'选项链接'
  8. 用户被重定向到新页面,但我再次需要
    wait()
    来检查元素选择器是否存在。

这里一定有问题,我可以摆脱

wait
吗? 谢谢。

javascript node.js dom cypress cypress-conditional-testing
2个回答
1
投票

对于第二个

wait()
,如果您的问题与您的页面需要比默认超时更多的时间来加载这一事实有关,您仍然可以覆盖它。

  cy.url().then(() => {
    cy.url().should("contain", "/path/to/menu/option");
    cy.contains(dataCySelector("AN_ELEMENT"), {timeout: 30_000});
  });

对于第一个

wait
,If/Else 很奇怪。应该知道它何时打开,所以我会避免它(通过为这两种情况创建例如 2 个函数)然后,对于每种情况,我会在必要的地方添加一个
{timeout: 30_000}


0
投票

一般来说,把

.then()
改成
.should()
就可以重试,不用等了

重试是一种聪明的等待方式,因为它只会在不满足条件时等待。

您必须使用

expect()
assert()
来触发重试。赛普拉斯修补那些
chai
方法并使用抛出的错误来触发每次重试。

检查网址

cy.url().should((url) => {
  expect(url).to.include("/path/to/menu/option")  // retries if not true
})
// or 
cy.url().should('include', "/path/to/menu/option")  

// this command can be separate, 
// Cypress has a queue and this line is only run after the above succeeds
cy.contains(dataCySelector("AN_ELEMENT"))  

检查 gridRow parent 的可见性

你在测试的顶部加载了一个干净的页面,所以你的菜单最初不会打开(页面应该按预期加载)。

测试可以简单地是:

cy.get(selectors.CATEGORIES)
  .eq(2)
  .within(() => {
    cy.contains("category").click()
    cy.contains("Front End").should("be.visible").click()
    cy.url().should('include', '/path/to/menu/option')
    cy.contains(dataCySelector("AN_ELEMENT"))  
  })

但出于说明的目的,如果尚未打开,这应该打开菜单。

cy.get(dataCySelector("gridRow"))
  .parent()
  .then($menu => {
    const menuIsClosed = $menu.css("display") === 'none';
    if (menuIsClosed) {
      $menu.click()            // jQuery click()
    }
  })

注释它选择第一个“菜单选项”而不是第三个似乎表明菜单项是延迟加载的。

您可以通过为菜单选项的数量(长度属性)添加

.should()
断言来克服这个问题。

cy.get(dataCySelector("gridRow"))
  .should('have.length', 3)
cy.contains("Front End").should("be.visible").click()

整个测试

您想“解耦”步骤,以便您可以单独检查它们。

由于您已将基本的 Cypress 命令抽象为自定义命令,并且没有给出详细信息,因此很难准确描述代码,但这是我将采用的方法:

cy.get(selectors.CATEGORIES)
  .eq(2)
  .within(() => {

    // open the parent
    cy.get(dataCySelector("gridRow"))
      .parent()
      .then($menu => {
        if ($menu.css("display") === 'none') {
          $menu.click()            // jQuery click()
        }
      })
      .should('not.have.css', 'display', 'none')   // add retry in case of lag

    // ensure all options loaded
    cy.get(dataCySelector("gridRow"))
      .should('have.length', 3)                  

    // click required option
    cy.contains("Front End").should("be.visible").click()
    cy.url().should('include', '/path/to/menu/option')

    // verify page
    cy.contains(dataCySelector("AN_ELEMENT"))  
  })
© www.soinside.com 2019 - 2024. All rights reserved.