diff --git a/lib/modules/file/clean.js b/lib/modules/file/clean.js index f1083fd4..343de595 100644 --- a/lib/modules/file/clean.js +++ b/lib/modules/file/clean.js @@ -59,7 +59,7 @@ var _clean = function( config, options, next ) { // attempt to delete a folder that has a deletable folder inside of it var sortedDirectories = _.sortBy( directories, "length" ).reverse(); for ( var i = 0; i < sortedDirectories.length; i++ ) { - var dirPath = path.join( config.watch.compiledDir, sortedDirectories[i]); + var dirPath = path.join( config.watch.compiledDir, sortedDirectories[i] ); fs.exists( dirPath, _removeDirectoryIfExists( config, dirPath, done ) ); } }; diff --git a/src/modules/file/beforeRead.coffee b/src/modules/file/beforeRead.coffee index 624cfbbd..c8f93ca2 100644 --- a/src/modules/file/beforeRead.coffee +++ b/src/modules/file/beforeRead.coffee @@ -8,6 +8,9 @@ _notValidExtension = (file) -> ext = path.extname(file.inputFileName).replace(/\./,'') allExtensions.indexOf(ext) is -1 +# goal is to process files as they come in +# and determine if the file needs to be processed +# and if not, remove it from files array _fileNeedsCompiling = (config, options, next) -> hasFiles = options.files?.length > 0 return next() unless hasFiles @@ -20,7 +23,7 @@ _fileNeedsCompiling = (config, options, next) -> next() options.files.forEach (file) -> - # if using require verification, forcing compile to assemble require information + # if module has asked for recompile to rebuild cached assets # or if extension is for file that was placed here, not that originated the workflow # like with .css files and CSS proprocessors if (options.isJavascript and config.__forceJavaScriptRecompile) or _notValidExtension(file) @@ -37,8 +40,8 @@ _fileNeedsCompiling = (config, options, next) -> done() _fileNeedsCompilingStartup = (config, options, next) -> - # force compiling on startup to build require dependency tree - # but not for vendor javascript + # modules have the ability to force recompile on startup + # often because they have cached data that isn't up to date if config.__forceJavaScriptRecompile and options.isJSNotVendor if config.log.isDebug() config.log.debug "File [[ #{options.inputFile} ]] NEEDS compiling/copying" diff --git a/src/modules/file/clean.js b/src/modules/file/clean.js index f1083fd4..343de595 100644 --- a/src/modules/file/clean.js +++ b/src/modules/file/clean.js @@ -59,7 +59,7 @@ var _clean = function( config, options, next ) { // attempt to delete a folder that has a deletable folder inside of it var sortedDirectories = _.sortBy( directories, "length" ).reverse(); for ( var i = 0; i < sortedDirectories.length; i++ ) { - var dirPath = path.join( config.watch.compiledDir, sortedDirectories[i]); + var dirPath = path.join( config.watch.compiledDir, sortedDirectories[i] ); fs.exists( dirPath, _removeDirectoryIfExists( config, dirPath, done ) ); } }; diff --git a/test/unit-test.js b/test/unit-test.js index ee2024c1..bf27ba91 100644 --- a/test/unit-test.js +++ b/test/unit-test.js @@ -2,4 +2,5 @@ require("./units/modules/file/write-test"); require("./units/modules/file/read-test"); require("./units/modules/file/init-test"); require("./units/modules/file/delete-test"); -require("./units/modules/file/clean-test"); \ No newline at end of file +require("./units/modules/file/clean-test"); +require("./units/modules/file/beforeRead-test"); \ No newline at end of file diff --git a/test/units/modules/file/beforeRead-test.js b/test/units/modules/file/beforeRead-test.js new file mode 100644 index 00000000..61214d73 --- /dev/null +++ b/test/units/modules/file/beforeRead-test.js @@ -0,0 +1,127 @@ +var path = require( "path" ) + , sinon = require( "sinon" ) + , utils = require( path.join(process.cwd(), "test", "utils") ) + , beforeReadModule = require( path.join(process.cwd(), "lib", "modules", "file", "beforeRead") ) + , fileUtils = require( path.join(process.cwd(), "lib", "util", "file" ) ) + , fakeMimosaConfig = utils.fakeMimosaConfig(); + ; + +describe( "Mimosa beforeRead workflow module", function(){ + var startupFunction + , postStartupFunction + , spy + ; + + before(function(done) { + var i = 0; + utils.testRegistration( beforeReadModule, function( func ) { + if (i++) { + postStartupFunction = func; + done(); + } else { + startupFunction = func; + } + }); + + spy = sinon.spy(); + + }); + + afterEach(function() { + spy.reset(); + }); + + describe( "when invoked during startup", function() { + + it( "will invoke the lifecycle callback immediately when forced", function(){ + var postStartupFuncSpy = sinon.spy(postStartupFunction); + fakeMimosaConfig.__forceJavaScriptRecompile = true; + var opts = { + isJSNotVendor:true, + files:[] + }; + startupFunction( fakeMimosaConfig, opts, spy ); + expect( spy.calledOnce ).to.be.true; + expect( postStartupFuncSpy.callCount ).to.eql(0); + postStartupFuncSpy.reset(); + delete fakeMimosaConfig.__forceJavaScriptRecompile; + }); + + it( "will not invoke the lifecycle callback immediately if forced and vendor file", function(){ + fakeMimosaConfig.__forceJavaScriptRecompile = true; + var opts = { + isJSNotVendor:false, + files:["foo"] + }; + var forEachSpy = sinon.spy(opts.files, "forEach", function(){}); + startupFunction( fakeMimosaConfig, opts, spy ); + expect( spy.calledOnce ).to.be.true; + expect( forEachSpy.calledOnce ).to.be.true; + forEachSpy.reset(); + delete fakeMimosaConfig.__forceJavaScriptRecompile; + }); + + }); + + describe( "when invoked after startup", function() { + + it("with no files the lifecycle callback will be immediately executed", function(){ + postStartupFunction( fakeMimosaConfig, {files:[]}, spy ); + expect( spy.calledOnce ).to.be.true; + }); + + it("with many files with invalid extension will let file through untouched", function() { + var options = { + files:["foo.css", "bar.bar"] + }; + postStartupFunction( fakeMimosaConfig, options, spy ); + expect( spy.calledOnce ).to.be.true; + expect(options.files[0]).to.eql("foo.css"); + expect(options.files[1]).to.eql("bar.bar"); + }); + + it("with many javascript files and recompile forced, will let files through untouched", function() { + var options = { + files:["foo.js", "bar.js"], + isJavascript: true + }; + fakeMimosaConfig.__forceJavaScriptRecompile = true; + postStartupFunction( fakeMimosaConfig, options, spy ); + expect( spy.calledOnce ).to.be.true; + expect(options.files[0]).to.eql("foo.js"); + expect(options.files[1]).to.eql("bar.js"); + delete fakeMimosaConfig.__forceJavaScriptRecompile; + }); + + + it("with will remove files that do not need compilation", function() { + var options = { + files:[{ + inputFileName:"foo.js", + outputFileName:"notnull" + },{ + inputFileName:"bar.js", + outputFileName:"notnull" + },{ + inputFileName:"baz.js", + outputFileName:"notnull" + }] + }; + + sinon.stub(fileUtils, "isFirstFileNewer", function(inputName, outputName, cb){ + if (inputName === "foo.js") { + cb(false); + } else { + cb(true); + } + }); + + postStartupFunction( fakeMimosaConfig, options, spy ); + expect( spy.calledOnce ).to.be.true; + expect(options.files.length).to.eql(2); + expect(options.files[0].inputFileName).to.eql("bar.js"); + expect(options.files[1].inputFileName).to.eql("baz.js"); + fileUtils.isFirstFileNewer.restore(); + }); + }); +}); \ No newline at end of file diff --git a/test/utils.js b/test/utils.js index 1f651478..86e3eb5e 100644 --- a/test/utils.js +++ b/test/utils.js @@ -16,7 +16,8 @@ var crypto = require( "crypto" ) log: { success: function(msg, opts){}, warn: function(msg, opts){}, - error: function(msg, opts){} + error: function(msg, opts){}, + isDebug: function(){return false;} }, vendor: { javascripts: "javascripts/vendor",