Unit Testing Angular app in a dockerized Jenkins container.

Anupam Mahapatra
5 min readFeb 19, 2019

Install node.js and Angular CLI on your machine :
There are 100 ways to install node.js on your machine if you are on a Linux flavored environment. But I recommend using nvm. Please follow this article to setup node. please install version 10 or newer as our subsequent dependencies need that.
Install Angular CLI with this:
npm install -g @angular/cli

Create an Angular project:

Create a new Angular project from scratch as or clone my git project. This project has a few changes over the boilerplate code as I will explain here.

Do a package update before moving forward
npm update

We have updated karma configuration at src/karma.conf.js

browsers:[  
"ChromeHeadlessNoSandbox"
],
customLaunchers:{
ChromeHeadlessNoSandbox:{
base:"ChromeHeadless",
flags:[
"--no-sandbox",
// required to run without privileges in Docker
"--disable-web-security",
"--disable-gpu",
"--remote-debugging-port=9222"
]
}
},
singleRun:false,
junitReporter:{
outputDir:'test-reports',
// results will be saved as $outputDir/$browserName.xml
outputFile
:'junit-report.xml',
// if included,
results will be saved as $outputDir/$browserName/$outputFile
suite
:'',
// suite will become the package name attribute in xml testsuite element
useBrowserName
:false,
// add browser name to report and classes names
nameFormatter
:undefined,
// function (browser,
result) to customize the name attribute in xml testcase element
classNameFormatter
:undefined,
// function (browser,
result) to customize the classname attribute in xml testcase element
properties
:{
} // key value pair of properties to add to the section of the report
}
});

We have also updated protractor configuration file at e2e/protractor.conf.js

capabilities:{  
chromeOptions:{
args:[
'--headless',
'--disable-gpu',
'--window-size=800x600',
'--disable-dev-shm-usage',
'--no-sandbox'
]
},
browserName:"ChromeHeadless"
},

Updated run commands at e2e/protractor.conf.js

"scripts":{  
"ng":"ng",
"start":"ng serve",
"build":"ng build",
"test":"ng test --watch=false",
"lint":"ng lint",
"e2e":"ng e2e"
},

In my project, I have included very basic test cases in location :

project/src/app

under the file name ~/*.spec.ts

If your machine doesn’t have chrome installed, please look for the instruction towards the end of the second part of this blog With all this setup, if we run

npm run test

It should run the test cases and give us the result

Running a Jenkins Container:

Jenkins is one of several CI/CD tool out there to build, test and deploy your application automatically. Jenkins Pipeline as script prompted my team to try out the tool. In this blog, I will try to run Jenkins inside a container on my local machine, enhance capabilities to run a NodeJS application and publish our unit test results for one such application.

If we look at the official Jenkins image on dockerhub : https://hub.docker.com/r/jenkins/jenkins/
and go to the documentation link and inspect the docker file in the repo
we can see that the user inside the application is ‘Jenkins’.
This restricts some of the application installations that we will do going forward, so I made my own docker layer on top of the official layer. My dockerfile contains just this :

FROM jenkins/jenkins:lts
# if we want to install via apt
USER root

With this dockerfile, we can build our image with the following:

docker build -t myj .

Here the -t tags the image with the name myj: latest. The ‘.’ at the end is very important as you may already know.

We will run the container with the following:

docker run — name myj2 -p 9090:8080 -p 60000:50000 -v /Users/<user name>/<some folder path > :/var/jenkins_home myj:latest

The command maps the <PHYSICAL PORT>: <CONTAINER PORT>
Also, it maps the </PHYSICAL/FILE/FOLDER/LOCATION>: <LOCATION IN THE CONTAINER>. Upon running this we will have a container which has a file system mapped to a physical location in my computer which I can check on. I don’t run it detached and keep that tab open. it’s not necessary, but just my preference.

If everything went well, you will have a page up on 127.0.0.1:9090 which is asking you for the Admin Password. Go into the physical folder that we have the container mapped to as look for “Secret/InitialPassword” file
After logging with the password, we will be asked for: Install suggested plugins. I am making sure the
1. NodeJS plugin under “Build Tool”
2. JUnit plugin under “Build Analysis and reporting” is installed.
We can install these plugins at a later stage too from inside the Jenkins portal.
Installing all the plugins will take some time.
After that, it will ask you to set up a user name and password for the user and you will have the Jenkins home page up and running.

Go to “Jenkins” tab on the top left corner of the homepage. From thereon Manager Jenkins > Global Tool configuration > NodeJS

As you can see from the screenshot, I have chosen to install Node JS 10.15.1 for this blog. I have also assigned the name “node” for the plugin. Test out the installation first. Go to the homepage > New Item
Give it some name and choose the “Pipeline” type from the menu below. Inside the pipeline definition, use this code

pipeline {
agent any

tools {nodejs "node"}

stages {
stage('Example') {
steps {
sh 'npm config ls'
}
}
}
}

This is basically building a node task and running an npm command. If the installation goes through, we know that the installation went good.

Next thing we need for our unit tests to work is a headless chrome. NodeJS projects with unit testing through Karma come default with support for Chrome Headless. We can install this using

# Set the Chrome repo.
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list
# Install Chrome.
RUN apt-get update && apt-get -y install google-chrome-stable .

Making a build plan :

In a general build plan, we can make changes to the default setup such as

and in the build select a script with the following code

git -c http.sslVerify=false clone https://USERNAME:PASSWORD@GITHUB.URL/APP_NAME.gitcd APP_NAMEnpm install -g @angular/cli -ynpm update -ynpm run test

and run your build.
It should give you the same results that we verified on our local system, but this time inside a container of Jenkins.

--

--