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
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);
}
});
});
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.
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
}
If we run the test again, it should fail.
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");
});
});
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()
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();
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)");
});
References:
Top comments (0)