AngularJS-based applications are meant to be developed in test-driven manner, but how to run e2e tests in browser on GitLab CI?

End-to-end tests for AngularJS run TypeScript specs on Protractor in real browser as if user would interact with software.

The problem

How to launch an actual browser on Continuous Integration platform with just command line at our disposal? There is no obvious out-of-the-box solution for CI/CD pipelines.

The plan

  • Run Xvfb (X virtual framebuffer)
  • Launch all AngularJS tests on Xvfb display with headless Chrome (Selenium testing)

The solution

Protractor configuration

// protractor.conf.js

const { SpecReporter } = require('jasmine-spec-reporter');

exports.config = {
  allScriptsTimeout: 11000,
  specs: [
    // spec paths
  capabilities: {
    browserName: 'chrome',
    chromeOptions: {
      args: ['--headless', '--no-sandbox']
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    print: function() {}
  beforeLaunch: function() {
      project: 'e2e/tsconfig.e2e.json'
  onPrepare: function() {
    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));

GitLab CI configuration

# .gitlab-ci.yml

image: node:8

  - test
  - build

  stage: test
    # Add Google Chrome to aptitude's (package manager) sources
    - echo "deb stable main" | tee -a /etc/apt/sources.list
    # Fetch Chrome's PGP keys for secure installation
    - wget -q -O - | apt-key add -
    # Update aptitude's package sources
    - apt-get -qq update -y
    # Install latest Chrome stable, Xvfb packages
    - apt-get -qq install -y google-chrome-stable xvfb gtk2-engines-pixbuf xfonts-cyrillic xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable imagemagick x11-apps default-jre
    # Launch Xvfb
    - Xvfb :0 -ac -screen 0 1024x768x24 &
    # Export display for Chrome
    - export DISPLAY=:99
    # Install AngularJS CLI exclusively
    # Add --unsafe-perm to resolve problems with node-gyp infinite loop on Docker
    - npm install --silent --unsafe-perm -g @angular/[email protected]
    # Install remaining project dependencies
    - npm install --silent
    # Download Selenium server JAR, drivers for Chrome
    - node ./node_modules/.bin/webdriver-manager update
    - ng test --single-run --progress false
    - ng e2e --progress false

  stage: build
    - npm install --silent --unsafe-perm -g @angular/[email protected]
    - npm install --silent
    - ng build --prod --progress false
      - dist/
    - master