UNPKG

serverless-step-functions

Version:

The module is AWS Step Functions plugin for Serverless Framework

423 lines (392 loc) 20.2 kB
'use strict'; const expect = require('chai').expect; const sinon = require('sinon'); const BbPromise = require('bluebird'); const Serverless = require('serverless/lib/Serverless'); const AwsProvider = require('serverless/lib/plugins/aws/provider'); const CLI = require('serverless/lib/classes/CLI'); const chalk = require('chalk'); const ServerlessStepFunctions = require('./index'); const logger = require('./utils/logger'); describe('#index', () => { let serverless; let serverlessStepFunctions; beforeEach(() => { serverless = new Serverless(); serverless.service.service = 'step-functions'; const options = { stage: 'dev', region: 'us-east-1', }; serverless.configSchemaHandler = { // eslint-disable-next-line no-unused-vars defineTopLevelProperty: (propertyName, propertySchema) => {}, }; serverless.setProvider('aws', new AwsProvider(serverless)); serverless.cli = new CLI(serverless); serverlessStepFunctions = new ServerlessStepFunctions(serverless, options); }); describe('#constructor()', () => { it('should have hooks', () => expect(serverlessStepFunctions.hooks).to.be.not.empty); it('should set the provider variable to an instance of AwsProvider', () => expect(serverlessStepFunctions.provider).to.be.instanceof(AwsProvider)); it('should have access to the serverless instance', () => expect(serverlessStepFunctions.serverless).to.deep.equal(serverless)); it('should set the options variable', () => expect(serverlessStepFunctions.options).to.deep.equal({ stage: 'dev', region: 'us-east-1', })); it('should set the region variable', () => expect(serverlessStepFunctions.region).to.be.equal('us-east-1')); it('should set the stage variable', () => expect(serverlessStepFunctions.stage).to.be.equal('dev')); it('should run invoke:stepf:invoke promise chain in order', () => { const invokeStub = sinon .stub(serverlessStepFunctions, 'invoke').returns(BbPromise.resolve()); const yamlParseStub = sinon .stub(serverlessStepFunctions, 'yamlParse').returns(BbPromise.resolve()); return serverlessStepFunctions.hooks['invoke:stepf:invoke']() .then(() => { expect(invokeStub.calledOnce).to.be.equal(true); expect(yamlParseStub.calledOnce).to.be.equal(true); serverlessStepFunctions.yamlParse.restore(); serverlessStepFunctions.invoke.restore(); }); }); it('should run package:initialize promise chain in order', () => { const yamlParseStub = sinon .stub(serverlessStepFunctions, 'yamlParse').returns(BbPromise.resolve()); return serverlessStepFunctions.hooks['package:initialize']() .then(() => { expect(yamlParseStub.calledOnce).to.be.equal(true); serverlessStepFunctions.yamlParse.restore(); }); }); it('should run package:compileFunctions promise chain in order', () => { const compileIamRoleStub = sinon .stub(serverlessStepFunctions, 'compileIamRole').returns(BbPromise.resolve()); const compileStateMachinesStub = sinon .stub(serverlessStepFunctions, 'compileStateMachines').returns(BbPromise.resolve()); const compileActivitiesStub = sinon .stub(serverlessStepFunctions, 'compileActivities').returns(BbPromise.resolve()); const compileAlarmsStub = sinon .stub(serverlessStepFunctions, 'compileAlarms').returns(BbPromise.resolve()); const compileNotificationsStub = sinon .stub(serverlessStepFunctions, 'compileNotifications').returns(BbPromise.resolve()); return serverlessStepFunctions.hooks['package:compileFunctions']() .then(() => { expect(compileIamRoleStub.calledOnce).to.be.equal(true); expect(compileStateMachinesStub.calledAfter(compileIamRoleStub)).to.be.equal(true); expect(compileActivitiesStub.calledAfter(compileStateMachinesStub)).to.be.equal(true); expect(compileAlarmsStub.calledAfter(compileActivitiesStub)).to.be.equal(true); expect(compileNotificationsStub.calledAfter(compileAlarmsStub)).to.be.equal(true); serverlessStepFunctions.compileIamRole.restore(); serverlessStepFunctions.compileStateMachines.restore(); serverlessStepFunctions.compileActivities.restore(); serverlessStepFunctions.compileAlarms.restore(); serverlessStepFunctions.compileNotifications.restore(); }); }); it('should run package:compileEvents promise chain in order when http event is empty', () => { const compileScheduledEventsStub = sinon .stub(serverlessStepFunctions, 'compileScheduledEvents').returns(BbPromise.resolve()); const compileCloudWatchEventEventsStub = sinon .stub(serverlessStepFunctions, 'compileCloudWatchEventEvents') .returns(BbPromise.resolve()); const httpValidateStub = sinon .stub(serverlessStepFunctions, 'httpValidate').returns({ events: [] }); const compileRestApiStub = sinon .stub(serverlessStepFunctions, 'compileRestApi').returns(BbPromise.resolve()); const compileResourcesStub = sinon .stub(serverlessStepFunctions, 'compileResources').returns(BbPromise.resolve()); const compileMethodsStub = sinon .stub(serverlessStepFunctions, 'compileMethods').returns(BbPromise.resolve()); const compileAuthorizersStub = sinon .stub(serverlessStepFunctions, 'compileAuthorizers').returns(BbPromise.resolve()); const compileHttpLambdaPermissions = sinon .stub(serverlessStepFunctions, 'compileHttpLambdaPermissions') .returns(BbPromise.resolve()); const compileCorsStub = sinon .stub(serverlessStepFunctions, 'compileCors').returns(BbPromise.resolve()); const compileHttpIamRoleStub = sinon .stub(serverlessStepFunctions, 'compileHttpIamRole').returns(BbPromise.resolve()); const compileDeploymentStub = sinon .stub(serverlessStepFunctions, 'compileDeployment').returns(BbPromise.resolve()); const compileApiKeysStub = sinon .stub(serverlessStepFunctions, 'compileApiKeys').returns(BbPromise.resolve()); const compileUsagePlanStub = sinon .stub(serverlessStepFunctions, 'compileUsagePlan').returns(BbPromise.resolve()); const compileUsagePlanKeysStub = sinon .stub(serverlessStepFunctions, 'compileUsagePlanKeys').returns(BbPromise.resolve()); return serverlessStepFunctions.hooks['package:compileEvents']() .then(() => { expect(compileScheduledEventsStub.calledOnce).to.be.equal(true); expect(compileCloudWatchEventEventsStub.calledOnce).to.be.equal(true); expect(httpValidateStub.calledOnce).to.be.equal(true); expect(compileRestApiStub.notCalled).to.be.equal(true); expect(compileResourcesStub.notCalled).to.be.equal(true); expect(compileMethodsStub.notCalled).to.be.equal(true); expect(compileAuthorizersStub.notCalled).to.be.equal(true); expect(compileHttpLambdaPermissions.notCalled).to.be.equal(true); expect(compileCorsStub.notCalled).to.be.equal(true); expect(compileHttpIamRoleStub.notCalled).to.be.equal(true); expect(compileDeploymentStub.notCalled).to.be.equal(true); expect(compileApiKeysStub.notCalled).to.be.equal(true); expect(compileUsagePlanStub.notCalled).to.be.equal(true); expect(compileUsagePlanKeysStub.notCalled).to.be.equal(true); serverlessStepFunctions.compileScheduledEvents.restore(); serverlessStepFunctions.compileCloudWatchEventEvents.restore(); serverlessStepFunctions.httpValidate.restore(); serverlessStepFunctions.compileRestApi.restore(); serverlessStepFunctions.compileResources.restore(); serverlessStepFunctions.compileMethods.restore(); serverlessStepFunctions.compileAuthorizers.restore(); serverlessStepFunctions.compileHttpLambdaPermissions.restore(); serverlessStepFunctions.compileCors.restore(); serverlessStepFunctions.compileHttpIamRole.restore(); serverlessStepFunctions.compileDeployment.restore(); serverlessStepFunctions.compileApiKeys.restore(); serverlessStepFunctions.compileUsagePlan.restore(); serverlessStepFunctions.compileUsagePlanKeys.restore(); }); }); it('should run package:compileEvents promise chain in order', () => { const compileScheduledEventsStub = sinon .stub(serverlessStepFunctions, 'compileScheduledEvents').returns(BbPromise.resolve()); const compileCloudWatchEventEventsStub = sinon .stub(serverlessStepFunctions, 'compileCloudWatchEventEvents') .returns(BbPromise.resolve()); const httpValidateStub = sinon .stub(serverlessStepFunctions, 'httpValidate').returns({ events: [1, 2, 3] }); const compileRestApiStub = sinon .stub(serverlessStepFunctions, 'compileRestApi').returns(BbPromise.resolve()); const compileResourcesStub = sinon .stub(serverlessStepFunctions, 'compileResources').returns(BbPromise.resolve()); const compileMethodsStub = sinon .stub(serverlessStepFunctions, 'compileMethods').returns(BbPromise.resolve()); const compileRequestValidatorsStub = sinon .stub(serverlessStepFunctions, 'compileRequestValidators').returns(BbPromise.resolve()); const compileAuthorizersStub = sinon .stub(serverlessStepFunctions, 'compileAuthorizers').returns(BbPromise.resolve()); const compileCorsStub = sinon .stub(serverlessStepFunctions, 'compileCors').returns(BbPromise.resolve()); const compileHttpIamRoleStub = sinon .stub(serverlessStepFunctions, 'compileHttpIamRole').returns(BbPromise.resolve()); const compileDeploymentStub = sinon .stub(serverlessStepFunctions, 'compileDeployment').returns(BbPromise.resolve()); const compileApiKeysStub = sinon .stub(serverlessStepFunctions, 'compileApiKeys').returns(BbPromise.resolve()); const compileUsagePlanStub = sinon .stub(serverlessStepFunctions, 'compileUsagePlan').returns(BbPromise.resolve()); const compileUsagePlanKeysStub = sinon .stub(serverlessStepFunctions, 'compileUsagePlanKeys').returns(BbPromise.resolve()); return serverlessStepFunctions.hooks['package:compileEvents']() .then(() => { expect(compileScheduledEventsStub.calledOnce).to.be.equal(true); expect(compileCloudWatchEventEventsStub.calledOnce).to.be.equal(true); expect(httpValidateStub.calledOnce).to.be.equal(true); expect(compileRestApiStub.calledOnce).to.be.equal(true); expect(compileResourcesStub.calledAfter(compileRestApiStub)).to.be.equal(true); expect(compileMethodsStub.calledAfter(compileResourcesStub)).to.be.equal(true); expect(compileAuthorizersStub.calledAfter(compileResourcesStub)).to.be.equal(true); expect(compileRequestValidatorsStub.calledAfter(compileMethodsStub)).to.be.equal(true); expect(compileCorsStub.calledAfter(compileRequestValidatorsStub)).to.be.equal(true); expect(compileHttpIamRoleStub.calledAfter(compileCorsStub)).to.be.equal(true); expect(compileDeploymentStub.calledAfter(compileHttpIamRoleStub)).to.be.equal(true); expect(compileApiKeysStub.calledAfter(compileDeploymentStub)).to.be.equal(true); expect(compileUsagePlanStub.calledAfter(compileApiKeysStub)).to.be.equal(true); expect(compileUsagePlanKeysStub.calledAfter(compileUsagePlanStub)).to.be.equal(true); serverlessStepFunctions.compileScheduledEvents.restore(); serverlessStepFunctions.compileCloudWatchEventEvents.restore(); serverlessStepFunctions.httpValidate.restore(); serverlessStepFunctions.compileRestApi.restore(); serverlessStepFunctions.compileResources.restore(); serverlessStepFunctions.compileMethods.restore(); serverlessStepFunctions.compileRequestValidators.restore(); serverlessStepFunctions.compileAuthorizers.restore(); serverlessStepFunctions.compileHttpIamRole.restore(); serverlessStepFunctions.compileDeployment.restore(); serverlessStepFunctions.compileApiKeys.restore(); serverlessStepFunctions.compileUsagePlan.restore(); serverlessStepFunctions.compileUsagePlanKeys.restore(); }); }); it('should run after:deploy:deploy promise chain in order', () => { const getEndpointInfoStub = sinon .stub(serverlessStepFunctions, 'getEndpointInfo').returns(BbPromise.resolve()); const displayStub = sinon .stub(serverlessStepFunctions, 'display').returns(BbPromise.resolve()); return serverlessStepFunctions.hooks['after:deploy:deploy']() .then(() => { expect(getEndpointInfoStub.calledOnce).to.be.equal(true); expect(displayStub.calledAfter(getEndpointInfoStub)).to.be.equal(true); serverlessStepFunctions.getEndpointInfo.restore(); serverlessStepFunctions.display.restore(); }); }); }); describe('#invoke()', () => { it('should run promise chain in order', () => { const getStateMachineArnStub = sinon .stub(serverlessStepFunctions, 'getStateMachineArn').returns(BbPromise.resolve()); const startExecutionStub = sinon .stub(serverlessStepFunctions, 'startExecution').returns(BbPromise.resolve()); const describeExecutionStub = sinon .stub(serverlessStepFunctions, 'describeExecution') .returns(BbPromise.resolve({ status: 'SUCCEED' })); return serverlessStepFunctions.invoke() .then(() => { expect(getStateMachineArnStub.calledOnce).to.be.equal(true); expect(startExecutionStub.calledAfter(getStateMachineArnStub)).to.be.equal(true); expect(describeExecutionStub.calledAfter(startExecutionStub)).to.be.equal(true); serverlessStepFunctions.getStateMachineArn.restore(); serverlessStepFunctions.startExecution.restore(); serverlessStepFunctions.describeExecution.restore(); }); }); it('should run promise chain in order when invocation error occurs', () => { const getStateMachineArnStub = sinon .stub(serverlessStepFunctions, 'getStateMachineArn').returns(BbPromise.resolve()); const startExecutionStub = sinon .stub(serverlessStepFunctions, 'startExecution').returns(BbPromise.resolve()); const describeExecutionStub = sinon .stub(serverlessStepFunctions, 'describeExecution') .returns(BbPromise.resolve({ status: 'FAILED' })); const getExecutionHistoryStub = sinon .stub(serverlessStepFunctions, 'getExecutionHistory').returns(BbPromise.resolve({ events: [{ executionFailedEventDetails: '', }], })); return serverlessStepFunctions.invoke() .then(() => { expect(getStateMachineArnStub.calledOnce).to.be.equal(true); expect(startExecutionStub.calledAfter(getStateMachineArnStub)).to.be.equal(true); expect(describeExecutionStub.calledAfter(startExecutionStub)).to.be.equal(true); expect(getExecutionHistoryStub.calledAfter(describeExecutionStub)).to.be.equal(true); serverlessStepFunctions.getStateMachineArn.restore(); serverlessStepFunctions.startExecution.restore(); serverlessStepFunctions.describeExecution.restore(); serverlessStepFunctions.getExecutionHistory.restore(); }); }); }); describe('#deploy()', () => { let logSpy; beforeEach(() => { logger.config(serverless); logSpy = sinon.spy(logger, 'log'); serverless.cli = { consoleLog: logSpy }; serverlessStepFunctions.endpointInfo = 'https://example.com'; }); afterEach(() => { logSpy.restore(); }); it('should not display endpoints if http event not given', () => { serverlessStepFunctions.serverless.service.stepFunctions = {}; const expectedMessage = ''; const message = serverlessStepFunctions.display(); expect(logSpy.calledOnce).to.equal(false); expect(message).to.equal(expectedMessage); }); it('should display endpoints if http event given as object', () => { serverlessStepFunctions.serverless.service.stepFunctions = { stateMachines: { myStateMachine: { define: 'my-define', events: [ { http: { path: 'foo/bar', method: 'post', }, }, ], }, }, }; let expectedMessage = ''; expectedMessage += `${chalk.yellow.underline('Serverless StepFunctions Outputs')}\n`; expectedMessage += `${chalk.yellow('endpoints:')}`; expectedMessage += '\n POST - https://example.com/foo/bar'; expectedMessage += '\n'; const message = serverlessStepFunctions.display(); expect(logSpy.calledOnce).to.equal(true); expect(message).to.equal(expectedMessage); }); it('should display endpoints if http event given as string', () => { serverlessStepFunctions.serverless.service.stepFunctions = { stateMachines: { myStateMachine: { define: 'my-define', events: [ { http: 'post foo/bar', }, ], }, }, }; let expectedMessage = ''; expectedMessage += `${chalk.yellow.underline('Serverless StepFunctions Outputs')}\n`; expectedMessage += `${chalk.yellow('endpoints:')}`; expectedMessage += '\n POST - https://example.com/foo/bar'; expectedMessage += '\n'; const message = serverlessStepFunctions.display(); expect(logSpy.calledOnce).to.equal(true); expect(message).to.equal(expectedMessage); }); it('should display endpoints if http event given with path as slash', () => { serverlessStepFunctions.serverless.service.stepFunctions = { stateMachines: { myStateMachine: { define: 'my-define', events: [ { http: 'post /', }, ], }, }, }; let expectedMessage = ''; expectedMessage += `${chalk.yellow.underline('Serverless StepFunctions Outputs')}\n`; expectedMessage += `${chalk.yellow('endpoints:')}`; expectedMessage += '\n POST - https://example.com'; expectedMessage += '\n'; const message = serverlessStepFunctions.display(); expect(logSpy.calledOnce).to.equal(true); expect(message).to.equal(expectedMessage); }); it('should display endpoints if events given as object', () => { serverlessStepFunctions.serverless.service.stepFunctions = { stateMachines: { myStateMachine: { define: 'my-define', events: {}, }, }, }; const expectedMessage = ''; const message = serverlessStepFunctions.display(); expect(logSpy.calledOnce).to.equal(false); expect(message).to.equal(expectedMessage); }); it('should display endpoints if http event does not exists', () => { serverlessStepFunctions.serverless.service.stepFunctions = { stateMachines: { myStateMachine: { define: 'my-define', events: [ { foo: 'bar', }, ], }, }, }; const expectedMessage = ''; const message = serverlessStepFunctions.display(); expect(logSpy.calledOnce).to.equal(false); expect(message).to.equal(expectedMessage); }); }); });