Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions lib/cli/collect-files.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const { castArray } = require("../utils.cjs");
* @private
*/
module.exports = ({
allowEmpty,
ignore,
extension,
file: fileArgs,
Expand Down Expand Up @@ -94,11 +95,17 @@ module.exports = ({
// give full message details when only 1 file is missing
const noneFoundMsg =
unmatchedSpecFiles.length === 1
? `Error: No test files found: ${JSON.stringify(
? `No test files found: ${JSON.stringify(
unmatchedSpecFiles[0].pattern,
)}` // stringify to print escaped characters raw
: "Error: No test files found";
console.error(pc.red(noneFoundMsg));
: "No test files found";

if (allowEmpty) {
console.warn(pc.yellow(`Warning: ${noneFoundMsg}`));
return { files: [], unmatchedFiles: [] };
}

console.error(pc.red(`Error: ${noneFoundMsg}`));
process.exit(1);
} else {
// print messages as a warning
Expand Down
1 change: 1 addition & 0 deletions lib/cli/run-helpers.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ exports.runMocha = async (mocha, options) => {
} = options;

const fileCollectParams = {
allowEmpty: watch,
ignore,
extension,
file,
Expand Down
12 changes: 11 additions & 1 deletion lib/nodejs/file-unloader.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,18 @@ const require = createRequire(import.meta.url);

/**
* Deletes a file from the `require` cache.
* A file that no longer exists on disk has nothing left to unload.
* @param {string} file - File
*/
export function unloadFile(file) {
delete require.cache[require.resolve(file)];
let resolved;
try {
resolved = require.resolve(file);
} catch (err) {
if (err.code === "MODULE_NOT_FOUND") {
return;
}
throw err;
}
delete require.cache[resolved];
}
2 changes: 2 additions & 0 deletions lib/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ export type PluginFinalizer = (
* An object to configure how Mocha gathers test files
*/
export interface FileCollectionOptions {
/** Return an empty list instead of exiting when no test files are found */
allowEmpty?: boolean;
/** File extensions to use */
extension?: string[];
/** Files, dirs, globs to run */
Expand Down
40 changes: 40 additions & 0 deletions test/integration/options/watch.spec.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,26 @@ describe("--watch", function () {
});
});

it("keeps watching when the last test file is removed", function () {
const testFile = path.join(tempDir, "test/a.js");
copyFixture(DEFAULT_FIXTURE, testFile);

return runMochaWatchJSONAsync(
["test/**/*.js", "--watch-files", "test/**/*.js"],
{ cwd: tempDir, expectedRuns: 3 },
async (_mochaProcess, { waitForRuns }) => {
fs.rmSync(testFile, { force: true });
await waitForRuns(2);
copyFixture("passing.fixture.cjs", path.join(tempDir, "test/b.js"));
},
).then((results) => {
expect(results, "to have length", 3);
expect(results[0].passes, "to have length", 1);
expect(results[1].passes, "to have length", 0);
expect(results[2].passes, "to have length", 2);
});
});

describe("when in parallel mode", function () {
it("reruns test when watched test file is touched", function () {
const testFile = path.join(tempDir, "test.js");
Expand All @@ -78,6 +98,26 @@ describe("--watch", function () {
expect(results, "to have length", 2);
});
});

it("keeps watching when the last test file is removed", function () {
const testFile = path.join(tempDir, "test/a.js");
copyFixture(DEFAULT_FIXTURE, testFile);

return runMochaWatchJSONAsync(
["--parallel", "test/**/*.js", "--watch-files", "test/**/*.js"],
{ cwd: tempDir, expectedRuns: 3 },
async (_mochaProcess, { waitForRuns }) => {
fs.rmSync(testFile, { force: true });
await waitForRuns(2);
copyFixture("passing.fixture.cjs", path.join(tempDir, "test/b.js"));
},
).then((results) => {
expect(results, "to have length", 3);
expect(results[0].passes, "to have length", 1);
expect(results[1].passes, "to have length", 0);
expect(results[2].passes, "to have length", 2);
});
});
});

it("reruns test when file matching --watch-files changes", function () {
Expand Down
Loading