Skip to content

Commit

Permalink
Collect test files later
Browse files Browse the repository at this point in the history
This commit prepares improvements to the watch mode behavior. In the future
we want Mocha in watch mode to pick up new test files. This requires
that the test files are collected inside `watchRun` instead of before.

To accomplish this change we rename `handleFiles` to `collectFiles` and
move it to its own module. Instead of calling `collectFiles` in
`lib/cli/run` and passing the files on to `watchRun` or `singleRun` we
pass down th options threw `runMocha` and call `collectFiles` in both
`watchRun` and `singleRun`.
  • Loading branch information
Thomas Scholtes committed Jun 15, 2019
1 parent c903147 commit 0c63f7b
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 111 deletions.
82 changes: 82 additions & 0 deletions lib/cli/collect-files.js
@@ -0,0 +1,82 @@
'use strict';

const path = require('path');
const ansi = require('ansi-colors');
const debug = require('debug')('mocha:cli:run:helpers');
const minimatch = require('minimatch');
const utils = require('../utils');

/**
* Smash together an array of test files in the correct order
* @param {Object} [opts] - Options
* @param {string[]} [opts.extension] - File extensions to use
* @param {string[]} [opts.spec] - Files, dirs, globs to run
* @param {string[]} [opts.ignore] - Files, dirs, globs to ignore
* @param {boolean} [opts.recursive=false] - Find files recursively
* @param {boolean} [opts.sort=false] - Sort test files
* @returns {string[]} List of files to test
* @private
*/
module.exports = ({
ignore = [],
extension = [],
file = [],
recursive = false,
sort = false,
spec = []
} = {}) => {
let files = [];
const unmatched = [];
spec.forEach(arg => {
let newFiles;
try {
newFiles = utils.lookupFiles(arg, extension, recursive);
} catch (err) {
if (err.code === 'ERR_MOCHA_NO_FILES_MATCH_PATTERN') {
unmatched.push({message: err.message, pattern: err.pattern});
return;
}

throw err;
}

if (typeof newFiles !== 'undefined') {
if (typeof newFiles === 'string') {
newFiles = [newFiles];
}
newFiles = newFiles.filter(fileName =>
ignore.every(pattern => !minimatch(fileName, pattern))
);
}

files = files.concat(newFiles);
});

if (!files.length) {
// give full message details when only 1 file is missing
const noneFoundMsg =
unmatched.length === 1
? `Error: No test files found: ${JSON.stringify(unmatched[0].pattern)}` // stringify to print escaped characters raw
: 'Error: No test files found';
console.error(ansi.red(noneFoundMsg));
process.exit(1);
} else {
// print messages as an warning
unmatched.forEach(warning => {
console.warn(ansi.yellow(`Warning: ${warning.message}`));
});
}

const fileArgs = file.map(filepath => path.resolve(filepath));
files = files.map(filepath => path.resolve(filepath));

// ensure we don't sort the stuff from fileArgs; order is important!
if (sort) {
files.sort();
}

// add files given through --file to be ran first
files = fileArgs.concat(files);
debug('files (in order): ', files);
return files;
};
118 changes: 21 additions & 97 deletions lib/cli/run-helpers.js
Expand Up @@ -9,11 +9,9 @@

const fs = require('fs');
const path = require('path');
const ansi = require('ansi-colors');
const debug = require('debug')('mocha:cli:run:helpers');
const minimatch = require('minimatch');
const utils = require('../utils');
const watchRun = require('./watch-run');
const collectFiles = require('./collect-files');

const cwd = (exports.cwd = process.cwd());

Expand Down Expand Up @@ -93,116 +91,42 @@ exports.handleRequires = (requires = []) => {
});
};

/**
* Smash together an array of test files in the correct order
* @param {Object} [opts] - Options
* @param {string[]} [opts.extension] - File extensions to use
* @param {string[]} [opts.spec] - Files, dirs, globs to run
* @param {string[]} [opts.ignore] - Files, dirs, globs to ignore
* @param {boolean} [opts.recursive=false] - Find files recursively
* @param {boolean} [opts.sort=false] - Sort test files
* @returns {string[]} List of files to test
* @private
*/
exports.handleFiles = ({
ignore = [],
extension = [],
file = [],
recursive = false,
sort = false,
spec = []
} = {}) => {
let files = [];
const unmatched = [];
spec.forEach(arg => {
let newFiles;
try {
newFiles = utils.lookupFiles(arg, extension, recursive);
} catch (err) {
if (err.code === 'ERR_MOCHA_NO_FILES_MATCH_PATTERN') {
unmatched.push({message: err.message, pattern: err.pattern});
return;
}

throw err;
}

if (typeof newFiles !== 'undefined') {
if (typeof newFiles === 'string') {
newFiles = [newFiles];
}
newFiles = newFiles.filter(fileName =>
ignore.every(pattern => !minimatch(fileName, pattern))
);
}

files = files.concat(newFiles);
});

if (!files.length) {
// give full message details when only 1 file is missing
const noneFoundMsg =
unmatched.length === 1
? `Error: No test files found: ${JSON.stringify(unmatched[0].pattern)}` // stringify to print escaped characters raw
: 'Error: No test files found';
console.error(ansi.red(noneFoundMsg));
process.exit(1);
} else {
// print messages as an warning
unmatched.forEach(warning => {
console.warn(ansi.yellow(`Warning: ${warning.message}`));
});
}

const fileArgs = file.map(filepath => path.resolve(filepath));
files = files.map(filepath => path.resolve(filepath));

// ensure we don't sort the stuff from fileArgs; order is important!
if (sort) {
files.sort();
}

// add files given through --file to be ran first
files = fileArgs.concat(files);
debug('files (in order): ', files);
return files;
};

