'Karma Chrome Headless not working on Jenkins

When I run the below setup with Docker locally on my mac everything works fine.

But same setup does not work on Jenkins running on Ubuntu 16.04

ChromiumHeadless have not captured in 60000 ms, killing.

Following error log is from Jenkins console:

25 05 2018 06:35:09.076:INFO [karma]: Karma v2.0.2 server started at http://0.0.0.0:9222/
25 05 2018 06:35:09.079:INFO [launcher]: Launching browser Chromium_no_sandbox with unlimited concurrency
25 05 2018 06:35:09.090:INFO [launcher]: Starting browser ChromiumHeadless
25 05 2018 06:36:09.128:WARN [launcher]: ChromiumHeadless have not captured in 60000 ms, killing.
25 05 2018 06:36:09.139:INFO [launcher]: Trying to start ChromiumHeadless again (1/2).
25 05 2018 06:37:09.140:WARN [launcher]: ChromiumHeadless have not captured in 60000 ms, killing.
25 05 2018 06:37:09.147:INFO [launcher]: Trying to start ChromiumHeadless again (2/2).

Package.json ... "testProd": "./node_modules/karma/bin/karma start karma.conf-prod.js --single-run",

Dockerfile

FROM zenika/alpine-node:latest
LABEL name="product-web"

# Update apk repositories
RUN echo "http://dl-2.alpinelinux.org/alpine/edge/main" > /etc/apk/repositories
RUN echo "http://dl-2.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
RUN echo "http://dl-2.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories

