From 532d89c1f69ca30da6edefb0da174bfc3dfde9dc Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 30 Mar 2017 09:57:02 +0200 Subject: [PATCH] Update tests to be side-effect free Use proxyquire and stubbing to make the tests side-effect free. This way the tests will succeed even when someone who runs the tests has the serverless-alpha plugin installed globally. --- lib/classes/PluginManager.js | 14 +++---- lib/classes/PluginManager.test.js | 61 ++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/lib/classes/PluginManager.js b/lib/classes/PluginManager.js index e6b2c8949..252cb935c 100644 --- a/lib/classes/PluginManager.js +++ b/lib/classes/PluginManager.js @@ -31,20 +31,16 @@ class PluginManager { } try { - const prefixPath = childProcess.execSync('npm config get prefix --silent').toString().trim(); + let prefixPath = childProcess.execSync('npm config get prefix --silent').toString().trim(); if (prefixPath && prefixPath.length) { - // get the path to the global node_modules dir - // see: https://docs.npmjs.com/files/folders - let globalNodeModulesPath; - if (os.platform === 'win32') { - globalNodeModulesPath = prefixPath; - } else { - globalNodeModulesPath = path.join(prefixPath, 'lib'); + // get the path to the global node_modules dir (see: https://docs.npmjs.com/files/folders) + if (os.platform !== 'win32') { + prefixPath = path.join(prefixPath, 'lib'); } const serverlessAlphaPluginPath = resolveFrom( - globalNodeModulesPath, + prefixPath, 'serverless-alpha' ); diff --git a/lib/classes/PluginManager.test.js b/lib/classes/PluginManager.test.js index bc07c8f53..16e31ee95 100644 --- a/lib/classes/PluginManager.test.js +++ b/lib/classes/PluginManager.test.js @@ -14,6 +14,7 @@ const mockRequire = require('mock-require'); const testUtils = require('../../tests/utils'); const os = require('os'); const sinon = require('sinon'); +const proxyquire = require('proxyquire'); describe('PluginManager', () => { let pluginManager; @@ -327,19 +328,25 @@ describe('PluginManager', () => { beforeEach(() => { tmpDirPath = testUtils.getTmpDirPath(); fse.mkdirsSync(tmpDirPath); - serverless.config.servicePath = tmpDirPath; - }); - - afterEach(() => { serverless.config.servicePath = false; }); describe('when serverless-alpha is installed locally', () => { beforeEach(() => { + serverless.config.servicePath = tmpDirPath; const pluginPath = path.join(tmpDirPath, 'node_modules', 'serverless-alpha'); class ServerlessAlpha {} testUtils.installPlugin(pluginPath, ServerlessAlpha); + + const resolveFromStub = sinon.stub() + .withArgs(serverless.config.servicePath, 'serverless-alpha') + .returns(pluginPath); + const ModifiedPluginManager = proxyquire('./PluginManager.js', { + 'resolve-from': resolveFromStub, + }); + + pluginManager = new ModifiedPluginManager(serverless); }); it('should auto-load the plugin', () => { @@ -352,7 +359,6 @@ describe('PluginManager', () => { describe('when running on a UNIX machine', () => { let npmStub; - let prefixPath; let globalNodeModulesPath; beforeEach(() => { @@ -360,9 +366,24 @@ describe('PluginManager', () => { .withArgs('npm config get prefix --silent') .returns(tmpDirPath); - prefixPath = tmpDirPath; - globalNodeModulesPath = path.join(prefixPath, 'lib', 'node_modules'); - fse.mkdirsSync(path.join(prefixPath, 'lib', 'node_modules')); + const prefixPath = path.join(tmpDirPath, 'lib'); + globalNodeModulesPath = path.join(prefixPath, 'node_modules'); + fse.mkdirsSync(globalNodeModulesPath); + + // add a mock for the serverless-alpha plugin in the tmpDir + class ServerlessAlpha {} + const globalAlphaPluginPath = path.join(globalNodeModulesPath, 'serverless-alpha'); + fse.mkdirsSync(globalAlphaPluginPath); + testUtils.installPlugin(globalAlphaPluginPath, ServerlessAlpha); + + const resolveFromStub = sinon.stub(); + resolveFromStub.withArgs(serverless.config.servicePath, 'serverless-alpha').returns(false); + resolveFromStub.withArgs(prefixPath, 'serverless-alpha').returns(globalAlphaPluginPath); + const ModifiedPluginManager = proxyquire('./PluginManager.js', { + 'resolve-from': resolveFromStub, + }); + + pluginManager = new ModifiedPluginManager(serverless); }); afterEach(() => { @@ -370,13 +391,6 @@ describe('PluginManager', () => { }); it('should auto load the plugin if globally installed via npm', () => { - // add a mock for the serverless-alpha plugin in the tmpDir - class ServerlessAlpha {} - const globalAlphaPluginPath = path.join(globalNodeModulesPath, 'serverless-alpha'); - - fse.mkdirsSync(globalAlphaPluginPath); - testUtils.installPlugin(globalAlphaPluginPath, ServerlessAlpha); - pluginManager.autoloadServerlessAlphaPlugin(); expect(npmStub.calledWithExactly('npm config get prefix --silent')).to.equal(true); @@ -385,10 +399,21 @@ describe('PluginManager', () => { }); }); - it('should not load the serverless-alpha plugin if not installed', () => { - pluginManager.autoloadServerlessAlphaPlugin(); + describe('when serverless-alpha is not installed at all', () => { + beforeEach(() => { + const resolveFromStub = sinon.stub().returns(false); + const ModifiedPluginManager = proxyquire('./PluginManager.js', { + 'resolve-from': resolveFromStub, + }); - expect(pluginManager.plugins.length).to.equal(0); + pluginManager = new ModifiedPluginManager(serverless); + }); + + it('should not load the serverless-alpha plugin if not installed', () => { + pluginManager.autoloadServerlessAlphaPlugin(); + + expect(pluginManager.plugins.length).to.equal(0); + }); }); });