CircleCI Test Configuration for Angular Projects
Tags: angular, testing, ci, unittest
Published: 2019-08-18 20:26:42

One of the best ways to keep your project bug free is through a test suite, but it's easy to forget to run tests all the time. Continuous integration (CI) servers let you set up your project repository so that your tests run on every commit and pull request.

[CircleCI](https://www.circleci.com) is a paid service, but it is provided free for open source projects. You can create a public project on Github and add CircleCI without paying.

<br>

---

<br>

>## Configure project for CircleCI

* Create a folder called `.circleci` at the project root![CircleCI Folder](https://thepracticaldev.s3.amazonaws.com/i/25q2wjrw27un8mdujzph.png)

* In the new folder, create a file called `config.yml` with the following content

```YAML
    version: 2

    jobs:
        # The test job
        test:
            working_directory: ~/project-name
            docker:
                - image: circleci/node:10-browsers
            steps:
                # Checkout the code from the branch into the working_directory
                - checkout
                # Log the current branch
                - run:
                    name: Show current branch
                    command: echo ${CIRCLE_BRANCH}
                # Restore local dependencies from cache
                - restore_cache:
                    keys:
                    - v1-dependencies-{{ checksum "package-lock.json" }}
                    - v1-dependencies-
                # Install project dependencies
                - run:
                    name: Install local dependencies
                    command: npm install
                # Cache local dependencies if they don't exist
                - save_cache:
                    key: v1-dependencies-{{ checksum "package-lock.json" }}
                    paths:
                        - node_modules
                # Lint the source code
                - run:
                    name: Linting
                    command: npm run lint
                # Test the source code
                - run:
                    name: Testing
                    command: npm run test -- --no-watch --no-progress --browsers=ChromeHeadlessCI
                # End to End test
                - run:
                    name: End to End Test
                    command: npm run e2e -- --protractor-config=e2e/protractor-ci.conf.js

```
* [Configure CLI for testing in chrome](#configure)

* Commit you changes and push them to your repository

* [Sign up for Circle CI](https://circleci.com/docs/2.0/first-steps/) and [add your project](https://circleci.com/docs/2.0/projects/). Your project should start building.

<br>

---

<br>

>## Circle CI configuration file

A Circle CI config file has 3 main components; a version, a list of jobs and a list of workflows.

The version is simply the Circle CI version that we are going to use.

A job can be compared to an independent environment for running a list of commands or steps. Common things you can achieve with a job include;
* instaling the tools you need to run/build/test your project.
* executing bash commands.
* storing or restoring items from the Circle CI cache.

A workflow is a way to manage your jobs. You may need a job to run only on specific branches or at specific times, or you want some of the jobs to run in parallel and some in sequence. Workflow is where you make these configurations.

In our case, we have only one job; **the test job**. These are the attributes of the test job.
* The docker attribute: Specify a docker image used to create the container of the environment. Circle CI comes with a list of pre-built images that you can find [here](https://circleci.com/docs/2.0/circleci-images/)
```YAML
    docker:
        - image: circleci/node:10-browsers
```
* The working directory attribute: The current directory which will be the place where all the steps run.
```YAML
    working_directory: ~/project-name
```
* The steps attribute: This is a list of steps (commands) that you want to run in the current job.
```YAML
    steps
        # Checkout the code from the branch into the working_directory
        # Log the current branch
        # Restore local dependencies from cache

```
There are a few types of steps we'll use in our configuration.
* The **checkout** step: used to checkout the code from the current branch into the working directory.
```YAML
    - checkout
```
* The **run** step: used to execute a bash command. You can specify a descriptive name which you are going to see in the Circle CI interface
```YAML
    - run:
        name: Testing the project
        command: npm run test
```
* The **save_cache** step: used to store a cache of a file or a directory in the Circle CI storage. A common use case is to install the npm dependencies only once and then cache the node_modules folder using a hash of the package-lock.json (or package.json) file as the cache key.
```YAML
    -save_cache:
        key: v1-dependencies-{{ checksum "package-lock.json" }}
            paths:
                - node_modules
```
* The **restore_cache** step; used to restore a cached item using the cache key.
```YAML
    - restore_cache:
        keys:
            - v1-dependencies-{{ checksum "package-lock.json" }}
            - v1-dependencies-
```

<br>

---

<br>

> ## Putting the CI job into a workflow

In this case, we want to run the test job when we commit to develop, staging or the master branch. A workflow by default is triggered by pushing to any branch.

The test workflow has a `filter` attribute which is used to select the branches that it will run on. The code snippet is shown below
```YAML
    workflows:
        version: 2
        # the test workflow
        test_workflow:
            jobs:
                - deploy:
                    filters:
                        branches:
                            only:
                                - develop
                                - staging
                                - master
```
Add the workflow code snippet to the config.yml file, commit and push your changes. Your project is ready to build.

<br>

---

<br>

> <h2 id='configure'>Configure CLI for CI testing in Chrome</h2>

When the CLI commands `ng test` and `ng e2e` are generally running the CI tests in your environment, you might still need to adjust your configuration to run the Chrome browser tests.

Follow the steps below to configure CLI
* In the Karma configuration file, `karma.conf.js`, add a custom launcher called ChromeHeadlessCI below browsers:
```javascript
    browsers: ['Chrome'],
    customLaunchers: {
        ChromeHeadlessCI: {
            base: 'ChromeHeadless',
            flags: ['--no-sandbox']
        }
    },
```
* In the root folder of your e2e tests project, create a new file named `protractor-ci.conf.js`. This new file extends the original `protractor.conf.js`
```javascript
    const config = require('./protractor.conf').config;

    config.capabilities = {
        browserName: 'chrome',
        chromeOptions: {
            args: ['--headless', '--no-sandbox']
        }
    };

    exports.config = config;
```
Now you can run the following commands to use the --no-sandbox flag:
```bash
    ng test --no-watch --no-progress --browsers=ChromeHeadlessCI
    ng e2e --protractor -config=e2e/protractor-ci.conf.js
```

<br>

---

<br>

> ## References
> * [Angular Test Documentation](https://angular.io/guide/testing#configure-project-for-circle-ci)
> * [Free Code Camp tutorial on CircleCI 2.0](https://www.freecodecamp.org/news/our-journey-for-using-circleci-2-0-to-build-and-deploy-an-angular-app-to-aws-s3-8e7ea3f51503/)