Lambda IT Blog

E2E Tests with Cypress 4 & Angular 9

Publiziert am 15. Mar 2020 von Matthias Baldi

With Cypress, you can write E2E tests with a well-developed tooling.
Cypress does not need browser drivers like Selenium, because the code is executed directly as Javascript in the browser. Therefore, the installation is quite short and no periodic updates of the drivers are needed.
The Cypress CLI comes with a handy Electron UI to simplify debugging with DOM snapshots and pretty log output.
In addition to the normal features like screenshots, Cypress can also record videos of the tests performed by default.
This article is about getting started with Cypress together with Angular. The same setup could be done with other frontend technologies as well.

Tooling:

  • Cypress 4
  • Angular 9, with matching Typescript
  • Chrome 80
  • Visual Studio Code

Installation and Setup Cypress

Prerequisites:

  • Installed NodeJS
  • Installed Angular CLI
  • If you have a proxy, you need to configure the proxy for node, Cypress will download some executables after it's installation.

We start by setting up a new Angular app with the flag --defaults:

ng new cypressApp --defaults
cd cypressApp

Then we install the Cypress tooling. Cypress will download the Electron app during the installation.

npm install cypress --save-dev

To scaffold all necessary folders and files we can start Cypress the first time.
With the following command we bring up the Electron Cypress UI:

./node_modules/.bin/cypress open # you can close if after the first successful start

Alternatively, you can add a script entry to your package.json file to start the same command with npm run cypress:open to avoid having to write the path every time:

...,
"scripts": {
    ...,
    "cypress:open": "cypress open",
    ...
},
...

As previously mentioned, Cypress has created the required folder structure {project_folder}/cypress . In our case the Angular workplace is our project_folder.
In the cypress folder you will find the folders integration, fixtures, plugins and support.

  • fixtures: Folder to store test data you need for example to simulate REST calls or file uploads.
    It would be very easy to test REST API calls with cy.request vs the stored fixtures.
  • integration: In this folder we will save all our spec files you can structure your tests in subfolders.
  • plugins: Folder to install third-party plugins, later we will install a plugin
  • support: Includes possible custom commands, which allows you to outsource repeatable code from your tests in separate commands. i.e. logins, form submits etc.

Cypress UI after first start

As soon as we get the necessary folders, we are able to install the required Typescript types and a plugin for Cypress to integrate Typescript.

Attention: The installation of the Typescript plugin fails if you install the plugin together with Cypress.
The plugin requires the Cypress folder structure.

npm install @types/cypress @bahmutov/add-typescript-to-cypress --save-dev

By installing the Typescript plugin for Cypress the appropriate tsconfig.json file is created in the ./cypress folder.
Please check that it looks like the following piece of code to get the best possible integration:

{
    "extends": "../tsconfig.json",
    "include": ["../node_modules/cypress", "**/*.ts"],
    "exclude": []
}

Writing Tests with Cypress

As a next step we will create a folder under ./cypress/integration/mymodule and in there a first file to write a test, in my case: sample_spec.ts. Fill in the following code into this file:

describe('Angular Welcome Board', () => {
    it('has title', () => {
        cy.visit('http://localhost:4200');
        cy.contains('cypressApp app is running!');
    });
});

Let's check if this first test works against the previously generated Angular app.
Open a second terminal and start the app with ng start and Cypress with ng run cypress:open. Cypress list your created spec-file and click on it to start the test. Seconds later this test should be green and look like this:

Cypress first Javascript Test

The first simple test works without problems, but when we take a look at the code, we see that we have added a cy.visit.
If we now have several tests that all call cy.visit and e.g. call a login in a more complicated setup, this is not nice enough and should be outsourced. Cypress stores these commands in the cypress/support folder.
There is already a pre-generated command.js file, which we will rename command.ts and copy the following code. Afterwards you have to reload the Electron app by clicking the Retry Button and may to restart your test.

declare global {
    namespace Cypress {
        interface Chainable {
            /**
             * Open browser and navigate
             *
             * @param [host='http://localhost'] hostname where your app is running
             * @param [port=4200] number of port where your app is running
             */
            open(host?: string, port?: number): Chainable<Element>;

            /**
             * Navigate to given button in our page
             * @param buttonNo button number
             */
            findAndClick(buttonNo: number): Chainable<Element>;
        }
    }
}

// helper functions
export function open(host: string = 'http://localhost', port: number = 4200) {
    cy.visit(`${host}:${port}`);
    // may do here your login or other stuff
}

export function findAndClick(buttonNo: number) {
    cy.get('div:nth-child(8)')
        .find(`div:nth-child(${buttonNo})`)
        .click();
}

Cypress.Commands.add('open', open);
Cypress.Commands.add('findAndClick', findAndClick);

