Modify Protractor Configuration for Build Server

As a part of setting up the Ionic 2 project I am currently working on, I decided to also configure end-to-end testing using Protractor. I based it on the excellent Clicker demo project. It worked great for running tests during development, but lacks support for headless test execution on a build server.

Since build server has no desktop associated, Chrome browser needs to be replaced with a headless alternative, PhantomJS:

npm install --save-dev phantomjs-prebuilt

The following changes to protractor.conf.js will instruct Protractor to use PhantomJs instead of Chrome:

exports.config = {
  // ...
  capabilities: {
    'browserName': 'phantomjs',
    'phantomjs.binary.path': require('phantomjs-prebuilt').path
  },
  directConnect: true,
  // ...
}

Setting phantomjs.binary.path as above will ensure that Protractor can find the PhantomJS executable, no matter the OS in use.

This is enough to ensure that the build server can run the tests, however we also want the test results to show up in the build server dashboard. In order to achieve this, we need to use a reporter that our build server can understand. For TeamCity, there's a dedicated TeamCityReporter available in jasmine-reporters package:

npm install --save-dev jasmine-reporters

Activating it requires another change in protractor.conf.js:

exports.config = {
  // ...
  onPrepare: function() {
    var TeamCityReporter = require('jasmine-reporters').TeamCityReporter;
    jasmine.getEnv().addReporter(new TeamCityReporter());
  }
  // ...
}

While I could apply both changes directly to protractor.conf.js, the tests would then be run the same way in my development environment, but I don't want that. I'd like to keep using Chrome and SpecReporter during development and only switch to PhantomJS and and TeamCityReporter on the build server.

Protractor allows me to specify the configuration file I want it use:

protractor ./protractor.conf.teamcity.js

Now I can make a copy of the original protractor.conf.js file, and modify it instead. Even better, I can keep my configuration DRY by referencing the original file in protractor.conf.teamcity.js instead of copying it, and only modify the values, which I want to be different:

var config = exports.config = require('./protractor.conf.js').config;

config.capabilities = {
  'browserName': 'phantomjs',
  'phantomjs.binary.path': require('phantomjs-prebuilt').path
};
config.directConnect = false;
config.onPrepare = function() {
  var TeamCityReporter = require('jasmine-reporters').TeamCityReporter;
  jasmine.getEnv().addReporter(new TeamCityReporter());
};

If I now make any changes to protractor.conf.js, they will automatically be reflected in protractor.conf.teamcity.js. I've effectively avoided the risk of forgetting to modify both files and causing the configurations to diverge.

Copyright
Creative Commons License