DEV Community

Hajar | هاجر
Hajar | هاجر

Posted on

Getting Started with Cypress

What's Cypress?
Cypress is a JavaScript-based front-end testing tool. It helps you test the journey that users take from once they visit your website till they leave. You can use Cypress to test what users will see when they visit the website for the first time. Or where they should be redirected to when they click some link or another. Or if cookies get saved when they signup or login. And so many other things.

Installation
To run Cypress, you need to install it as a dev dependency into your project and then run yarn run cypress open.

yarn add cypress --dev
yarn run cypress open
Enter fullscreen mode Exit fullscreen mode

Note: You can also download it from Cypress.io, double click Cypess.exe and then select your project.

Once you add Cypress to your project, cypress folder and other sup-directories will be added to the root of your project.
What we care about in these sub-directories is integration. You can delete all the files created under that directory and create a new file called first_test.spec.js. This is where we're going to add our first test.

Let's write a test for a function that returns random numbers between 0-90.

// 1
const getRandomNum = () => Math.floor(Math.random() * 100);
// 2
describe("test getRandomNum", () => {
  // 3 
  it("should be less than 100", () => {
    // 4
    for (let i = 0; i < 10; i++) {
      expect(getRandomNum()).lessThan(100);
    }
  });
});
Enter fullscreen mode Exit fullscreen mode

1- So, we have a function somewhere that returns a number between 0-9.
2- We first write a describe block to group all the tests related to getRandomNum and name it test getRandomNum.
3- Then, we write the it block in which we write our test.
4- Finally, we run a for loop to test our function. We should expect a number lessThan 100 every time we call getRandomNum().

If everything goes well, the test should pass.

the test successed

Now, what if we refactored our code and accidentally made a tiny mistake.

function getRandomNum() {
  return Math.floor(Math.random() * 100 + 100); // 100 was added to the number by mistake
}
Enter fullscreen mode Exit fullscreen mode

If we run the test again, it should fail.
a red failed test

The cool part is that Cypress tells you exactly where the test fails and why it fails. Here in our test, we told Cypress to expect getRandomNum() to return a number lessThan 100, but instead we got 190. So Cypress complained about it to let us know that something went wrong after we refactored the code.

Cypress is much more powerful than just testing a function that generates random numbers, especially for applications built in React -- for example. It provides you with tools that help you mount your components and test their behavior. It's exactly like simulating how a user uses your website.

Let's pretend that we have a website and that we want to test that the Contact link gets redirected to the contact page onClick.

// 1
describe.only("test contact link", () => {
  // 2
  it("should be redirected to a contact page", () => {
    // 3
    cy.visit("http://localhost:3000");
    // 4
    cy.contains("Contact").click();
    // 5
    cy.url().should("include", "/contact");
  });
});
Enter fullscreen mode Exit fullscreen mode

1- Add a describe block, and since we only care about testing the contact link right now, run that test only.
2- Start the it block.
3- First, ask Cypress (cy) to visit/go to the application.
4*- Then we tell it to find the first element that has the text Contact and clicks it.
5- Finally, Cypress tests if the the current url contains /contact.

Note*: contains is case sensitive. If the text is "Contact" but you write "contact"(lower case), the link won't be found and you'll have a Timed out error. You can override that behavior by passing { matchCase: false } as an option to contains.

cy.contains("Contact", { matchCase: false }).click()
Enter fullscreen mode Exit fullscreen mode

Also, note that contains finds the first element that has the text "Contact", so if you have two "Contact" links on the page you'll need to use get with contains.

cy.get("nav").contains("Contact") // to get the link in the nav
cy.get("footer").contains("Contact") // to get the link in the footer
//Or
cy.contains("nav", "Contact").click();
cy.contains("footer", "Contact").click();
Enter fullscreen mode Exit fullscreen mode

What if we have a login page where people can login or see an error message if the login fails... let's test that.

describe("Login", () => {
  // we write the code we want to run before each test in a beforeEach block
  beforeEach(() => {
    cy.visit("http://localhost:3000/login");
  });

  it("should succeed with correct credentials ", () => {
    // find the element (input) with id:username and type hajarNasr
    cy.get("#username").type("hajarNasr");
    // find the element (input) with id:password and type uniquePassword
    cy.get("#password").type("uniquePassword");
    // find the element (button) with id:submit-btn and click it
    cy.get("#submit-btn").click();

    // those two lines confirm that the user has logged successfully in and got redirected to homepage
    cy.contains("Welcome hajarNasr");
    cy.url().should("include", "/home");  });
});

// To test that an error msg gets displayed when user enters wrong data.

  it("should fail with wrong credentials ", () => {
    cy.get("#username").type("fakeUser");
    cy.get("#password").type("fakePassword");
    cy.get("#submit-btn").click();

    // this line confirms that user has not logged in because the page doen't contain a welcome message
    cy.should("not.contain", "Welcome fakeUser");
    // and this should confirm that we're still in the login page
    cy.url().should("include", "/login");
    // and that an element with a className error is displayed in red.
    cy.get(".error").should("have.css", "color", "rgb(255, 0, 0)");
  });
Enter fullscreen mode Exit fullscreen mode

References:

Top comments (0)