/**
* Give Mocha files and tell it to run
* @param {Mocha} mocha - Mocha instance
* @param {Options} [opts] - Options
* @param {string[]} [opts.files] - List of test files
* @param {Options} [opts] - Command line options
* @param {boolean} [opts.exit] - Whether or not to force-exit after tests are complete
* @returns {Runner}
* @private
*/
exports.singleRun = (mocha, {files = [], exit = false} = {}) => {
exports.singleRun = (mocha, options) => {
const files = collectFiles(options);
debug('running tests with files', files);
mocha.files = files;
return mocha.run(exit ? exitMocha : exitMochaLater);
return mocha.run(options.exit ? exitMocha : exitMochaLater);
};

/**
* Actually run tests
* @param {Mocha} mocha - Mocha instance
* @param {Object} [opts] - Options
* @param {boolean} [opts.watch=false] - Enable watch mode
* @param {string[]} [opts.extension] - List of extensions to watch
* @param {string|RegExp} [opts.grep] - Grep for test titles
* @param {string} [opts.ui=bdd] - User interface
* @param {boolean} [opts.exit=false] - Force-exit Mocha when tests done
* @param {string[]} [files] - Array of test files
* @param {Object} opts - Command line options
* @private
*/
exports.runMocha = (
mocha,
{watch = false, extension = [], grep = '', ui = 'bdd', exit = false} = {},
files = []
) => {
if (watch) {
watchRun(mocha, {extension, grep, ui, files});
exports.runMocha = (mocha, options) => {
options = Object.assign(
{
watch: false,
extension: [],
grep: '',
ui: 'bdd',
exit: false
},
options
);
if (options.watch) {
watchRun(mocha, options);
} else {
exports.singleRun(mocha, {files, exit});
exports.singleRun(mocha, options);
}
};

Expand Down
6 changes: 1 addition & 5 deletions lib/cli/run.js
Expand Up @@ -16,7 +16,6 @@ const {

const {
list,
handleFiles,
handleRequires,
validatePlugin,
runMocha
Expand Down Expand Up @@ -290,8 +289,5 @@ exports.builder = yargs =>
exports.handler = argv => {
debug('post-yargs config', argv);
const mocha = new Mocha(argv);
const files = handleFiles(argv);

debug('running tests with files', files);
runMocha(mocha, argv, files);
runMocha(mocha, argv);
};
16 changes: 7 additions & 9 deletions lib/cli/watch-run.js
Expand Up @@ -3,6 +3,7 @@
const utils = require('../utils');
const Context = require('../context');
const Mocha = require('../mocha');
const collectFiles = require('./collect-files');

/**
* Exports the `watchRun` function that runs mocha in "watch" mode.
Expand All @@ -14,15 +15,12 @@ const Mocha = require('../mocha');
/**
* Run Mocha in "watch" mode
* @param {Mocha} mocha - Mocha instance
* @param {Object} opts - Options
* @param {string[]} opts.extension - List of extensions to watch
* @param {string|RegExp} opts.grep - Grep for test titles
* @param {string} opts.ui - User interface
* @param {string[]} opts.files - Array of test files
* @param {Object} [opts] - Command line options
* @private
*/
module.exports = (mocha, {extension, grep, ui, files}) => {
module.exports = (mocha, options) => {
let runner;
const files = collectFiles(options);

console.log();
hideCursor();
Expand All @@ -34,7 +32,7 @@ module.exports = (mocha, {extension, grep, ui, files}) => {
process.exit(128 + 2);
});

const watchFiles = utils.files(process.cwd(), extension);
const watchFiles = utils.files(process.cwd(), options.extension);
let runAgain = false;

const loadAndRun = () => {
Expand All @@ -61,12 +59,12 @@ module.exports = (mocha, {extension, grep, ui, files}) => {
const rerun = () => {
purge();
eraseLine();
if (!grep) {
if (!options.grep) {
mocha.grep(null);
}
mocha.suite = mocha.suite.clone();
mocha.suite.ctx = new Context();
mocha.ui(ui);
mocha.ui(options.ui);
loadAndRun();
};

Expand Down

0 comments on commit 0c63f7b

Please sign in to comment.