Useful Cypress Automation Test Tips

Cypress in a pot
Photo by Tzingtao Chow on Unsplash

Reliable wait using network wait

The challenge: Flakiness due to unreliable waiting for elements

So, we’ve created a test script, selected all the proper elements, executing all the right actions and prepared all kinds of assertion, but when the time to run the script comes, the elements took too long to load or disappear too quickly. What do we do?

The Solution: Use cy.wait() for more reliable wait

In cypress we could use cy.wait() to make cypress wait for certain resource to resolve before continue to the next action.

Let’s try it

Here’s the code in wait.spec.js

/// <reference types="cypress" />

let userName = "Admin";
let password = "admin123";

context("Good things come to those who wait", () => {
  before(() => {
    cy.clearCookies();
    cy.visit("https://opensource-demo.orangehrmlive.com/");
  });

  beforeEach(() => {
    Cypress.Cookies.preserveOnce("PHPSESSID");
    // Hi Cypress, I'd like to work with network
    cy.server();

    cy.route("/index.php/dashboard/employeeDistribution").as(
      "indexDashboardEmployeeDistribution"
    );
    cy.route("/index.php/dashboard/pendingLeaveRequests").as(
      "indexDashboardPendingLeaves"
    );
  });

  it("Verify title", () => {
    cy.title().should("eq", "OrangeHRM");
  });

  it("Input username and password", () => {
    cy.get("#txtUsername")
      .should("exist")
      .clear()
      .type(userName)
      .should("have.value", userName);
    cy.get("#txtPassword")
      .should("exist")
      .clear()
      .type(password)
      .should("have.value", password);
  });

  it("Click login", () => {
    cy.get("#btnLogin").should("exist").click();
    // This is the network wait
    
    cy.wait("@indexDashboardEmployeeDistribution");
    cy.wait("@indexDashboardPendingLeaves");
  });

  it("These action are done after all the wait are completed", () => {
    cy.get("h1").should("exist").and("have.text", "Dashboard");
  });
});

Now check the relevant code.

  1. Let say you already have cypress installed in your project and ready to run them. For more information on how to install Cypress, Cypress.io has a great documentation you could check out.
  2. Create a new spec file under cypress/integration
  3. Let’s call it wait.spec.js
  4. Let’s try it on https://opensource-demo.orangehrmlive.com/ demo website on how to use cy.wait()
  5. On this line cy.server(); we basically tell Cypress that we want to work with network. It’s required for the next command which is cy.route()
  6. cy.route("/index.php/dashboard/employeeDistribution").as("indexDashboardEmployeeDistribution"); On this line of code, we’re telling Cypress to spy on any request with format of "/index.php/dashboard/employeeDistribution" and giving it alias of "indexDashboardEmployeeDistribution" which we’ll use later.
  7. And on this code cy.wait("@indexDashboardEmployeeDistribution"); we told cypress to wait for the request of "indexDashboardEmployeeDistribution" to be completed
  8. After all the wait has been completed then Cypress will execute the next commands resulting in more reliable automated test.

Here’s how the waiting looks like when you run the script

figure 1

The power comes from .within()

The challenge: Test failed because multiple similar elements are found (Including the hidden one)

So, we’ve created a test script, selected all the proper elements, executing all the right actions and prepared all kinds of assertion, but when the time to run the script comes, multiple elements are selected and the action failed to execute or only execute one of them. What do we do?

It’s especially a problem if there’s no specific selector is defined.

The solution: .within() make sure you select the element within the right element

Use .within()

According to cypress documentation, .within() will scopes all subsequent cy commands to within this element. Useful when working within a particular group of elements such as a <form>

Let’s try it

Here’s the code in within.spec.js

/// <reference types="cypress" />

let userName = "Admin";
let password = "admin123";

