UNPKG

nightwatch

Version:

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

232 lines (180 loc) 6.78 kB
const path = require('path'); const fs = require('fs'); const minimatch = require('minimatch'); const Utils = require('../utils'); const Concurrency = require('./concurrency'); const {Logger, validExtensions, jsFileExt, singleSourceFile} = Utils; const {getTestSourceForRerunFailed} = require('./rerunUtil'); class TestSource { static get GroupNameDelimiter() { return ','; } constructor(settings, argv = {}) { this.argv = argv; this.settings = settings; this.src_folders = settings.src_folders || []; } getTestSourceForSingle(targetPath) { let testsource; if (Array.isArray(targetPath)) { targetPath = targetPath[0]; } if (targetPath && path.resolve(targetPath) === targetPath) { testsource = targetPath; } else { testsource = path.join(process.cwd(), targetPath); } const fileExt = path.parse(testsource).ext; if (!validExtensions.includes(fileExt)) { const fileExists = fs.existsSync(testsource); if (fileExists) { const err = new Error(`Cannot load file ${testsource}`); err.detailedErr = `Files with ${fileExt} extension are not supported by Nightwatch.`; err.showTrace = false; throw err; } testsource += jsFileExt; } return testsource; } getRerunFailedFile(minimal_report_file_path) { const jsonFile = path.resolve(process.env.NIGHTWATCH_RERUN_REPORT_FILE || minimal_report_file_path || ''); if (!Utils.fileExistsSync(jsonFile)) { const err = new Error('Unable to find the Json reporter file to rerun failed tests'); err.showTrace = false; err.detailedErr = 'Configure the environment variable NIGHTWATCH_RERUN_REPORT_FILE with Json reporter file path'; err.help = [ `Try setting ${Logger.colors.cyan('minimal_report_file_path: "JSON-REPORTER-PATH"')} in nightwatch configuration`, `Or, try running: ${Logger.colors.cyan('export NIGHTWATCH_RERUN_REPORT_FILE="JSON-REPORTER-PATH"')}` ]; throw err; } return jsonFile; } getTestSourceForRerunFailed() { const {reporter_options: {minimal_report_file_path}} = this.settings; const minimalJsonFile = this.getRerunFailedFile(minimal_report_file_path); try { const {modules = {}} = require(minimalJsonFile); const testsource = []; Object.keys(modules).forEach(moduleKey => { if (modules[moduleKey] && modules[moduleKey].status === 'fail') { testsource.push(modules[moduleKey].modulePath); } }); if (testsource.length === 0) { const err = new Error('Rerun Failed Tests: No failed tests found to rerun.'); err.noFailedTestFound = true; err.showTrace = false; err.detailedErr = 'Run nightwatch with --help to display usage info.'; throw err; } return testsource; } catch (err) { if (err.noFailedTestFound) { err.message = 'Rerun Failed Tests: Invalid Json reporter.'; err.showTrace = false; err.detailedErr = 'Please set env variable NIGHTWATCH_RERUN_REPORT_FILE with valid Json reporter path.'; } throw err; } } /** * Returns the path where the tests are located * @returns {*} */ getSource() { const {test_runner} = this.settings; if ((process.env.NIGHTWATCH_RERUN_FAILED === 'true' || this.argv['rerun-failed']) && Concurrency.isMasterProcess() && test_runner?.type !== 'cucumber') { return getTestSourceForRerunFailed(this.settings); } if (this.src_folders.length === 0 && test_runner?.src_folders && test_runner?.type === 'cucumber') { this.src_folders = test_runner?.src_folders; } if (this.argv['test-worker'] || singleSourceFile(this.argv)) { return this.getTestSourceForSingle(this.argv.test || this.argv._source); } if (this.argv.testcase) { this.argv.testcase = null; Logger.warn('Option --testcase used without --test is ignored.'); } if (Array.isArray(this.argv._source) && (this.argv._source.length > 0)) { return this.argv._source; } if (this.argv.group) { // add support for multiple groups if (Utils.isString(this.argv.group)) { this.argv.group = this.argv.group.split(TestSource.GroupNameDelimiter); } const groupTestsource = this.findGroupPathMultiple(this.argv.group); // If a group does not exist in the multiple src folder case, it is removed // from the test path list. if (this.src_folders.length === 1) { return groupTestsource; } // only when all groups fail to match will there be a run error const testsource = groupTestsource.filter(Utils.dirExistsSync); if (!this.settings.silent) { const ignoredSource = groupTestsource.filter(entry => testsource.indexOf(entry) === -1); if (ignoredSource.length) { Logger.warn('The following group paths were not found and will be excluded from the run:\n - ' + ignoredSource.join('\n - ')); } } return testsource; } this.applySrcFilters(); return this.src_folders; } /** * Apply "exclude" patterns on src_folders, in case more than one was specified */ applySrcFilters() { if (this.src_folders.length < 2) { return this; } if (this.settings.exclude) { const arrExclude = Array.isArray(this.settings.exclude) ? this.settings.exclude : [this.settings.exclude]; const resolvedExclude = arrExclude.map(item => path.resolve(item)); this.src_folders = this.src_folders.filter(item => { const resolvedPath = path.resolve(item); let match = true; resolvedExclude.forEach(function(pattern) { match = !resolvedPath.includes(pattern) && !minimatch(resolvedPath, pattern); }); return match; }); } } /** * Gets test paths from each of the src folders for a single group. * * @param {string} groupName * @return {Array} */ findGroupPath(groupName) { const fullGroupPath = path.resolve(groupName); // for each src folder, append the group to the path // to resolve the full test path return this.src_folders.map(function(srcFolder) { const fullSrcFolder = path.resolve(srcFolder); if (fullGroupPath.indexOf(fullSrcFolder) === 0) { return groupName; } return path.join(srcFolder, groupName); }); } /** * Gets test paths for tests from any number of groups. * * @param {Array} groups */ findGroupPathMultiple(groups) { let paths = []; groups.forEach(groupName => { paths = paths.concat(this.findGroupPath(groupName)); }); return paths; } } module.exports = TestSource;