Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Running Cypress Tests in an Angular Project With Travis CI

DZone's Guide to

Running Cypress Tests in an Angular Project With Travis CI

Following up on another article, we show web devs how to run tests on their Angular apps in a DevOps environment. Read on to get started!

· Web Dev Zone ·
Free Resource

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

In my last blog post, I explained how to get started with Cypress tests. The next step would be running these tests in a Continuous Integration and Continuous Delivery (CI and CD) environment. The advantage of this is that with every commit the tests are being executed automatically and you get feedback about whether your application is still doing good or not automatically.

Travis CI is a very well known Continuous Integration Environment and is very common when working with OSS projects. The best thing about it is that it is free to use for an open source project.

Preparations

To get started we need to modify our project.json a bit. Referring to this demo we know that with

"cypress:open": "concurrently \"ng serve\" \"cypress open\""

We can start our end-to-end testing to see what is going on with our application. The problem is that on CI/CD environments you do want to run everything only once and throw an error if at least one test is failing and you want to shut down the server and clean everything up when things have done good and you can continue to the next step in your build/release pipeline.

Create an npm Continuous Integration Command

I like using the abstraction of commands from the package.json scripts tag especially when it comes to CI. So we can add a command for now which - no matter which CI service in the end - will call and trigger our end to end tests.

"cypress:ci": "<should do something>",

Building the Application

We want to test our production ready application. So the first script we will add is the ng build --prod command to get an application output we can test.

"cypress:ci": "ng build --prod <should do something>",

Starting the Server to Serve the App

Having done that, we want to start an independent HTTP server which serves our application like a real web server would do if a human would enter our site and click around. I am using http-server a lot. When installed globally, it has a nice and easy CLI which we can use to run our web server wherever we want. We can install it for our project and access it via a script tag. Knowing that our application will build into the folder dist/cypressTest in our case we can start a web server and give the path as a command line argument. Let's create a new script tag for that:

"cypress:ci": "ng build --prod <should do something>",
"start:ci": "http-server ./dist/cypressTest -a localhost -p 8000 -c-1"

So http-server ./dist/cypressTest is starting the server on our required path. With -a localhost we can specify the IP which is going to be used. This is localhost or 127.0.0.1 in this case. As a port we sepcify -p 8000 and because we do a lot of reloading we are disabling the cache with -c-1.

Rmemeber we told cypress to load localhost:8000 in our tests. cy.visit('http://localhost:8000');

Starting Cypress

So we are building our application now and are running a web server on Travis CI so Cypress is able to access it (like a user would do it) and can test it. The cypress open command opens Cypress and keeps it open (who would have thought of that). What we need however is a command to run all the tests we implemented once and shut down then. We can use the cypress run command (doc). So let's create a script tag for that as well:

"cypress:ci": "ng build --prod <should do something>",
"start:ci": "http-server ./dist/cypressTest -a localhost -p 8000 -c-1",
"cypress:run": "cypress run",

Getting the Pieces Together (I of II)

Let's stick a few pieces together so far: we can let Cypress run and start the tests. We can build our application and start a web server to serve our app to Cypress. We only have to concatenate it for our main CI command Travis CI has to call in the end:

"cypress:ci": "ng build --prod && start:ci && cypress:run",
"start:ci": "http-server ./dist/cypressTest -a localhost -p 8000 -c-1",
"cypress:run": "cypress run",

The && is just running one command after the other when the current one is finished. But starting a web server never finishes really. It is started and will run until you shut it down. On CI environments, you want to shut down after all the tests have run and you want it to happen automatically. So we need something to run commands in parallel and that will stop automatically.

Running Commands in Parallel

Running commands in parallel can be done with the npm package npm-run-all. The command run-p does exactly that: running npm commands in parallel. After installing it, let us use this one to help us out:

"cypress:ci": "ng build --prod && run-p start:ci cypress:run",
"start:ci": "http-server ./dist/cypressTest -a localhost -p 8000 -c-1",
"cypress:run": "cypress run",

With that we are building our application in prod mode (thanks to the angular cli) and start our webserver and cypress in parallel. But how do we shut down if everything went well?

Getting the Pieces Together (II of II)

Taking a look at the documentation from run-all we can see that the -r or --race can “kill all tasks when a task finished with zero.” Cool! Exactly what we need. So let's use this one:

"scripts": {
    ...
    "cypress:run": "cypress run",
    "cypress:ci": "ng build --prod && run-p --race start:ci cypress:run",
    "start:ci": "http-server ./dist/cypressTest -a localhost -p 8000 -c-1"
  },

Cool. Now we need to tell Travis to call exactly that command cypress:ci which we use to trigger all our tests.

Connecting Your Project to Travis CI

To get Travis going, you need to connect your project with Travis once you've logged in and added your repository. If you have done that, you can add a travis.yml file to your project on the root level with the following content:

language: node_js
node_js:
  - "8.9"
cache:
  directories:
    - ~/.npm
    - node_modules
install:
  - npm install
script:
  - npm run cypress:ci

First, we set the language to node_js defining the version afterward. The install tasks are just a plain npm install to install all dependencies. After doing that Travis CI should automatically call npm run cypress:ci which is the command from our package.json.

If you've connected your GitHub repository to Travis and added this file, the checking of the build should automatically trigger and your Cypress tests should run automatically.

CypressTravis

Hope this helps!

Fabian

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

Topics:
web dev ,angular ,travis ci ,cypress

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}