context("The power comes from within()", () => {
  before(() => {
    cy.clearCookies();
    cy.visit("https://opensource-demo.orangehrmlive.com/");
  });

  beforeEach(() => {
    Cypress.Cookies.preserveOnce("PHPSESSID");
    // Hi Cypress, I'd like to work with network
    cy.server();
    // cy.route("/index.php/communication/**").as("indexCommunication");
    cy.route("/index.php/dashboard/employeeDistribution").as(
      "indexDashboardEmployeeDistribution"
    );
    cy.route("/index.php/dashboard/pendingLeaveRequests").as(
      "indexDashboardPendingLeaves"
    );
  });

  it("Verify title", () => {
    cy.title().should("eq", "OrangeHRM");
  });

  it("Input username and password", () => {
    cy.get("#txtUsername")
      .should("exist")
      .clear()
      .type(userName)
      .should("have.value", userName);
    cy.get("#txtPassword")
      .should("exist")
      .clear()
      .type(password)
      .should("have.value", password);
  });

  it("Click login", () => {
    cy.get("#btnLogin").should("exist").click();
    // This is the network wait
    // cy.wait("@indexCommunication");
    cy.wait("@indexDashboardEmployeeDistribution");
    cy.wait("@indexDashboardPendingLeaves");
  });

  it("Open Buzz in main menu", () => {
    cy.get("h1").should("exist").and("have.text", "Dashboard");
    cy.get("ul#mainMenuFirstLevelUnorderedList").should("exist").as("mainMenu");
    cy.get("@mainMenu").within(($mainMenu) => {
      cy.get("li").should("have.length.greaterThan", 11);
      cy.contains("li", "Buzz").should("exist").click();
    });
  });

  it("Search visible text area within #buzzContainer", () => {
    cy.get("#buzzContainer").as("buzzContainer");
    cy.get("@buzzContainer").within(($container) => {
      cy.get("#page1").as("page1");
      cy.get("@page1").within(($page1) => {
        cy.get("textarea#createPost_content").should("have.length", 1);
      });
    });
  });
});

Now check the relevant code.

cy.get("@mainMenu").within(($mainMenu) => {
cy.get("li").should("have.length.greaterThan", 11);
cy.contains("li", "Buzz").should("exist").click();
});

Cypress will search for li and only search inside @mainMenu. Cypress will also search li which contain "Buzz” text inside it.

Here’s how the script look like when run

Cypress within image
figure 2

NEXT: Testing upload file with cypress

Challenge: How do I testing a file upload with cypress?

Solution: Use cypress-file-upload from npmjs.com

You can use cypress-file-upload from npmjs.com to test file upload. Here’s the link: https://www.npmjs.com/package/cypress-file-upload

First, install the package using npm by cd into the root cypress directory and run npm install --save-dev cypress-file-upload in command prompt.

After installing the package, you’ll need to add import 'cypress-file-upload'; in the cypress/support/commands.js file

Then, You’ll be able to use .attachFile(yourFixturePath) command in your spec.js files

Here’s an example test script for uploading file.

// file-upload-spec.js
/// <reference types="cypress" />

context("The power comes from within()", () => {
  before(() => {
    cy.clearCookies();
    cy.visit("https://www.azurespeed.com/Azure/UploadLargeFile");
  });

  beforeEach(() => {
    // Hi Cypress, I'd like to work with network
    cy.server();
  });

  it("Verify title", () => {
    cy.title().should(
      "eq",
      "Azure Storage Large File Upload Speed Test - Azure Speed Test"
    );
  });

  it("Click Start testing", function () {
    cy.get("main.bd-content").within(($bdContent) => {
      cy.contains("button", " Start testing ").should("exist").click();
    });
  });

  it("Attach file into file input", function () {
    cy.get("div.modal-content")
      .should("exist")
      .within(($modal) => {
        cy.contains("#modal-basic-title", "Upload file").should("exist");
        cy.get('input[type="file"]').should("exist").attachFile("fff.png");
        cy.contains("div > label", "Region")
          .should("exist")
          .next()
          .select("southeastasia");
        cy.contains("button", " Upload ").should("exist").click();
        cy.get("button.close").should("exist").click();
      });
  });

  it("Verify file is uploaded", function () {
    cy.get("main.bd-content").within(($bdContent) => {
      cy.get("table.table")
        .should("exist")
        .within(($table) => {
          cy.contains("td", "fff.png").should("exist");
        });
    });
  });
});

Here’s how the script looks like when you run it

Cypress in a pot photo by Tzingtao Chow on Unsplash

0 Comments

Leave your comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.