diff --git a/lib/app/private/controller/load-modules.js b/lib/app/private/controller/load-modules.js index 49613656d..22fc3987c 100644 --- a/lib/app/private/controller/load-modules.js +++ b/lib/app/private/controller/load-modules.js @@ -56,7 +56,10 @@ module.exports = function (cb) { var actionIdentity = (identity + path.sep + actionName).toLowerCase().replace((new RegExp(path.sep,'g')), '.'); // If the action identity matches one we've already loaded from disk, bail. if (actionsLoadedFromDisk[actionIdentity]) { - throw new Error('The action `' + actionName + '` in `' + filePath + '` conflicts with a previously-loaded action.'); + var conflictError = new Error('The action `' + actionName + '` in `' + filePath + '` conflicts with a previously-loaded action.'); + conflictError.code = 'E_CONFLICT'; + conflictError.identity = actionIdentity; + throw conflictError; } // Attempt to load the action into our set of actions. // This may throw an error, which will be caught below. @@ -75,7 +78,10 @@ module.exports = function (cb) { // e.g. somefolder.dostuff var actionIdentity = match[1].toLowerCase().replace((new RegExp(path.sep,'g')), '.'); if (actionsLoadedFromDisk[actionIdentity]) { - throw new Error('The action `' + _.last(actionIdentity.split('.')) + '` in `' + filePath + '` conflicts with a previously-loaded action.'); + var conflictError = new Error('The action `' + _.last(actionIdentity.split('.')) + '` in `' + filePath + '` conflicts with a previously-loaded action.'); + conflictError.code = 'E_CONFLICT'; + conflictError.identity = actionIdentity; + throw conflictError; } // Attempt to load the action into our set of actions. // This may throw an error, which will be caught below. diff --git a/test/integration/controllers.test.js b/test/integration/controllers.test.js index 1400c86ea..c3fff64a2 100644 --- a/test/integration/controllers.test.js +++ b/test/integration/controllers.test.js @@ -139,9 +139,10 @@ describe('controllers :: ', function() { }); }); - after(function() { + after(function(done) { sailsApp.lower(function() { process.chdir(curDir); + return done(); }); }); @@ -266,4 +267,55 @@ describe('controllers :: ', function() { }); + describe.only('with conflicting actions in api/controllers', function() { + + var curDir, tmpDir, sailsApp; + var warn; + var warnings = []; + + before(function(done) { + // Cache the current working directory. + curDir = process.cwd(); + // Create a temp directory. + tmpDir = tmp.dirSync({gracefulCleanup: true, unsafeCleanup: true}); + // Switch to the temp directory. + process.chdir(tmpDir.name); + // Create a top-level legacy controller file. + Filesystem.writeSync({ + force: true, + destination: 'api/controllers/TopLevelController.js', + string: 'module.exports = { fnAction: function (req, res) { res.send(\'fn controller action!\'); } };' + }).execSync(); + // Create a top-level action file with a req/res function. + Filesystem.writeSync({ + force: true, + destination: 'api/controllers/toplevel/fnaction.js', + string: 'module.exports = function (req, res) { res.send(\'standalone fn!\'); };' + }).execSync(); + + return done(); + + }); + + after(function() { + process.chdir(curDir); + }); + + it('should fail to load sails', function(done) { + // Load the Sails app. + appHelper.load({hooks: {views: false, grunt: false}, log: {level: 'error'}}, function(err, _sails) { + if (!err) { + _sails.lower(function() { + return done(new Error('Should have thrown an error!')); + }); + } + assert.equal(err.code, 'E_CONFLICT'); + assert.equal(err.identity, 'toplevel.fnaction'); + return done(); + }); + + }); + + }); + });