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.
GitHub Source
System Requirements
- Node - 16.10.0 +
- Angular Cli - 13
- Cypress latest
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
$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.
Delete existing example tests files.
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
/cypress/videos
Login Page
Demo Angular routing project by default navigates to #/login route.
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.
Test Fail
Just modified cy.get('h1').contains('Sign In') to break the test.
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
Login Page Desktop
You will find this login screen for Angular routing demo project.
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('srinivas@9lessons.info');
cy.get('#loginPassword').focus().clear().type('12345');
cy.get('#loginButton').click();
});
it('should navigate to dashboard page', () => {
cy.get('h1').contains('Dashboard');
});
});
Test Result
Mobile View
The login page has different design for mobile/iPad screens.
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("srinivas@9lessons.info");
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("srinivas@9lessons.info", "123456");
});
it("should display the dashboard page", () => {
cy.get("h1").contains("Dashboard");
cy.get("h3").contains("Your email is srinivas@9lessons.info");
});
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("srinivas@9lessons.info", "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.
0 comments:
Post a Comment
Note: only a member of this blog may post a comment.