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

The*_*ris 0 javascript cypress cypress-conditional-testing

我试图wait()在测试中避免使用该功能。

我知道,根据官方文档,Cypress 是异步工作的,我们不需要使用该wait()函数,特别是visit()命令处理该函数,因为它加载页面然后继续前进。

在我的测试用例中,我想处理导致问题的两件事:

  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  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"));
        });
      });
    });
});

Run Code Online (Sandbox Code Playgroud)

所以我的流程是这样的:


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

这里一定有问题,我可以去掉waits 吗?谢谢。

Fod*_*ody 5

一般来说,更改.then().should()将使您重试并消除等待的需要。

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

您必须使用expect()assert()来触发重试。Cypress 修补这些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"))  
Run Code Online (Sandbox Code Playgroud)

检查 gridRow 父级的可见性

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

测试可以简单地是:

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"))  
  })
Run Code Online (Sandbox Code Playgroud)

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

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

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

.should()您可以通过添加菜单选项数量(长度属性)的断言来克服这个问题。

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

整个测试

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

很难准确地了解代码,因为您已将基本的 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"))  
  })
Run Code Online (Sandbox Code Playgroud)