Cypress UI Automation End to End Testing
Wall Script
MailxEngine
Monday, November 15, 2021

Cypress UI Automation End to End Testing

UI automation is the most important part of the CI/CD(continuous integration and continuous delivery) process. Integration testing helps you to avoid manual regression testing and improve the application quality. In this post I will explain how to implement UI automation testing to existing Angular projects using the Cypress tool, this is a great alternative for Protractor. Take a look at the video tutorials for better understanding.

Cypress UI Automation End to End Testing

GitHub Source

System Requirements
  • Node - 16.10.0 +
  • Angular Cli - 13
  • Cypress latest
Video Tutorial


Install Cypress Globally
npm install -g cypress

Angular Project
Clone the existing Angular project. Start the project using ng serve command. Angular Routing with Lazy Loading Design Pattern
$git clone new https://github.com/srinivastamada/angular-routing.git
$cd create-angular-project

Add Cypress Plugin
npm install cypress --save-dev

Cypress Setup
Execute the following command inside the project directory. Angular
npx cypress open

React
yarn run cypress open

This will generate a new cypress folder with cypress.json. Here cypress.json is a configuration file.
Cypress UI Automation folder

Delete existing example tests files.
Cypress UI Automation folder

cypress.json
This is a configuration file for Cypress, you can enable and disable the options. Here I have configured default browser view port window to 1200x800 pixels and testFiles pointed to integration folder. Configure baseUrl value based on the project.
{
"baseUrl": "http://localhost:4200",
"testFiles": ["*.*"],
"viewportWidth": 1200,
"viewportHeight": 800,
"screenshotOnRunFailure": true,
"video": true,
"watchForFileChanges": false,
"chromeWebSecurity": false,
"pageLoadTimeout": 60000
}


Note: Video tutorial will give better explanation.

.gitignore
Ignore videos and screenshots to Git.
/cypress/screenshots 
/cypress/videos

Login Page
Demo Angular routing project by default navigates to #/login route.
Cypress UI login page

login.spec.js
Create a login.spec.js file under the integration folder. Here the test is verifying the page title and route name.
describe('Login page', () => {
beforeEach(() => {
cy.visit('http://localhost:4200')
})
it('should display the login page', () => {
cy.url().should('include', '/login');
cy.get('h1').contains('Login');
});
});

Run Cypress
Go to project path and execute the following command. Make sure the project is up and running with ng server.
$cypress run

Test Success
Success test result.
Cypress Test success

Test Fail
Just modified cy.get('h1').contains('Sign In') to break the test.
Cypress test failure

Here you will find the test video and screenshot. I would recommend disable video option, because more tests will create large video recording file. Go to cypress.json and change the video value to false
Cypress UI Automation folder

Login Page Desktop
You will find this login screen for Angular routing demo project.
Cypress UI login page

login.spec.ts
We are implementing more tests to verify page labels and form validations.
describe('Login page', () => {
beforeEach(() => {
cy.visit('http://localhost:4200')
})
it('should display the login page', () => {
cy.url().should('include', '/login');
cy.get('h1').contains('Login');
});

it('should verify page labels', () => {
cy.get('h1').contains('Login');
cy.get('#forgotLink').contains('Forgot password?');
cy.get('#loginButton').contains('Login');
cy.get('#signupMenuLink').contains('Signup');
cy.get('#loginMenuLink').contains('Login');
});

it('should verify login validation', () => {
cy.get('#loginButton').click();
cy.get('.has-text-danger').contains('Please give valid data');
});

it('should check with invalid login inputs', () => {
cy.get('#loginEmail').focus().clear().type('srinivas');
cy.get('#loginPassword').focus().clear().type('12345');
cy.get('#loginButton').click();
cy.get('.has-text-danger').contains('Please give valid data');
});

it('should check with valid login inputs', () => {
cy.get('#loginEmail').focus().clear().type('[email protected]');
cy.get('#loginPassword').focus().clear().type('12345');
cy.get('#loginButton').click();
});

it('should navigate to dashboard page', () => {
cy.get('h1').contains('Dashboard');
});
});

Test Result
Cypress Test result

Mobile View
The login page has different design for mobile/iPad screens.
Cypress Test success

Test for Multiple Views
We can add tests based on the context. Here you will find two different contexts for Mobile and Desktop versions.
describe("Login page", () => {
const baseUrl = Cypress.config().baseUrl;
context("Mobile/Ipad view", () => {
beforeEach(() => {
cy.viewport(550, 750);
cy.visit(baseUrl);
});
it("should verify page labels for mobile/ipad view", () => {
cy.visit("http://localhost:4200");
cy.get("h1").contains("Login");
cy.get("#forgotLink").contains("Forgot password?");
cy.get("#loginButton").contains("Login");
cy.get(".navbar-burger").should("be.visible");
});
});
context("Desktop", () => {
beforeEach(() => {
cy.visit(baseUrl);
});
it("should display the login page", () => {
cy.url().should("include", "/login");
cy.get("h1").contains("Login");
});

it("should verify page labels", () => {
cy.get("h1").contains("Login");
cy.get("#forgotLink").contains("Forgot password?");
cy.get("#loginButton").contains("Login");
cy.get("#signupMenuLink").contains("Signup");
cy.get("#loginMenuLink").contains("Login");
cy.get(".navbar-burger").should("not.visible");
});

it("should verify login validation", () => {
cy.get("#loginButton").click();
cy.get(".has-text-danger").contains("Please give valid data");
});

it("should check with invalid login inputs", () => {
cy.get("#loginEmail").focus().clear().type("srinivas");
cy.get("#loginPassword").focus().clear().type("12345");
cy.get("#loginButton").click();
cy.get(".has-text-danger").contains("Please give valid data");
});

it("should check with valid login inputs", () => {
cy.get("#loginEmail").focus().clear().type("[email protected]");
cy.get("#loginPassword").focus().clear().type("12345");
cy.get("#loginButton").click();
});

it("should navigate to dashboard page", () => {
cy.get("h1").contains("Dashboard");
});
});
});


commands.js
Cypress global commands file. Here you implement your own commands for reusable actions. Here we implemented a login command for upcoming tests.
Cypress.Commands.add("login", (email, password) => {
const baseUrl = Cypress.config().baseUrl;
cy.visit(baseUrl);
cy.get("#loginEmail").focus().clear().type(email);
cy.get("#loginPassword").focus().clear().type(password);
cy.get("#loginButton").click();
});

Dashboard Page
Accessing the Dashboard page needed a user authentication. You have to use cy.login action to navigate the dashboard page.
dashboard.spec.js
describe("Dashboard page", () => {
beforeEach(() => {
cy.login("[email protected]", "123456");
});
it("should display the dashboard page", () => {
cy.get("h1").contains("Dashboard");
cy.get("h3").contains("Your email is [email protected]");
});
});

Settings Page
This is similar like the dashboard page. Initially the page is landing on dashboard page and based on the menu link settings link action, the settings page will appear. settings.spec.js
describe("Settings page", () => {
beforeEach(() => {
cy.login("[email protected]", "123456");
cy.get("#settingsLink").click();
});

it("should display the settings page", () => {
cy.wait(500);
cy.url().should("include""/settings");
cy.get("h1").contains("Settings");
});
});


This way you can implement tests for your components to product your work. When you are working the project with multiple developers.
web notification

1 comments:

Make in India