'use strict'; const chai = require('chai'); const sinon = require('sinon'); const yaml = require('js-yaml'); const fse = require('fs-extra'); const proxyquire = require('proxyquire'); const fixturesEngine = require('../../fixtures/programmatic'); const resolveConfigurationPath = require('../../../lib/cli/resolve-configuration-path'); const { expect } = require('chai'); chai.use(require('chai-as-promised')); const npmCommand = 'npm'; describe('test/unit/commands/plugin-install.test.js', async () => { const spawnFake = sinon.fake(); const installPlugin = proxyquire('../../../commands/plugin-install', { 'child-process-ext/spawn': spawnFake, }); const pluginName = 'serverless-plugin-1'; afterEach(() => { spawnFake.resetHistory(); }); describe('without plugins in configuration', () => { let serviceDir; let configurationFilePath; before(async () => { const fixture = await fixturesEngine.setup('function'); const configuration = fixture.serviceConfig; serviceDir = fixture.servicePath; configurationFilePath = await resolveConfigurationPath({ cwd: serviceDir, }); const configurationFilename = configurationFilePath.slice(serviceDir.length + 1); const options = { name: pluginName, }; await installPlugin({ configuration, serviceDir, configurationFilename, options, }); }); it('should install plugin', () => { const firstCall = spawnFake.firstCall; const command = [firstCall.args[0], ...firstCall.args[1]].join(' '); const expectedCommand = `${npmCommand} install --save-dev ${pluginName}`; expect(command).to.have.string(expectedCommand); }); it('should add plugin to serverless file', async () => { const serverlessFileObj = yaml.load(await fse.readFile(configurationFilePath, 'utf8'), { filename: configurationFilePath, }); expect(serverlessFileObj.plugins).to.include(pluginName); }); }); describe('with plugins in configuration', () => { it('should not add plugin to serverless file if it is already present in configuration but configured behind a variable', async () => { const fixture = await fixturesEngine.setup('function', { configExt: { plugins: ['${self:custom.pluginName}'], custom: { pluginName, }, }, }); const configuration = fixture.serviceConfig; // Simulate that the variable has been resolved configuration.plugins = [pluginName]; const serviceDir = fixture.servicePath; const configurationFilePath = await resolveConfigurationPath({ cwd: serviceDir, }); const configurationFilename = configurationFilePath.slice(serviceDir.length + 1); const options = { name: pluginName, }; await installPlugin({ configuration, serviceDir, configurationFilename, options, }); const serverlessFileObj = yaml.load(await fse.readFile(configurationFilePath, 'utf8'), { filename: configurationFilePath, }); expect(serverlessFileObj.plugins).not.to.include(pluginName); }); }); });