const rootRequire = require('rpcm-root-require');
const fse = require('fs-extra');
const lodash = require('lodash');
const path = require('path');
const showdown = require('showdown').setOption('tables', 'true');
const converter = new showdown.Converter();
rootRequire('/platform-helpers/string-extensions');
/**
* Runner options validator
*
* @module
* @static
* @requires rpcm-root-require
* @requires fs-extra
* @requires lodash
* @requires string-extensions
*/
class RunnerOptionsValidator {
/**
* Validates the options provided when the test Runner is called
*
* @param {object} object with the runner options
* @static
* @testFile tests\self-tests\unit-tests\runner-options-validator.spec.js
* @throws Throws the specific error related to the provided invalid option.
*/
static validate = (opts) => {
opts = opts || {};
opts.enableProxy = !!opts.enableProxy;
opts.enableTrace = !!opts.enableTrace;
opts.reportOnly = !!opts.reportOnly;
opts.showInBrowser = opts.showInBrowser !== false;
opts.runFullCrossBrowser = !!opts.runFullCrossBrowser;
// crossbrowser is always true if fullcrossbrowser is true
opts.runCrossBrowser = !!opts.runCrossBrowser || opts.runFullCrossBrowser;
opts.extraProxyCommands = opts.extraProxyCommands || '';
// cross browser is run remotely, always, and the proxy also currently requires it, as set up
opts.runRemotely = !!opts.runRemotely || opts.runCrossBrowser || opts.enableProxy;
opts.showDurations = !!opts.showDurations;
opts.enableSauceConnect = !!opts.enableSauceConnect || !!opts.enableProxy;
opts.summaryReportTitle = opts.summaryReportTitle || '';
opts.reportContext = opts.reportContext || '';
opts.summaryContext = opts.summaryContext || '';
opts.hasReportContext = (opts.reportContext && opts.reportContext !== '') || false;
opts.hasSummaryContext = (opts.summaryContext && opts.summaryContext !== '') || false;
opts.runRetries = opts.runRetries || 0;
if (isNaN(opts.runRetries) || opts.runRetries < 0 || Array.isArray(opts.runRetries) || typeof opts.runRetries === 'boolean') opts.runRetries = 0;
opts.runRetries = parseInt(opts.runRetries);
if (!Array.isArray(opts.blockPatterns)) opts.blockPatterns = [];
if (!Array.isArray(opts.urlRewrites)) opts.urlRewrites = [];
if (!Array.isArray(opts.helpers)) opts.helpers = [];
if (typeof opts.extraProxyCommands !== 'string') throw new Error('The parameter \'extraProxyCommands\' needs to be a string!');
if (typeof opts.summaryReportTitle !== 'string') throw new Error('The parameter \'summaryReportTitle\' needs to be a string!');
if (typeof opts.reportContext !== 'string') throw new Error('The parameter \'reportContext\' needs to be a string!');
if (typeof opts.summaryContext !== 'string') throw new Error('The parameter \'summaryContext\' needs to be a string!');
if (typeof opts.enableProxy !== 'boolean') throw new Error('The parameter \'enableProxy\' needs to be a boolean!');
if (typeof opts.enableTrace !== 'boolean') throw new Error('The parameter \'enableTrace\' needs to be a boolean!');
if (typeof opts.runFullCrossBrowser !== 'boolean') throw new Error('The parameter \'runFullCrossBrowser\' needs to be a boolean!');
if (typeof opts.runCrossBrowser !== 'boolean') throw new Error('The parameter \'runCrossBrowser\' needs to be a boolean!');
if (typeof opts.runRemotely !== 'boolean') throw new Error('The parameter \'runRemotely\' needs to be a boolean!');
if (typeof opts.showDurations !== 'boolean') throw new Error('The parameter \'showDurations\' needs to be a boolean!');
if (typeof opts.enableSauceConnect !== 'boolean') throw new Error('The parameter \'enableSauceConnect\' needs to be a boolean!');
/**
* REPORT INFO
*/
opts.reportContext = converter.makeHtml(opts.reportContext);
opts.summaryContext = converter.makeHtml(opts.summaryContext);
/**
* TEST FILES SPECS
*/
if (!Array.isArray(opts.specs)) throw new Error('Please provide an array with at least one test file to run!');
if (opts.specs.length < 1) throw new Error('Please provide an array with at least one test file to run!');
opts.specs.forEach((spec, index) => {
if (lodash.isString(spec)) {
opts.specs[index] = { testFile: spec };
}
if (lodash.isPlainObject(spec)) {
if (!fse.existsSync('{0}/{1}'.format(rootRequire.rootPath, spec.testFile))) { throw new Error('Please provide a path to an existing test file! File not found: {0}'.format(spec.testFile)); }
}
});
/**
* BLOCK PATTERNS
*/
if (opts.blockPatterns.length > 0) {
opts.blockPatterns.forEach(blockPattern => {
if (!lodash.isPlainObject(blockPattern)) { throw new Error('Each item in the \'blockPatterns\' array should be an object'); }
if (!blockPattern.pattern && !blockPattern.type) { throw new Error('Each item in the \'blockPatterns\' array should have following compulsory properties: \'pattern\' and \'type\''); }
});
}
/**
* URL REWRITES
*/
if (opts.urlRewrites.length > 0) {
opts.urlRewrites.forEach(urlRewrite => {
if (!lodash.isPlainObject(urlRewrite)) { throw new Error('Each item in the \'urlRewrites\' array should be an object'); }
if (!urlRewrite.pattern && !urlRewrite.type && !urlRewrite.target && !urlRewrite.replacement) { throw new Error('Each item in the \'urlRewrites\' array should have following compulsory properties: \'pattern\', \'type\', \'target\' and \'replacement\''); }
});
}
/**
* TRACE DATA
*
* These are options but they have no requirements except if 'enableTrace' is true.
* If they are specified they will be used to generate a trace. The trace generation fails if the data provided is invalid.
*/
// opts.traceAccount
// opts.traceProfile
if ((opts.enableTrace && !opts.traceAccount) || (opts.enableTrace && !opts.traceProfile)) {
throw new Error('The parameter \'traceAccount\' and \'traceProfile\' are compulsory when Trace is enabled!');
}
/**
* HELPERS
*/
// remove duplicates
opts.helpers = [...new Set(opts.helpers)];
// remove inexistent files
opts.helpers = opts.helpers.filter(file => fse.existsSync('{0}/{1}'.format(rootRequire.rootPath, file)));
// copy helpers to temp folder (not sure why, maybe remove later if not needed)
opts.helpers.forEach(helper => fse.copySync(helper, '{0}/tmp/tests/helpers/{1}'.format(rootRequire.rootPath, path.basename(helper))));
};
}
module.exports = RunnerOptionsValidator;