We define a new namespace to extend the Cypress commands by our own written commands.
Additionally, we will type our existing methods, Here I added some comments and optional parameters for the open method.

Then remove the cy.visit() command in your spec file and add the following line at the beginning of your test:

// ...
before(() => {
    cy.open();
});
// ...

As soon as you saved your code, Cypress will run the test again and it should still be green.
We copied an other helper function before, so let's use it in another test case.

// ...
it('able to click buttons', () => {
    cy.findAndClick(2);
    cy.findAndClick(5);
    cy.get('div.terminal').contains('ng test');
});
// ...

Directly after saving this file, you should be able to see that this test is now listed and is green.
Now it is time to get to know another nice feature of Cypress - DOM Snapshots.

Cypress HTML DOM snapshot feature

Cypress creates a Dom Snapshot for every command and allows you to see the hitbox and the state before the event and after.
If you need to debug further, you can open the browser [F12] to get a more detailed view of what happened.

Using Cypress with CI

To run the Cypress tests in a CI/CD environment, an Electron (headed) UI is not the most elegant solution, as it requires additional dependencies, such as an X server or other.
Cypress has an other command than open to run the tests in a headless Electron environment.
Let's configure this command in our package.json:

...,
"scripts": {
    ...,
    "cypress:ci": "cypress run",
    "cypress:open": "cypress open"
},
...

If you want to test cross browser or just not with the Electron environment, you can add the flags --browser chrome --headless to use any installed Browser.

When you now run npm run cypress:ci you will see that Cypress is recording per default a video of your browser.
Should you have a limited disk-space and you may set the property to false.

To configure this behaviour you can use CLI flags or a config file. During the installation, cypress already created an empty cypress.json file in your project root.
Copy the following snippet to this config file and add -C cypress.json to your cypress:run command in the package.json.

The video attribute configures the mp4 creation after every executed testcase and via the ignoreTestFiles you can control which files will be executed during a test run, so exclude e.g the example test files.

{
    "ignoreTestFiles": "*.js",
    "video": false
}

The report after the command npm run cypress:run will then look like this:

Cypress Headless Report

Conclusion

It is very easy and fast to set up tests with Cypress E2E, which is ready to run on most common operating systems. If your system is behind an enterprise proxy, the setup may be problematic because Cypress can't automatically load the required binaries.

But why should we use Cypress for Angular projects instead of the standard solution Protractor? With Protractor you still need a Selenium driver, which is downloaded during the npm installation. Protractor has less tooling and less debugging features than Cypress (i.e. Dom Snapshots or integrated Video recording) and you have to patch it simultaneously with the used browser.

The maintainability of the tests is on a comparable level depending on the available selectors. With Cypress it should be very easy to parallelize tests and execute them faster, because they are run directly in the browser with Javascript.

Aktuelles im 2020

Visualisierungsworkshop

Wir wollen auch in nicht-technischen Skills am Ball bleiben und haben mit Vanessa Bigler einen Einblick in die Kunst der Visualisierung am Flipchart erhalten. Nach einer kurzen theoretischen Einführung ging es dann auch sofort in den praktischen Teil des Workshops.

Mit einfachen Symbolen kombiniert durch die richtigen Techniken und Stiften konnte jeder in kurzer Zeit ansehnliche Flipcharts erstellen. Auch die anfänglichen Befürchtungen, dass man nicht zeichnen kann, waren schnell vergessen.

Der Grundstein für eine erfolgreiche Visualisierung Karriere ist nun gelegt. Jetzt heisst es einfach üben, üben, üben….

weiterlesen

Team Workshop

Am 25. Juni begab sich das ganze Lambda Team auf den Niesen für einen internen Workshop. Der Start des Workshops war nicht oben auf dem Niesen, sondern unten an der Talstation. Erste Aufgabe des Tages: den Gipfel in irgendeiner Form erklimmen. Die einen entschieden sich zu wandern, andere joggten den Weg hinauf – jeder in seinem Tempo. Nachdem wir unsere Batterien mit einem währschaften Mittagessen wieder aufgeladen haben, sind wir gestärkt in den zweiten Teil gestartet.

weiterlesen

Kontaktformular

Haben Sie Fragen?

Haben Sie ein spannendes Projekt oder brauchen Sie Unterstützung beim Lösen einer Herausforderung?

Wir freuen uns auf Ihre Kontaktaufnahme.

Lambda Team

Swiss Made Software

Die Lambda IT bekennt sich zum Standort Bern und Schweiz und entwickelt nicht nur zu 100% alle Software in der Schweiz, sondern versucht auch, wenn immer möglich, die lokalen Partner und Industrien zu berücksichtigen.