platform-helpers/runner-tests-list-builder.js

'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;