This is not the place to have a discussion about what I call E2E testing and how it may differ to what you think E2E testing encompasses.

Over the past few months I've been doing some work on automated E2E tests with NightwatchJS. Our goal is to test our happy paths on every commit/deploy/release, making sure we have not broken anything inadvertently.

Our Setup

We use nightwatch-cucumber to write our features and then implement their step definitions. I've never used cucumber before, but I like it. 1

Locally we test using chrome (via chromedriver). Tbh, it's fantastic.

Our build servers, on the other hand, run the tests using PhantomJS, since we stood this up when the --headless flag wasn't around.

Let's talk about how we can migrate from PhantomJS (deprecated now) to Headless Chrome.

Installing Chrome on CentOS

The headless flag is ready to rock-n-roll, since v59 (on linux), so I've been having a go at installing it on our CentOS agents.

We orchestrate our boxes with Chef, so the code below will be written in that syntax.

Enable the stable chrome repo

yum_repository 'google-chrome' do
  description 'Google Chrome Repo'
  baseurl '$basearch'
  gpgkey ''
  action :add

Install google chrome stable

package 'google-chrome-stable' do
  action :install

Install fonts

At first I only installed google chrome. Unfortunately, we ran into a few problems when trying to use it. After a quick google I found I needed to install the fonts Chrome requires.

%w(ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc).each do |pkg|
  package pkg do
    action :install

Trying it out

After all of that you should get a successful output when you try to do something in headless chrome. The example below is taking a screenshot.

[vagrant@default-centos-7 ~]$ google-chrome --headless --disable-gpu --screenshot
[0810/] Written to file screenshot.png.

NightwatchJS Setup

We needed to continue to use Selenium to get our Nightwatch tests running. Maybe one of these days I'll look at trying standalone Chrome.

Our nightwatch.config.js is below. If you run a self-signed cert on your localhost (for dev presumably) you'll have to add an extra flag in the args.

Note: when running with the --headless flag, chrome will not accept insecure certificates and will error with a timeout or something along those lines. This issue has been reported and a fix should be coming soon.

const chromedriverPath = require('chromedriver').path;
const seleniumPath = require('selenium-server').path;

module.exports = {
  output_folder: 'reports',
  custom_commands_path: '',
  custom_assertions_path: '',
  page_objects_path: 'page_objects',
  globals_path: 'config/globals.js',
  selenium: {
    start_process: true,
    server_path: seleniumPath,
    log_path: '',
    host: '',
    port: 4444,
    cli_args: {
      '': chromedriverPath
  test_settings: {
    default: {
      selenium_port: 4444,
      selenium_host: '',
      silent: true,
      screenshots: {
        enabled: true,
        on_failure: true,
        path: 'screenshots/'
      request_timeout_options: {
        timeout: 60 * 1000,
        retry_attempts: 3
      desiredCapabilities: {
        browserName: 'chrome',
        javascriptEnabled: true,
        acceptSslCerts: true,
        chromeOptions: {
          args: [
            '--window-size=1400,1000', // not really required for this
            // '--allow-insecure-localhost', // only needed if using self-signed cert

I have tried so many combinations and this is the only one that seemed to have worked for me.

Hope this helps at least someone!

**1:** WHOOOAAAAAHHHHH some of you may be saying as you don't like Gherkin or Cucumber. As I write the steps to have dynamic variables, it makes my life a lot easier to copy and paste steps and change one word around. Then a little switch in the step definition and I've just enabled a full new path. It's neither here nor there. To each their own.