UNPKG

nightwatch

Version:

Easy to use Node.js based end-to-end testing solution for web applications using the W3C WebDriver API.

264 lines (212 loc) 7.44 kB
const path = require('path'); const Concurrency = require('../concurrency'); const Utils = require('../../utils'); const {Logger} = Utils; const {augmentTestSuite} = require('./mocha/extensions.js'); class MochaRunner { static MochaNightwatch({argv, settings, addtOpts}) { const Mocha = require('mocha'); const CustomRunner = require('./mocha/custom-runner.js'); return class MochaNightwatch extends Mocha { constructor(mochaOpts, nightwatchSettings) { super(mochaOpts); this.nightwatchSettings = nightwatchSettings; this._runnerClass = CustomRunner; const runner = this; this.suite.on('suite', function (suite) { suite.on('suite', function (childSuite) { augmentTestSuite({suite: childSuite, runner, argv, settings, addtOpts}); }); augmentTestSuite({suite, runner, argv, settings, addtOpts}); }); } }; } get supportsConcurrency() { return true; } get combinedReporterList() { return ['mochawesome', 'html']; } get type() { return 'mocha'; } constructor(settings, argv, addtOpts = {}) { this.startTime = new Date().getTime(); this.settings = settings; this.argvOpts = argv; this.publishReport = false; this.argv = argv; this.processListener = addtOpts.processListener; this.mochaOpts = settings.test_runner.options || {}; if (Utils.isUndefined(this.mochaOpts.timeout)) { this.mochaOpts.timeout = settings.globals.asyncHookTimeout; } if (this.settings.disable_colors) { this.mochaOpts.color = false; } if (this.mochaOpts.reporter === 'junit') { this.mochaOpts.reporter = 'mocha-junit-reporter'; } if (argv.reporter.includes('mochawesome')) { this.mochaOpts.reporter = 'mochawesome'; } else if (argv.reporter.includes('mocha-junit-reporter')) { try { require('mocha-junit-reporter'); } catch (err) { const error = new Error('Nightwatch needs the mocha-junit-reporter package for when using Mocha as a test runner.'); error.detailedErr = 'To install it, please run:\n npm install mocha-junit-reporter --save-dev'; error.showTrace = false; error.displayed = false; throw error; } this.mochaOpts.reporter = 'mocha-junit-reporter'; } if (this.mochaOpts.reporter === 'mochawesome') { try { require('mochawesome'); } catch (err) { const error = new Error('Nightwatch needs the mochawesome package for when using Mocha as a test runner.'); error.detailedErr = 'To install it, please run:\n npm install mochawesome --save-dev'; error.showTrace = false; error.displayed = false; throw error; } } if (argv.grep) { this.mochaOpts.grep = argv.grep; } if (argv['fail-fast']) { this.mochaOpts.bail = true; } if (argv.retries) { this.mochaOpts.retries = argv.retries; } if (argv.fgrep) { this.mochaOpts.fgrep = argv.fgrep; } if (argv.invert) { this.mochaOpts.invert = argv.invert; } this.mochaOpts.reporterOptions = this.mochaOpts.reporterOptions || {}; if (argv.reporter.includes('mocha-junit-reporter')) { this.mochaOpts.reporterOptions.mochaFile = path.join(settings.output_folder, 'test-results.xml'); } if (this.isTestWorker()) { const filePath = this.argv.test; const reportFilename = filePath.substring(filePath.lastIndexOf('/') + 1).split('.')[0]; this.mochaOpts.isWorker = true; if (argv.reporter.includes('mocha-junit-reporter')) { this.mochaOpts.reporterOptions.mochaFile = path.join(settings.output_folder, `${reportFilename}.xml`); } else if (argv.reporter.includes('mochawesome')) { this.mochaOpts.reporterOptions = Object.assign(this.mochaOpts.reporterOptions, { html: false, json: true, quiet: true, reportFilename }); } } if (this.mochaOpts.reporter === 'mochawesome' && !this.mochaOpts.reporterOptions.reportDir) { this.mochaOpts.reporterOptions.reportDir = settings.reportDir || 'html-report'; } const MochaNightwatch = MochaRunner.MochaNightwatch({settings, argv, addtOpts}); this.mocha = new MochaNightwatch(this.mochaOpts, settings); } async runConcurrent(testEnvArray, modules) { this.checkReporterDependencies(); this.concurrency = new Concurrency(this.settings, this.argv); const exitCode = await this.concurrency.runMultiple(testEnvArray, modules); await this.generateCombinedReport(); return exitCode; } checkReporterDependencies() { if (!this.argv.reporter.includes('mochawesome')) { return; } try { require('mochawesome-report-generator'); require('mochawesome-merge'); } catch (err) { const error = new Error('Nightwatch needs some more packages when running in parallel and using the mochawesome reporter:'); error.detailedErr = 'To install dependencies, please run:\n npm install mochawesome-report-generator mochawesome-merge --save-dev'; throw error; } } async generateCombinedReport() { if (!this.argv.reporter.includes('mochawesome')) { return; } const {reportDir} = this.mochaOpts.reporterOptions; const marge = require('mochawesome-report-generator'); const {merge} = require('mochawesome-merge'); const files = reportDir ? `${path.join(reportDir, '*.json')}` : './mochawesome-report/*.json'; const report = await merge({ files: [files] }); return marge.create(report, {}); } isTestWorker() { return this.argv['test-worker']; } closeOpenSessions() { const mochaSuite = this.mocha.suite; const client = mochaSuite && mochaSuite.client; if (client && client.sessionId) { const request = client.transport.createHttpRequest({ path: `/session/${client.sessionId}` }); return new Promise(function(resolve, reject) { request.delete() .on('error', function(err) { resolve(); }) .on('success', function() { resolve(); }); }); } return Promise.resolve(); } registerUncaughtErr(err) { } /** * Main entry-point of the runner * * @return {Promise} */ run(modules) { modules.forEach(module => this.mocha.addFile(module)); return new Promise((resolve, reject) => { this.mocha.run(failures => { if ((failures instanceof Error) && failures.sessionCreate) { Logger.error(failures); process.exit(1); } this.closeOpenSessions() .then(_ => { if (this.mocha.suite && this.mocha.suite.client) { return this.mocha.suite.client.transport.sessionFinished(); } }) .catch(err => { console.error(err.stack); }) .then(_ => { if (failures) { let err; if (failures instanceof Error) { err = failures; } else { err = new Error('Mocha reported test failures.'); err.failures = failures; } return reject(err); } resolve(); }); }); }); } } module.exports = MochaRunner;