# Install chromium
RUN apk -U --no-cache \
    --allow-untrusted add \
    zlib-dev \
    chromium \
    xvfb \
    wait4ports \
    xorg-server \
    dbus \
    ttf-freefont \
    mesa-dri-swrast \
    grep \
    udev \
    && apk del --purge --force linux-headers binutils-gold gnupg zlib-dev libc-utils \
    && rm -rf /var/lib/apt/lists/* \
    /var/cache/apk/* \
    /usr/share/man \
    /tmp/* \
    /usr/lib/node_modules/npm/man \
    /usr/lib/node_modules/npm/doc \
    /usr/lib/node_modules/npm/html \
    /usr/lib/node_modules/npm/scripts

WORKDIR /home/dev/code
COPY . .

#RUN rm -rf node_modules && npm cache clear --force

ENV CHROME_BIN=/usr/bin/chromium-browser
ENV CHROME_PATH=/usr/lib/chromium/

RUN npm install
RUN npm run testProd && npm run buildProd

karma.conf-prod.js

const path = require('path');
module.exports = function(config) {
    config.set({
        basePath: '',
        browsers: ['ChromeHeadlessNoSandbox'],
    customLaunchers: {
        ChromeHeadlessNoSandbox: {
            base: 'ChromeHeadless',
            flags: [
                '--no-sandbox',
                '--user-data-dir=/tmp/chrome-test-profile',
                '--disable-web-security'
            ]
        }
    },
        frameworks: ['mocha', 'chai'],
        captureConsole: true,
        files: [
            'node_modules/babel-polyfill/dist/polyfill.js',
            'test/root.js'
        ],
        preprocessors: {
            'src/index.js': ['webpack', 'sourcemap'],
            'test/root.js': ['webpack']
        },
        webpack: {
            devtool: 'inline-source-map',
            module: {
                loaders: [
                    {
                        test: /\.js$/,
                        loader: 'babel-loader',
                        exclude: path.resolve(__dirname, 'node_modules'),
                        query: {
                            plugins: ['transform-decorators-legacy', 'transform-regenerator'],
                            presets: ['env', 'stage-1', 'react']
                        }
                    },
                    {
                        test: /\.json$/,
                        loader: 'json-loader',
                    },
                ]
            },
            externals: {
                'react/addons': true,
                'react/lib/ExecutionEnvironment': true,
                'react/lib/ReactContext': true
            }
        },
        webpackServer: {
            noInfo: true
        },
        reporters: ['spec'],
        port: 9222,
        logLevel: config.LOG_INFO
    });
};

I even tried with logLevel: config.LOG_DEBUG but did not show anything missing or unusual.



Solution 1:[1]

The issue was with the jenkin's xbmc display driver .

I fixed it by switching to Travic-CI

before_install: - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start - sleep 3

Solution 2:[2]

Based on issue Karma 1.6 breaks Headless support for Chrome created on github, it is related to the slower machine and happens, because it took > 60 seconds before test bundle was parsed and executed by Chrome and therefore test run was started and communicated back to Karma server. Reasons why it may take long vary.

There are 2 ways to handle timeout:

Investigate why your test bundle loads >60 seconds and make sure it loads faster.

  1. Increase browserNoActivityTimeout to highter value, so test bundle has enough time to load.
  2. This particular appearance of timeout does not seem to be a Karma issue, but rather problem in the project or misconfiguration.

Based on the Derek's comment

There was a connection that was disconnecting too soon.

He found that in /static/karma.js, when the socket was created, there was a timeout value that is hardcoded to 2 seconds (see below). He just added another 0 to make it 20 seconds and the connection stayed open long enough for the server to respond to the initial request. karma/client/main.js

Lines 14 to 20 in e79463b

var socket = io(location.host, { 
   reconnectionDelay: 500, 
   reconnectionDelayMax: Infinity, 
   timeout: 2000, 
   path: KARMA_PROXY_PATH + KARMA_URL_ROOT.substr(1) + 'socket.io', 
   'sync disconnect on unload': true 
 }) 

The next problem he faced was that Karma thought there was no activity even though there was traffic going back and forth on the socket. To fix that he just added browserNoActivityTimeout: 60000 to the Karma configuration.

You need to change the timeout configuration more then that is in the configuration file.

Solution 3:[3]

package.json

"karma": "~1.7.1",
"karma-chrome-launcher": "~2.2.0",

karma.conf.js

browsers: ['ChromeHeadlessNoSandbox'],
customLaunchers: {
    ChromeHeadlessNoSandbox: {
        base: 'ChromeHeadless',
        flags: ['--no-sandbox']
    }
},

and need to use the below command with --source-map=false

"qa-test": "ng test --watch=false --progress=false --browsers=ChromeHeadless --code-coverage --source-map=false"

my build got succeeded after this change.

Solution 4:[4]

had the same issue "ChromHeadless have not captured in 60000 ms" (failing after 3 attempts), on Jenkins running on RHEL 7.5. Tried several configurations, and eventually adding the --proxy-bypass-list, and --proxy-server made it work.

minimal working configuration

 browsers: ['HeadlessChrome'],
    customLaunchers:{
      HeadlessChrome:{
        base: 'ChromeHeadless',
        flags: [
          '--no-sandbox',
          '--proxy-bypass-list=*',
          '--proxy-server=\'http://<my org proxy server>:8080\''
       ]
      }
    },

Below you can see a few more options in the config like the one I used. We have two browser configuration, Chrome for day to day dev work where we do want to see the browser open, and a headless chrome for CI/CD tests when building our solution on a Jenkins server.

Command line to run it in Jenkins:

npm run test -- -cc -sr --browser HeadlessChrome

In package.json we added a couple of lines to the scripts section:

 "test": "ng test",
    "test-dev": "ng test --browser Chrome",

karma.conf.js

 browsers: ['Chrome', 'HeadlessChrome'],
    customLaunchers:{
      HeadlessChrome:{
        base: 'ChromeHeadless',
        flags: [
          '--no-sandbox',
       //   '--remote-debugging-port=9222',
       //   '--enable-logging',
       //   '--user-data-dir=./karma-chrome',
       //   '--v=1',
       //   '--disable-background-timer-throttling',
       //   '--disable-renderer-backgrounding',
          '--proxy-bypass-list=*',
          '--proxy-server=\'http://<my org proxy server>:8080\''
       ]
      }
    },

After the above steps it worked from a shell on the Jenkins machine. However it failed when running as a Jenkins job with Cannot start ChromeHeadless Trying to start ChromeHeadless again (1/2). printed to the console.

I compared the env variables, and after a few trial and errors found that XDG_DATA_DIRS environment variable exists when logged in a bash shell (where headless chrome tests succeeds), and this variable was not defined in the failing Jenkins job env. So adding it (copied from the shell env | grep XDG_DATA_DIRS) finally solved it. I guess I should check what is the minimal configuration/dirs I should put there, and what is the root cause, but its working now :-)

Added the below to the jenkins job just before running the test

export XDG_DATA_DIRS=/users/<jenkins user e.g. jk1003>/.local/share/flatpak/exports/share/:/var/lib/flatpak/exports/share/:/usr/local/share/:/usr/share/

Another possible solution

A friend told me that he solved such an issue long ago using Xvfb

Solution 5:[5]

For me, below worked, seems version and conf issue:

In package.json I am using:

"karma": "1.3.0",
"karma-chrome-launcher": "2.2.0"

In karma conf add this:

    browsers: ['ChromeHeadlessNoSandbox'],
    customLaunchers: {
        ChromeHeadlessNoSandbox: {
            base: 'ChromeHeadless',
            flags: ['--no-sandbox']
        }
    }

It shall work.

Solution 6:[6]

For me I have to add the chrome local ip/port explicitly to NO_PROXY so that Karma could capture the browser.

In the karma.conf.js:

process.env.NO_PROXY = 'localhost, 0.0.0.0/4201, 0.0.0.0/9876';
process.env.no_proxy = 'localhost, 0.0.0.0/4201, 0.0.0.0/9876';

Note, even I export it in our jenkinsfile, it does not work, Have to be in the js process.

Solution 7:[7]

In my case, the machine was out of disk space, specifically for the /tmp/ folder.

Once I fixed that, the Jenkins job is able to run successfully again.

Solution 8:[8]

I was getting the same issue on Jenkins 2 with ChromeHeadless/ChromeHeadlessNoSandbox.

Setting captureTimeout in karma.ci.conf.js(in my case) as well as adding --no-proxy-server flag worked for me.

  customLaunchers: {
        ChromeHeadlessNoSandbox: {
            base: 'ChromeHeadless',
                flags: ['--no-sandbox','--no-proxy-server']
               }
            },
    captureTimeout: 180000

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Abdul Rahim
Solution 4
Solution 5 Ankit Saxena
Solution 6
Solution 7 Mihai Maerean
Solution 8 Ganesh Thorat