Skip to content
38 changes: 37 additions & 1 deletion lib/mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ Mocha.prototype.ui = function(name) {
*
* @private
* @see {@link Mocha#addFile}
* @see {@link Mocha#run}
* @see {@link Mocha#unloadFiles}
* @param {Function} [fn] - Callback invoked upon completion.
*/
Mocha.prototype.loadFiles = function(fn) {
Expand All @@ -290,6 +292,39 @@ Mocha.prototype.loadFiles = function(fn) {
fn && fn();
};

/**
* Removes a previously loaded file from Node's `require` cache.
*
* @private
* @see {@link Mocha#unloadFiles}
* @param {string} file - Pathname of file to be unloaded.
*/
Mocha.prototype.unloadFile = function(file) {
delete require.cache[require.resolve(file)];
};

/**
* @summary
* Unloads `files` from Node's `require` cache.
*
* @description
* This allows files to be "freshly" reloaded, providing the ability
* to reuse a Mocha instance programmatically.
*
* <strong>Not needed for (or used by) CLI.</strong>
*
* @public
* @see {@link Mocha#unloadFile}
* @see {@link Mocha#loadFiles}
* @see {@link Mocha#run}
* @returns {Mocha} this
* @chainable
*/
Mocha.prototype.unloadFiles = function() {
this.files.forEach(this.unloadFile, this);
return this;
};

/**
* Implements desktop notifications using a pseudo-reporter.
*
Expand Down Expand Up @@ -686,7 +721,7 @@ Mocha.prototype.forbidPending = function() {

/**
* @summary
* Runs tests and invokes `fn()` when complete.
* Runs the root suite and invokes `fn()` when complete.
*
* @description
* To run tests multiple times (or to run tests in files that are
Expand All @@ -695,6 +730,7 @@ Mocha.prototype.forbidPending = function() {
*
* @public
* @see {@link Mocha#loadFiles}
* @see {@link Mocha#unloadFiles}
* @see {@link Runner#run}
* @param {DoneCB} [fn] - Callback invoked when test execution completed.
* @return {Runner} runner instance
Expand Down
40 changes: 40 additions & 0 deletions test/node-unit/mocha.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict';

var Mocha = require('../../lib/mocha');
var Path = require('path');

describe('.unloadFile()', function() {
it('should unload a specific file from cache', function() {
var mocha = new Mocha({});
var filePath = __filename;

mocha.addFile(filePath);
mocha.loadFiles();
expect(require.cache, 'to have property', require.resolve(filePath));

mocha.unloadFile(filePath);
expect(require.cache, 'not to have property', require.resolve(filePath));
});
});

describe('.unloadFiles()', function() {
it('should unload all test files from cache', function() {
var mocha = new Mocha({});
var testFiles = [
__filename,
Path.join(__dirname, 'fs.spec.js'),
Path.join(__dirname, 'color.spec.js')
];

testFiles.forEach(mocha.addFile, mocha);
mocha.loadFiles();
testFiles.forEach(function(file) {
expect(require.cache, 'to have property', require.resolve(file));
});

mocha.unloadFiles();
testFiles.forEach(function(file) {
expect(require.cache, 'not to have property', require.resolve(file));
});
});
});