From 816167edc269183fe4391b80fa9e67a563dedc90 Mon Sep 17 00:00:00 2001
From: Scott Gress <scottmgress@gmail.com>
Date: Thu, 22 Sep 2016 13:46:11 -0500
Subject: [PATCH] Test conflicting on-disk actions

---
 lib/app/private/controller/load-modules.js | 10 +++-
 test/integration/controllers.test.js       | 54 +++++++++++++++++++++-
 2 files changed, 61 insertions(+), 3 deletions(-)

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();
+      });
+
+    });
+
+  });
+
 });