'use strict' const chai = require('chai') chai.use(require('chai-as-promised')) const { expect } = chai const Serverless = require('../../../lib/serverless') const semverRegex = require('semver-regex') const YamlParser = require('../../../lib/classes/yaml-parser') const PluginManager = require('../../../lib/classes/plugin-manager') const Utils = require('../../../lib/classes/utils') const Service = require('../../../lib/classes/service') const ConfigSchemaHandler = require('../../../lib/classes/config-schema-handler') const CLI = require('../../../lib/classes/cli') const ServerlessError = require('../../../lib/serverless-error') const runServerless = require('../../utils/run-serverless') const spawn = require('child-process-ext/spawn') const programmaticFixturesEngine = require('../../fixtures/programmatic') const path = require('path') const yaml = require('js-yaml') const _ = require('lodash') describe('Serverless', () => { let serverless beforeEach(() => { serverless = new Serverless({ commands: ['print'], options: {}, serviceDir: null, }) }) describe('#constructor()', () => { it('should set an empty providers object', () => { expect(serverless.providers).to.deep.equal({}) }) it('should set the Serverless version', () => { expect(serverless.version.length).to.be.at.least(1) }) it('should set the YamlParser class instance', () => { expect(serverless.yamlParser).to.be.instanceof(YamlParser) }) it('should set the PluginManager class instance', () => { expect(serverless.pluginManager).to.be.instanceof(PluginManager) }) it('should set the Utils class instance', () => { expect(serverless.utils).to.be.instanceof(Utils) }) it('should set the Service class instance', () => { expect(serverless.service).to.be.instanceof(Service) }) it('should set the ConfigSchemaHandler class instance', () => { expect(serverless.configSchemaHandler).to.be.instanceof( ConfigSchemaHandler, ) }) it('should have a config object', () => { expect(serverless.config).to.not.equal(undefined) }) it('should have a classes object', () => { expect(serverless.classes).to.not.equal(undefined) }) it('should store the CLI class inside the classes object', () => { expect(serverless.classes.CLI).to.deep.equal(CLI) }) it('should store the YamlParser class inside the classes object', () => { expect(serverless.classes.YamlParser).to.deep.equal(YamlParser) }) it('should store the PluginManager class inside the classes object', () => { expect(serverless.classes.PluginManager).to.deep.equal(PluginManager) }) it('should store the Utils class inside the classes object', () => { expect(serverless.classes.Utils).to.deep.equal(Utils) }) it('should store the Service class inside the classes object', () => { expect(serverless.classes.Service).to.deep.equal(Service) }) it('should store the ConfigSchemaHandler class inside the classes object', () => { expect(serverless.classes.ConfigSchemaHandler).to.deep.equal( ConfigSchemaHandler, ) }) it('should store the Error class inside the classes object', () => { expect(serverless.classes.Error).to.deep.equal(ServerlessError) }) }) describe('#init()', () => { it('should set an instanceId', async () => serverless.init().then(() => { expect(serverless.instanceId).to.match(/\d/) })) it('should create a new CLI instance', async () => serverless.init().then(() => { expect(serverless.cli).to.be.instanceof(CLI) })) it('should allow a custom CLI instance', async () => { class CustomCLI extends CLI {} serverless.classes.CLI = CustomCLI return serverless.init().then(() => { expect(serverless.cli).to.be.instanceof(CLI) expect(serverless.cli.constructor.name).to.equal('CustomCLI') }) }) // note: we just test that the processedInput variable is set (not the content of it) // the test for the correct input is done in the CLI class test file it('should receive the processed input form the CLI instance', async () => serverless.init().then(() => { expect(serverless.processedInput).to.not.deep.equal({}) })) }) describe('#setProvider()', () => { class ProviderMock {} it('should set the provider object in the provider object', () => { const myProvider = new ProviderMock() serverless.setProvider('myProvider', myProvider) expect(serverless.providers.myProvider).to.equal(myProvider) }) }) describe('#getProvider()', () => { class ProviderMock {} let myProvider beforeEach(() => { myProvider = new ProviderMock() serverless.setProvider('myProvider', myProvider) }) it('should return the provider object', () => { const retrivedProvider = serverless.getProvider('myProvider') expect(retrivedProvider).to.deep.equal(myProvider) }) }) describe('#getVersion()', () => { it('should get the correct Serverless version', () => { expect(semverRegex().test(serverless.getVersion())).to.equal(true) }) }) }) describe('test/unit/lib/serverless.test.js', () => { describe('Legacy API interface', () => { let serverless before(async () => { ;({ serverless } = await runServerless({ fixture: 'aws', command: 'package', })) }) it('Ensure that instance is setup', async () => { expect(serverless.variables).to.have.property('service') }) it('Ensure config.servicePath', async () => { expect(serverless.config).to.have.property('servicePath') }) }) describe('Extend configuration', () => { const pluginConfig = require('../../fixtures/programmatic/plugin/extend-config-plugin').pluginConfig const serverlessPath = path.resolve( __dirname, '../../../scripts/serverless.js', ) it('Extends configuration with given values', async () => { const customExt = { custom: {} } const configExt = { plugins: ['./extend-config-plugin/index.js'], provider: { stage: 'dev', }, custom: {}, } _.set(customExt, pluginConfig.overwriteValuePath, 'test_value') const { servicePath: serviceDir } = await programmaticFixturesEngine.setup('plugin', { configExt, }) const serverlessProcess = await spawn('node', [serverlessPath, 'print'], { cwd: serviceDir, }) const configuration = yaml.load(String(serverlessProcess.stdoutBuffer)) const targetValue = _.get(configuration, pluginConfig.targetValuePath) expect(targetValue, 'Target value should not be undefined').to.not.be .undefined const afterInitValue = _.get( configuration, pluginConfig.afterInitValuePath, ) expect(afterInitValue, 'afterInitValue should be undefined').to.be .undefined const refValue = _.get(configuration, pluginConfig.refValuePath) expect(refValue).to.deep.equal( targetValue, 'refValue should equal targetValue', ) const overwriteValue = _.get( configuration, pluginConfig.overwriteValuePath, ) expect(overwriteValue).to.deep.equal( targetValue, 'overwriteValue should equal targetValue', ) }) }) })