Merge pull request #3037 from breath103/master

add features on AWSInvokeLocal Plugin.
This commit is contained in:
Eslam λ Hefnawy 2017-03-13 19:23:39 +08:00 committed by GitHub
commit 8a32b39c37
3 changed files with 118 additions and 6 deletions

View File

@ -0,0 +1,22 @@
'use strict';
module.exports.withErrorByDone = (event, context) => {
context.done(new Error('failed'));
};
module.exports.withMessageByDone = (event, context) => {
context.done(null, 'Succeed');
};
module.exports.withMessageByLambdaProxy = (event, context) => {
context.done(null, {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
result: true,
message: 'Whatever',
}),
});
};

View File

@ -42,7 +42,15 @@ class AwsInvokeLocal {
if (!this.serverless.utils.fileExistsSync(absolutePath)) {
throw new this.serverless.classes.Error('The file you provided does not exist.');
}
this.options.data = this.serverless.utils.readFileSync(absolutePath);
//
if (absolutePath.endsWith('.js')) {
// to support js - export as an input data
this.options.data = require(absolutePath); // eslint-disable-line global-require
} else {
this.options.data = this.serverless.utils.readFileSync(absolutePath);
}
resolve();
} else {
try {
@ -143,8 +151,15 @@ class AwsInvokeLocal {
* we need require() here to load the handler from the file system
* which the user has to supply by passing the function name
*/
lambda = require(path // eslint-disable-line global-require
.join(this.serverless.config.servicePath, handlerPath))[handlerName];
const handlersContainer = require( // eslint-disable-line global-require
path.join(
this.serverless.config.servicePath,
this.options.extraServicePath || '',
handlerPath
)
);
lambda = handlersContainer[handlerName];
} catch (error) {
this.serverless.cli.consoleLog(error);
process.exit(0);
@ -167,10 +182,24 @@ class AwsInvokeLocal {
this.serverless.cli.consoleLog(chalk.red(JSON.stringify(errorResult, null, 4)));
process.exitCode = 1;
} else if (result) {
if (result.headers && result.headers['Content-Type'] === 'application/json') {
if (result.body) {
try {
Object.assign(result, {
body: JSON.parse(result.body),
});
} catch (e) {
throw new Error('Content-Type of response is application/json but body is not json');
}
}
}
this.serverless.cli.consoleLog(JSON.stringify(result, null, 4));
}
};
const startTime = new Date();
const context = {
awsRequestId: 'id',
invokeid: 'id',
@ -188,11 +217,11 @@ class AwsInvokeLocal {
fail(error) {
return callback(error);
},
done() {
return callback();
done(error, result) {
return callback(error, result);
},
getRemainingTimeInMillis() {
return 5000;
return (new Date()).valueOf() - startTime.valueOf();
},
};

View File

@ -150,6 +150,28 @@ describe('AwsInvokeLocal', () => {
});
});
it('it should require a js file if file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
const jsContent = [
'module.exports = {',
' headers: { "Content-Type" : "application/json" },',
' body: JSON.stringify([100, 200]),',
'}',
].join('\n');
serverless.utils.writeFileSync(path
.join(serverless.config.servicePath, 'data.js'), jsContent);
awsInvokeLocal.options.path = 'data.js';
return awsInvokeLocal.extendedValidate().then(() => {
expect(awsInvokeLocal.options.data).to.deep.equal({
headers: { 'Content-Type': 'application/json' },
body: '[100,200]',
});
});
});
it('it should throw error if service path is not set', () => {
serverless.config.servicePath = false;
expect(() => awsInvokeLocal.extendedValidate()).to.throw(Error);
@ -308,6 +330,45 @@ describe('AwsInvokeLocal', () => {
serverless.cli.consoleLog.restore();
});
describe('with done method', () => {
it('should exit with error exit code', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
awsInvokeLocal.invokeLocalNodeJs('fixture/handlerWithSuccess', 'withErrorByDone');
expect(process.exitCode).to.be.equal(1);
});
it('should succeed if succeed', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
awsInvokeLocal.invokeLocalNodeJs('fixture/handlerWithSuccess', 'withMessageByDone');
expect(serverless.cli.consoleLog.lastCall.args[0]).to.contain('"Succeed"');
});
});
describe('with Lambda Proxy with application/json response', () => {
it('should succeed if succeed', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
awsInvokeLocal.invokeLocalNodeJs('fixture/handlerWithSuccess', 'withMessageByLambdaProxy');
expect(serverless.cli.consoleLog.lastCall.args[0]).to.contain('{\n "statusCode": 200,\n "headers": {\n "Content-Type": "application/json"\n },\n "body": {\n "result": true,\n "message": "Whatever"\n }\n}'); // eslint-disable-line
});
});
describe('with extraServicePath', () => {
it('should succeed if succeed', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
awsInvokeLocal.options.extraServicePath = 'fixture';
awsInvokeLocal.invokeLocalNodeJs('handlerWithSuccess', 'withMessageByLambdaProxy');
expect(serverless.cli.consoleLog.lastCall.args[0]).to.contain('{\n "statusCode": 200,\n "headers": {\n "Content-Type": "application/json"\n },\n "body": {\n "result": true,\n "message": "Whatever"\n }\n}'); // eslint-disable-line
});
});
it('should exit with error exit code', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;