diff --git a/.travis.yml b/.travis.yml index 0a5ead6..59e3686 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,4 @@ language: node_js node_js: - - '10' - - '8' - - '6' - - '4' + - 'lts/erbium' + - 'lts/dubnium' diff --git a/index.d.ts b/index.d.ts index 2817d9c..51070ed 100644 --- a/index.d.ts +++ b/index.d.ts @@ -10,8 +10,12 @@ interface ContextOptions { timeout?: number; } -declare var mockContext: { - (options?: ContextOptions): Context; -}; +interface MockContext extends Context { + Promise: Promise; +} + +type MockInitialize = (options?: ContextOptions) => MockContext; + +declare const mockContext: MockInitialize; export = mockContext; diff --git a/index.js b/index.js index 8624a89..718aba3 100644 --- a/index.js +++ b/index.js @@ -1,40 +1,46 @@ -'use strict'; -const uuid = require('uuid'); -const moment = require('moment'); +const uuidv1 = require('uuid/v1'); +const uuidv4 = require('uuid/v4'); const defer = require('pinkie-defer'); const pkg = require('./package.json'); -module.exports = options => { - const id = uuid.v1(); - const stream = uuid.v4().replace(/-/g, ''); +const mockContext = userOptions => { + const id = uuidv1(); + const stream = uuidv4().replace(/-/g, ''); - const opts = Object.assign({ + const options = { region: 'us-west-1', account: '123456789012', functionName: pkg.name, functionVersion: '$LATEST', memoryLimitInMB: '128', - timeout: 3 - }, options); + timeout: 3, + ...userOptions + }; const deferred = defer(); - const start = Date.now(); + const d = new Date(); + const logDateString = [ + d.getFullYear(), + ('0' + (d.getMonth() + 1)).slice(-2), + ('0' + d.getDate()).slice(-2) + ].join('/'); + const start = d.getTime(); let end; - + let timeout = null; const context = { callbackWaitsForEmptyEventLoop: true, - functionName: opts.functionName, - functionVersion: opts.functionVersion, - invokedFunctionArn: `arn:aws:lambda:${opts.region}:${opts.account}:function:${opts.functionName}:${opts.alias || opts.functionVersion}`, - memoryLimitInMB: opts.memoryLimitInMB, + functionName: options.functionName, + functionVersion: options.functionVersion, + invokedFunctionArn: `arn:aws:lambda:${options.region}:${options.account}:function:${options.functionName}:${options.alias || options.functionVersion}`, + memoryLimitInMB: options.memoryLimitInMB, awsRequestId: id, invokeid: id, - logGroupName: `/aws/lambda/${opts.functionName}`, - logStreamName: `${moment().format('YYYY/MM/DD')}/[${opts.functionVersion}]/${stream}`, + logGroupName: `/aws/lambda/${options.functionName}`, + logStreamName: `${logDateString}/[${options.functionVersion}]/${stream}`, getRemainingTimeInMillis: () => { const endTime = end || Date.now(); - const remainingTime = (opts.timeout * 1000) - (endTime - start); + const remainingTime = (options.timeout * 1000) - (endTime - start); return Math.max(0, remainingTime); }, @@ -53,6 +59,10 @@ module.exports = options => { deferred.reject(err); }, done: (err, result) => { + if (timeout) { + clearTimeout(timeout); + } + if (err) { context.fail(err); return; @@ -63,11 +73,13 @@ module.exports = options => { Promise: new Promise(deferred) }; - setTimeout(() => { + timeout = setTimeout(() => { if (context.getRemainingTimeInMillis() === 0) { - context.fail(new Error(`Task timed out after ${opts.timeout}.00 seconds`)); + context.fail(new Error(`Task timed out after ${options.timeout}.00 seconds`)); } - }, opts.timeout * 1000); + }, options.timeout * 1000); return context; }; + +module.exports = mockContext; diff --git a/package.json b/package.json index 9037f61..f8ee09b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aws-lambda-mock-context", - "version": "3.2.1", + "version": "4.0.0", "description": "AWS Lambda mock context object", "license": "MIT", "author": { @@ -9,11 +9,16 @@ "url": "https://github.com/SamVerschueren" }, "engines": { - "node": ">=4" + "node": ">=10.18.0" }, "scripts": { "test": "xo && ava" }, + "ava": { + "require": [ + "esm" + ] + }, "files": [ "index.js", "index.d.ts" @@ -29,16 +34,15 @@ "promise" ], "dependencies": { - "moment": "^2.10.5", "pinkie-defer": "^1.0.0", - "uuid": "^3.0.1" + "uuid": "3.4.0" }, "devDependencies": { - "@types/aws-lambda": "^8.10.7", - "ava": "*", - "delay": "^2.0.0", - "in-range": "^1.0.0", - "xo": "^0.20.3" + "@types/aws-lambda": "^8.10.46", + "ava": "^3.5.1", + "delay": "^4.3.0", + "in-range": "^2.0.0", + "xo": "^0.28.1" }, "types": "index.d.ts" } diff --git a/test.js b/test.js index 5dc2761..babebbd 100644 --- a/test.js +++ b/test.js @@ -1,16 +1,17 @@ -import test from 'ava'; -import delay from 'delay'; -import inRange from 'in-range'; -import m from '.'; +const test = require('ava'); +const delay = require('delay'); +const inRange = require('in-range'); +const m = require('.'); -function invokeAsync(method, result, opts) { - opts = Object.assign({ +const invokeAsync = (method, result, options) => { + options = { ms: 500, - timeout: 3 - }, opts); + timeout: 3, + ...options + }; const ctx = m({ - timeout: opts.timeout + timeout: options.timeout }); setTimeout(() => { @@ -20,10 +21,10 @@ function invokeAsync(method, result, opts) { } ctx[method](result); - }, opts.ms); + }, options.ms); return ctx.Promise; -} +}; test('succeed', async t => { t.is(await invokeAsync('succeed', 'baz'), 'baz'); @@ -31,9 +32,9 @@ test('succeed', async t => { }); test('fail', async t => { - await t.throws(invokeAsync('fail', 'promise fail'), 'promise fail'); - await t.throws(invokeAsync('fail', new Error('promise fail')), 'promise fail'); - await t.throws(invokeAsync('done', new Error('promise fail')), 'promise fail'); + await t.throwsAsync(invokeAsync('fail', 'promise fail'), null, 'promise fail'); + await t.throwsAsync(invokeAsync('fail', new Error('promise fail')), null, 'promise fail'); + await t.throwsAsync(invokeAsync('done', new Error('promise fail')), null, 'promise fail'); }); test('result', t => { @@ -74,7 +75,7 @@ test('remaining time', async t => { const ms = ctx.getRemainingTimeInMillis(); - t.true(inRange(ctx.getRemainingTimeInMillis(), 1950, 2050)); + t.true(inRange(ctx.getRemainingTimeInMillis(), {start: 1950, end: 2050})); await delay(10); @@ -96,10 +97,10 @@ test('set function timeout', async t => { await delay(1000); - t.true(inRange(ctx.getRemainingTimeInMillis(), 8950, 9050)); + t.true(inRange(ctx.getRemainingTimeInMillis(), {start: 8950, end: 9050})); ctx.succeed(); }); test('timeout throws error', async t => { - await t.throws(invokeAsync('succeed', 'foo', {ms: 2000, timeout: 1}), 'Task timed out after 1.00 seconds'); + await t.throwsAsync(invokeAsync('succeed', 'foo', {ms: 2000, timeout: 1}), null, 'Task timed out after 1.00 seconds'); });