You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

221 lines
6.9 KiB

'use strict';
const chai = require('chai');
const sinon = require('sinon');
const mockery = require('mockery');
const Serverless = require('serverless');
const makeWebpackMock = require('./webpack.mock');
const makeUtilsMock = require('./utils.mock');
chai.use(require('sinon-chai'));
const expect = chai.expect;
describe('run', () => {
let webpackMock;
let utilsMock;
let baseModule;
let module;
let serverless;
before(() => {
mockery.enable({ warnOnUnregistered: false });
webpackMock = makeWebpackMock();
utilsMock = makeUtilsMock();
mockery.registerMock('webpack', webpackMock);
mockery.registerMock('./utils', utilsMock);
baseModule = require('../lib/run');
Object.freeze(baseModule);
});
after(() => {
mockery.disable();
mockery.deregisterAll();
});
beforeEach(() => {
serverless = new Serverless();
serverless.cli = {
log: sinon.spy(),
consoleLog: sinon.spy(),
};
webpackMock._resetSpies();
utilsMock._resetSpies();
module = Object.assign({
serverless,
options: {},
}, baseModule);
});
describe('utils', () => {
it('should expose utils methods', () => {
expect(module.loadHandler).to.be.a('function');
expect(module.getEvent).to.be.a('function');
expect(module.getContext).to.be.a('function');
});
describe('loadHandler', () => {
const testFunctionId = 'testFunctionId';
const testHandlerModuleName = 'testHandlerModule';
const testHandlerFunctionName = 'testHandlerFunction';
const testFunctionsConfig = {
[testFunctionId]: {
handler: `${testHandlerModuleName}.${testHandlerFunctionName}`,
}
};
const testPath = '/testpath';
const testFilename = `${testHandlerModuleName}.js`;
const testModuleFileName = `${testPath}/${testFilename}`;
const testStats = {
compilation: {
options: {
output: {
path: testPath,
filename: testFilename,
},
},
},
};
const testHandlerFunction = sinon.spy();
const testModule = {
[testHandlerFunctionName]: testHandlerFunction,
};
before(() => {
mockery.registerMock(testModuleFileName, testModule);
});
after(() => {
mockery.deregisterMock(testModuleFileName);
});
beforeEach(() => {
serverless.service.functions = testFunctionsConfig;
});
it('should require the handler module', () => {
const res = module.loadHandler(testStats, testFunctionId);
expect(res).to.equal(testHandlerFunction);
expect(utilsMock.purgeCache).to.have.callCount(0);
});
it('should purge the modules cache if required', () => {
const res = module.loadHandler(testStats, testFunctionId, true);
expect(utilsMock.purgeCache).to.have.been.calledWith(testModuleFileName);
});
});
it('should return a default event with `getEvent` and no option path', () => {
module.options.path = null;
const res = module.getEvent();
expect(res).to.equal(null);
});
it('should load an event object from disk with `getEvent`', () => {
const testPath = 'testPath';
module.options.path = testPath;
const testExampleObject = {};
module.serverless.utils.readFileSync = sinon.stub().returns(testExampleObject);
const res = module.getEvent();
expect(res).to.equal(testExampleObject);
});
it('should return an context object with `getContext`', () => {
const testFunctionName = 'testFunctionName';
const res = module.getContext(testFunctionName);
expect(res).to.eql({
awsRequestId: 'testguid',
functionName: testFunctionName,
functionVersion: '$LATEST',
invokeid: 'testguid',
isDefaultFunctionVersion: true,
logGroupName: `/aws/lambda/${testFunctionName}`,
logStreamName: '2016/02/14/[HEAD]13370a84ca4ed8b77c427af260',
memoryLimitInMB: '1024',
});
});
});
describe('run', () => {
const testEvent = {};
const testContext = {};
const testStats = {};
const testFunctionId = 'testFunctionId';
const testFunctionResult = 'testFunctionResult';
beforeEach(() => {
module.options['function'] = testFunctionId;
module.getEvent = sinon.stub().returns(testEvent);
module.getContext = sinon.stub().returns(testContext);
});
it('should execute the given function handler', () => {
const testHandlerFunc = sinon.spy((e, c, cb) => cb(null, testFunctionResult));
module.loadHandler = sinon.stub().returns(testHandlerFunc);
return module
.run(testStats)
.then((res) => {
expect(res).to.equal(testFunctionResult);
expect(testHandlerFunc).to.have.been.calledWith(
testEvent,
testContext
);
});
});
it('should fail if the function handler returns an error', () => {
const testError = 'testError';
const testHandlerFunc = sinon.spy((e, c, cb) => cb(testError));
module.loadHandler = sinon.stub().returns(testHandlerFunc);
return module
.run(testStats)
.catch((res) => {
expect(res).to.equal(testError);
});
});
});
describe('watch', () => {
const testEvent = {};
const testContext = {};
const testStats = {};
const testFunctionId = 'testFunctionId';
const testFunctionResult = 'testFunctionResult';
beforeEach(() => {
module.options['function'] = testFunctionId;
module.getEvent = sinon.stub().returns(testEvent);
module.getContext = sinon.stub().returns(testContext);
});
it('should throw if webpack watch fails', () => {
const testError = 'testError';
webpackMock.compilerMock.watch = sinon.spy((opt, cb) => cb(testError));
expect(module.watch.bind(module)).to.throw(testError);
});
it('should throw if function handler fails', () => {
const testError = 'testHandlerError';
const testHandlerFunc = sinon.spy((e, c, cb) => cb(testError));
module.loadHandler = sinon.stub().returns(testHandlerFunc);
let testCb;
webpackMock.compilerMock.watch = sinon.spy((opt, cb) => {
testCb = cb;
cb(null, webpackMock.statsMock);
});
expect(module.watch.bind(module)).to.throw(testError);
});
it('should call the handler every time a compilation occurs', () => {
const testHandlerFunc = sinon.spy((e, c, cb) => cb(null, testFunctionResult));
module.loadHandler = sinon.stub().returns(testHandlerFunc);
let testCb;
webpackMock.compilerMock.watch = sinon.spy((opt, cb) => {
testCb = cb;
cb(null, webpackMock.statsMock);
});
module.watch();
expect(testHandlerFunc).to.have.callCount(1);
testCb(null, webpackMock.statsMock);
expect(testHandlerFunc).to.have.callCount(2);
});
});
});