@testim/testim-cli
Version:
Command line interface for running Testing on you CI
174 lines (138 loc) • 4.88 kB
JavaScript
var WebdriverIO = require('../index.js'),
q = require('q'),
Mocha = require('mocha'),
should = require('should'), // jshint ignore:line
SauceLabs = require('saucelabs'),
glob = require('glob'),
merge = require('deepmerge'),
env = process.env._ENV,
specDir = env.match(/^(functional|multibrowser)$/),
failures = 0,
client, sessionID, specFiles, specDir, browserA, browserB;
var mocha = new Mocha({
timeout: 100000,
reporter: 'spec'
});
// globals for tests
conf = require('./conf/index.js');
assert = require('chai').assert;
expect = require('chai').expect;
require('chai').use(require('chai-as-promised'));
if(specDir) {
// only test functional test spec if required
specFiles = 'test/spec/' + specDir[0] + '/**/*.js';
} else {
// otherwise test global + device specific test specs
specFiles = '{test/spec/' + env + '/**/*.js,test/spec/*.js}';
}
function handleError(e) {
console.log('========== ERROR ==========\n', e.message, '\n', e.stack);
process.exit(1);
}
q.nfcall(glob, process.env._SPEC || specFiles).then(function(files) {
files.forEach(function(file) {
mocha.addFile(file);
});
console.log('-> Start Mocha tests');
var mochaDefer = q.defer();
mocha.run.call(mocha, mochaDefer.resolve.bind(mochaDefer));
return mochaDefer.promise;
}, handleError).then(function(f) {
failures = typeof f === 'number' ? f : f.failures || 'unknown';
console.log('-> Mocha tests finished with', failures, 'failures');
if (!client) {
return process.exit(failures);
}
sessionID = (client.requestHandler || {}).sessionID;
console.log('-> end all clients');
return client[conf.runsWithSauce ? 'end' : 'endAll']().catch(function(e) {});
}, handleError).then(function() {
/**
* only update sauce job when running in CI
*/
if (!process.env.TRAVIS_BUILD_ID || specDir) {
return process.exit(failures);
}
var sauceAccount = new SauceLabs({
username: process.env.SAUCE_USERNAME,
password: process.env.SAUCE_ACCESS_KEY
});
console.log('-> update sauce job: ', sessionID);
var updateJobDefer = q.defer();
sauceAccount.updateJob(sessionID, {
passed: failures === 0,
public: true
}, updateJobDefer.resolve.bind(updateJobDefer));
return updateJobDefer.promise;
}, handleError).then(function(res) {
console.log('-> sauce job updated', res);
process.exit(failures);
});
h = {
noError: function(err) {
assert(err === undefined);
},
checkResult: function(expected) {
return function(result) {
if(expected instanceof Array) {
return expected.should.containDeep([result]);
}
expected.should.be.exactly(result);
};
},
setup: function(options) {
if(!options) {
options = {};
}
return function() {
if(options.remoteOptions) {
conf = merge(conf, options.remoteOptions);
}
/**
* if instance already exists and no new session was requested return existing instance
*/
if (client && client.requestHandler.sessionID && !options.newSession) {
this.client = client;
/**
* if new session was requested create temporary instance
*/
} else if(options.newSession) {
this.client = WebdriverIO.remote(conf).init();
/**
* otherwise store created intance for other specs
*/
} else {
this.client = client = WebdriverIO.remote(conf).init();
}
return this.client.url(options.url || conf.testPage.start);
};
},
setupMultibrowser: function(options) {
if(!options) {
options = {};
}
return function(done) {
if(client && !options.asSingleton) {
this.matrix = client;
this.browserA = browserA;
this.browserB = browserB;
} else {
this.matrix = WebdriverIO.multiremote(conf.capabilities).init();
this.browserA = this.matrix.select('browserA');
this.browserB = this.matrix.select('browserB');
if(!options.asSingleton) {
client = this.matrix;
browserA = this.browserA;
browserB = this.browserB;
}
}
this.matrix.url(options.url || conf.testPage.start).call(done);
};
},
instanceLoop: function(cb) {
var self = this;
Object.keys(this.matrix.instances).forEach(function(instanceName) {
cb.call(self, self.matrix[instanceName]);
});
}
};