Last Updated: February 25, 2016
·
2.429K
· nevi

Grunt/Watch/Mocha only run on my changed file

Here is a little snippet to reach on of the lazy people dream :D

First we need a grunt watch task.

grunt.initConfig({
 watch: {
 automatic: {
 files: ['src/**/*.js']
 }
});

There is the worker:

MochaTester = {

 mochaOptions: {
 reporter: 'dot'
 },

 Mocha: require('mocha'),
 path: require('path'),
 fs: require('fs'),

 registerToWatchTask: function(target, mochaOptions){
 var tester = Object.create(this);

 tester.target = target;
 tester.mochaOptions = mochaOptions ? 
 mochaOptions : 
 this.mochaOptions;

 grunt.event.on("watch", tester.listener.bind(tester));
 return tester;
 },

 listener: function(action, filepath, target)
 {
 if (!this.isListenedEvent(action, target)) {
 return;
 }

 var testFile = this.getTestFilePath(filepath);

 if (filepath != testFile) {
 this.clearCache(filepath);
 }

 this.clearCache(testFile);
 this.createMochaWithFile(testFile);

 setTimeout(this.run.bind(this), 500);
 },

 isListenedEvent: function(action, target)
 {
 return action == 'changed' && target == this.target;
 },

 // */myFile.js
 // */test/myFileTest.js
 // either my file or his test file changed get the test file
 getTestFilePath: function(filepath)
 {
 var isTestFile = filepath.indexOf('Test.js') != -1,
 testFile = !isTestFile ? 
 filepath.replace(/(.+)\/(\w+)\.js/, '/test/Test.js') : 
 filepath;

 if (!isTestFile && !this.path.existsSync(filepath)) {
 throw new Error('\nTestFile not found:\n'+filepath)
 }

 return testFile;
 },

 // require cache all time, so second time zero test will execute
 // if does not clear from the cache
 clearCache: function(filepath)
 {
 require.cache[require.resolve('./'+filepath)] = undefined;
 },

 createMochaWithFile: function(filepath)
 {
 this.mocha = new this.Mocha(this.mochaOptions);
 this.mocha.addFile(filepath);
 },

 run: function()
 {
 this.mocha.run(function(failureCount){
 if (failureCount) {
 grunt.log.error('falling: ' + failureCount)
 } else {
 grunt.log.ok('OK');
 }
 });
 }
 }

And something familiar: need to register the task:)

MochaTester.registerToWatchTask('automatic');

3 Responses
Add your response

Good work, you saved me after a couple of hours trying to do that!

over 1 year ago ·

Hey you should publish that as a grunt-contrib package.

over 1 year ago ·

I'm glad to help you.

That would be nice, but first I need to figure out how can I do it with an extendable approach.

Like I run this way my phpunit tests too :D

over 1 year ago ·