14
votes

I am trying to use Cypress with an Angular (v. 5) CLI application.

The tests works fine when running locally, because here I can just start the serve command before running the cypress tests.

I tried following the documentation here, but none of the commands seems to be working.

I tried varioues combination, looking like this:

"cypress:run:report": "./node_modules/.bin/cypress run --record --key <key>",
"cypress:run:ci": "start-server-and-test serve:dev http://localhost:4200 cypress:run:report",
"cypress:run:ci2": "npm run -s serve:dev & npm run -s cypress:run:report",

Thanks in advance.

6
Hey! Do you mind changing the correct answer to the most upvoted answer? That may save some folks :DDev
Consider it done @Dev 😅DauleDK
Thanks buddy :DDev

6 Answers

14
votes

I wasn't satisfied with any of the answers provided, so I came up with the following:

Step 1: Install dev dependencies

npm install --save-dev concurrently wait-on

Step 2: Write the following scripts in your package.json:

"scripts": {
  "start": "ng serve",
  ...
  "cy:open": "cypress open",
  "cy:run": "cypress run",
  "e2e": "concurrently \"npm run start\" \"wait-on http-get://localhost:4200 && npm run cy:run\" --kill-others --success first",
  "e2e-gui": "concurrently \"npm run start\" \"wait-on http-get://localhost:4200 && npm run cy:open\" --kill-others --success first",
  ...
}

Then you can run npm run e2e or npm run e2e-gui.

Voila!

5
votes

start-server-and-test does not seem to integrate well with the 'ng serve' command. I got it to work by not using angular-cli for serving the app - no Modules API required:

package.json

"scripts": {
    "ci:serve": "ng build && http-server dist -p 4200",
    "cy:run": "cypress run",
    "cy:ci": "start-server-and-test ci:serve http://localhost:4200 cy:run"
}
"devDependencies": {
    // omitted angular & cypress deps
    "start-server-and-test": "x.x.x",
    "http-server": "x.x.x"
}
3
votes

Step 1: Install devDependencies:

npm i -D angular-http-server start-server-and-test

angular-http-server to create a simple dev-server

start-server-and-test to starts server, waits for URL, then runs test command; when the tests end, shuts down server

Step 2: Add scripts on package.json

"scripts": {
  "build": "ng build",
  "cy:run": "cypress run",
  "ci:cy-run": "start-server-and-test ci:start-server 4200 cy:run",
  "ci:start-server": "angular-http-server --silent --path ./dist/project-name -p 4200"
}

Step 4: Add this commands to your CI scripts:

npm run build
npm run ci:cy-run

Optional: Consider turning off videos and screenshotOnRunFailure on cypress.json and support directory

2
votes

After trying to solve this for some hours, I developed a solution using the Cypress Module API.

Package.json

"cypress:run:ci": "node ng-serve-and-run-cypress.js",

ng-serve-and-run-cypress

'use strict';

const cypress = require('cypress');
const { spawn } = require('child_process');
const child = spawn('ng', ['serve']);

// On error exit, and print
child.on('error', (err) => process.exit(1));
child.stderr.on('data', (data) => console.log(data.toString()));
// On exit, print exit code
child.on('exit', (code, signal) => console.log(`Child exitting with code ${code}`));

child.stdout.on('data', (data) => {
    const asString = data.toString();
    // Log the output to inform CI/User
    console.log(asString);
    if (asString.includes('webpack: Compiled successfully.')) {
        cypress.run({})
        .then((results) => {
            const errorCode = (results.failures >= 1) ? 1 : 0;
            child.kill();
            // When cypress is done running the tests, exit with errorCode from above.
            process.exit(errorCode);
        })
        .catch((err) => {
            child.kill();
            // If cypress hit's an error, exit with code 1
            process.exit(1);
        })
    }
});

Just post here if you are interested in more details.

1
votes

After trying several solution found on the Web I adopted the following one that is pretty nice and straightforward:

First of all you need to install wait-on and npm-run-all libs.

npm i wait-on npm-run-all --save-dev

wait-on waits the app to be served (up and running) on a specific port before proceeding with the next command npm-run-all allows to run multiple commands in parallel.

Here as it should appear the scripts section:

"scripts": {
   ...
   "serve": "ng serve",
   "cy:wait-run": "./node_modules/.bin/wait-on http-get://localhost:4200/ && cypress run",
   "cy:serve-and-run": "node_modules/.bin/run-p -r \"serve\" \"cy:wait-run\" "
   ...
 }
0
votes

I used lite-server because http-server didnt work out of the box for me with Angular routing.

npm i -D  lite-server && start-server-and-test

then in my package.json file

"scripts": {
   "ci:serve:employee-onboarding": "ng build --prod --project=employee-onboarding && lite-server -c lite-server-employee-onboarding-config.json",
   "cypress:ci:employee-onboarding": "start-server-and-test ci:serve:employee-onboarding http://localhost:4201 cy:run:employee-onboarding",
   "cy:run:employee-onboarding": "node_modules/.bin/cypress run --config-file ./apps/employee-onboarding-e2e/cypress-ci.json",
}

I run it like this:

npm run cypress:ci:employee-onboarding

my cypress-ci.json file looks like this:

{
  "baseUrl": "http://localhost:4201/",
  "integrationFolder": "apps/employee-onboarding-e2e/cypress/integration/employee-onboarding/tests-with-server-calls-mocked/",
  "fixturesFolder": "apps/employee-onboarding-e2e/cypress/fixtures"
}

and my lite-server-employee-onboarding-config.json file looks like this:

{
   "port": 4201,
   "server": { "baseDir": "dist/apps/employee-onboarding" }
}