E2E tests aim to evaluate the system from the user’s point of view, simulating operations such as typing in a field, clicking on a button, carrying out the assertion, and evaluating the messages on the screen, just as a user would evaluate whether the action was successful or not.
In the Angular ecosystem, in the past, there was a tool called Protractor to help with this type of testing, but it was discontinued by the Angular team in favor of other, more focused open source tools.
Among these new tools, we are going to use one of the most popular ones, called Cypress.
The Cypress framework is a tool that aims to help developers create and run all types of tests in the test pyramid, from unitary to E2E.
Let’s see it in action in our project. For that, we need to install and configure it. Follow these steps to install and configure Cypress:
- We will use the Angular CLI to install and configure Cypress. In the command line of your operating system, run the following command:
ng add @cypress/schematic
- Following the prompt’s instructions, we have created the Cypress files, in addition to adapting angular.json with the settings it needs.
- To run the tool, run the following command at the operating system prompt:
ng e2e
- The preceding command will run our application as we would with the ng serve command and open the tool’s interface.

Figure 10.3 – Execution of tests by Cypress
- Select the desired browser and click on Start E2E Testing and we will have the test execution interface.
Notice that we already have a file called spec.cy.ts. It was generated by Cypress to exemplify the creation of the test script. Let’s go back to Visual Studio Code and check this file:
describe(‘My First Test’, () => {
it(‘Visits the initial project page’, () => {
cy.visit(‘/’)
cy.contains(‘app is running!’)
})
})
Unlike Angular, Cypress uses Mocha (https://mochajs.org/) as a testing framework. However, in practice, as we can see in the preceding example, it is very similar to the Jasmine framework.
We have the describe function to create the test suite and the it function to create the test cases. The difference here is the cy object, which represents the browser’s interface, and with this object, we can perform actions and evaluate the state of the page, from the user’s point of view. Here, we use the visit method to go to the initial endpoint and we use the contains method to evaluate whether the text app is running appears on the page. We are going to delete this file because we are going to create the scripts for our application.
In the same folder as where the previous file was, we will create the login.cy.ts file and add the following code:
describe(‘Login Page:’, () => {
it(‘should login to the diary with the correct credentials.’, () => {
cy.visit(‘/’);
cy.get(‘#username’).type(‘mario’);
cy.get(‘#password’).type(‘1234’);
cy.get(‘:nth-child(3) > .w-full’).click();
cy.contains(‘Workout diary’);
});
});
In this test, we used the get method to obtain the page element through CSS queries so that we could act on them. First, we take the username and password fields and use the type method to simulate the user typing in these fields. Then we locate the Confirm button and use the click method to simulate the mouse click action.
To assert the test, we used the contains method to assess whether the diary screen was displayed.
The tricky part of creating this script is the CSS queries needed to get the elements we need. But at this point, Cypress helps us a lot.
By running the test, we can see that there is a target icon at the top of the screen. By clicking on it and selecting the element we want, Cypress will generate the necessary command ready to copy and paste into our script.

Figure 10.4 – Cypress helping with the CSS query
In this script, however, there is a problem in selecting the button, in addition to the query not being clear to another person reading the test script. If the team needs to change the layout, the test could break unduly.
To avoid this error, let’s change the login component template:
<button
type=”submit”
class=”w-full rounded bg-blue-500 px-4 py-2 text-white”
[disabled]=”loginForm.invalid”
[class.opacity-50]=”loginForm.invalid”
data-cy=”submit”
>
Login
</button>
With this custom HTML element, we can use the element marked with the data-cy attribute for our test:
describe(‘Login Page:’, () => {
it(‘should login to the diary with the correct credentials.’, () => {
cy.visit(‘/’);
cy.get(‘#username’).type(‘mario’);
cy.get(‘#password’).type(‘1234’);
cy.get(‘[data-cy=”submit”]’).click();
cy.contains(‘Workout diary’);
});
});
No Responses