'use strict';
const showdown = require('showdown').setOption('tables', 'true');
const lodash = require('lodash');
const fse = require('fs-extra');
const rootRequire = require('rpcm-root-require');
const LoggerWrapper = rootRequire('/platform-helpers/log4js-wrapper');
const logger = LoggerWrapper.getLogger();
const converter = new showdown.Converter();
const RunnerCapabilitiesBuilder = rootRequire('platform-helpers/runner-capabilities-builder.js');
rootRequire('/platform-helpers/string-extensions');
/**
* Runner capabilities builder
*
* @module
* @static
* @requires rpcm-root-require
* @requires lodash
* @requires fs-extra
* @requires log4js
* @requires showdown
* @requires runner-capabilities-builder
* @requires string-extensions
*/
class RunnerTestsListBuilder {
/**
* Builds the capabilities object for the test run
*
* @param {object} object with the runner options
* @static
* @testFile tests\self-tests\unit-tests\*******.spec.js
* @throws
*/
static build (opts) {
const granularList = [];
// keep the order of the browsers consistent
for (let i = 0; i < opts.capabilities.length; i++) {
const capability = opts.capabilities[i];
for (let j = 0; j < opts.specs.length; j++) {
const specEntry = opts.specs[j];
let spec;
let testContext = false;
let testTitle = false;
// simple entry, this is the filename
if (typeof specEntry === 'string') {
spec = specEntry;
} else if (typeof specEntry === 'object') {
spec = specEntry.testFile;
testContext = specEntry.testContext || false;
if (typeof testContext === 'string') {
testContext = converter.makeHtml(testContext);
}
testTitle = specEntry.testTitle || false;
}
capability['teal:capabilityNumber'] = i + 1;
capability['sauce:options'] = {};
// add a copy of the test to the tmp folder, where it will be included with the reports for reference
const shortSpecName = spec.split('/')[spec.split('/').length - 1];
fse.copySync(spec, '{0}/tmp/tests/{1}'.format(rootRequire.rootPath, shortSpecName));
const capCopy = lodash.cloneDeep(capability);
// copy and make sure it's an object for lookups (could be a string)
const specificSpec = typeof specEntry === 'object' ? specEntry : {};
const addFallback = function (single, shared) {
if (typeof single !== 'undefined') return single;
return shared;
};
// update any specific settings (overwrite the shared ones)
RunnerCapabilitiesBuilder.settingsList.forEach(setting => {
capCopy['teal:{0}'.format(setting)] = addFallback(specificSpec[setting], capCopy['teal:{0}'.format(setting)]);
});
capCopy['teal:runRemotely'] = (capCopy['teal:runRemotely'] || capCopy['teal:runCrossBrowser']);
capCopy['teal:specPath'] = spec;
capCopy['teal:testContext'] = testContext;
capCopy['teal:testTitle'] = testTitle;
capCopy['teal:helpers'] = opts.helpers;
capCopy['teal:enableSauceConnect'] = false;
// only use Sauce Connect if the proxy is also enabled - otherwise there's not really a point
if (opts.enableProxy) {
capCopy['teal:enableSauceConnect'] = true;
capCopy['sauce:options'].tunnelIdentifier = process.env.SAUCE_TUNNEL_IDENTIFIER;
capCopy['sauce:options'].idleTimeout = 300; // verrrryyyyy long, as a test
capCopy['sauce:options'].commandTimeout = 300; // verrrryyyyy long, as a test
// capCopy['sauce:options'].name = 'my example name' // fix this later
}
const isSafariOrIe = (capability.browserName.toLowerCase() === 'safari' || capability.browserName.toLowerCase() === 'internet explorer');
// don't use safari or ie if enableProxy is true unless enableSauceConnect is also true
if (!opts.enableProxy || !isSafariOrIe) {
granularList.push({
capability: capCopy,
spec: spec,
// don't use SauceConnect for browsers that allow insecure certs unless forced
sauceConnect: opts.enableProxy
});
} else {
logger.warn('runner-helper.js --> Skipping {0} on {1}, if you want to use a proxy on certain browsers you need to use the \'enableSauceConnect\' option in your runner.'
.format(spec, capCopy.browserName));
}
}
}
return granularList;
}
}
module.exports = RunnerTestsListBuilder;