├── .gitignore ├── .npmignore ├── .travis.yml ├── README.md ├── globals.d.ts ├── lib ├── events │ └── aws │ │ ├── alexa-skill-event-template.json │ │ ├── alexa-smart-home-event-template.json │ │ ├── api-gateway-event-template.json │ │ ├── cloud-watch-event-template.json │ │ ├── cloud-watch-log-event-template.json │ │ ├── cognito-user-pool-event-template.json │ │ ├── dynamo-stream-event-template.json │ │ ├── kinesis-template.json │ │ ├── s3-template.json │ │ ├── scheduled-template.json │ │ ├── sns-template.json │ │ └── sqs-template.json ├── index.spec.ts ├── index.ts └── types │ └── aws-lambda │ └── index.d.ts ├── package.json ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | matrix: 3 | include: 4 | - node_js: 6 5 | - node_js: 8 6 | - node_js: '10.15' 7 | install: 8 | - npm install 9 | script: 10 | - npm run lint 11 | - npm run test 12 | - npm run build 13 | deploy: 14 | - provider: npm 15 | email: services@serverless.com 16 | skip_cleanup: true 17 | tag: latest 18 | on: 19 | node: 10.15 20 | tags: true 21 | repo: serverless/event-mocks 22 | api_key: 23 | secure: "taCa56B/6O1glO83f5G1h6QyfAfLiyYmfbKOtqkVG90QqJEugupQ9RRK/uDgNMKhDhXx9zFYPoj8GK1WPQ+bNn0PEPflRgmgsJBjqLlqUTzVk+0HPPQz9I09IoS0CmQJyo54g8Twl/sEp4N2mObrvBwj03QMrJDmFup6FI9vi7inxhMTnBNMAxIm6f4VfrV1olBeyNhiXbTpTp3WINUcikospxTiGPZot+gOOpEJyXqr0M+b7tiqsYKsyUYz08gjSaYIjGpdZnWvLj+siQYNKlywogY/VEu7W9k5NRVMbfp9edaDEZ4Rk7h/20/Mv5AScIbCX/eKbbCvi8VVyqpNoGyPuOPd1MXZ7NoweZsypYi0KVHyV2aTF63SbUE5gSGYCojYRA2kUMRWj1DJzrY21UEOCw0PrL8xmsAPYBD25GDC5Fdc9idSUsC61S5WP/j6m7lggpmgQbne8nfe2qeAKwH7fOWydcvqmRnozSzzo5zTT07B0qb79LzbuCXA0baMkCpFFqtRwgXBxk7lRHA9G84XDwRjfzRg54mhCgML6EgagIYfSH/3VW6w8jJs09kP0tbHiqmPLjDIxaPiaf4hjj4zSMmGeSYV8OZOvukET31kGdieYK262Qh5DRWT0xC/56Okadl4q4mUVWFKapqfmmLtUjqmbg+gow8VUuSvWDE=" 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Event Mocks 2 | A small library that includes details mocks of AWS Lambda event sources. Useful for use when unit testing your Lambda functions. 3 | Supported Event Sources are: 4 | - [x] API Gateway 5 | - [x] SNS 6 | - [x] SQS 7 | - [x] DynamoDB 8 | - [x] S3 9 | - [x] Scheduled 10 | - [x] Websocket 11 | - [x] Alexa Skill 12 | - [x] Alexa Smart Home 13 | - [x] CloudWatch 14 | - [x] CloudWatch Log 15 | - [x] Cognito Pool 16 | - [x] IoT 17 | 18 | The library simply uses default event source mock templates and merge it with any overwrite you provide. [Check out the JSON template files](./lib/events/aws) to learn more about the data structure of each event source. 19 | 20 | ## Usage 21 | 22 | ### SNS 23 | 24 | ```js 25 | import createEvent from "@serverless/event-mocks" 26 | 27 | const mocked = createEvent( 28 | "aws:sns", 29 | { 30 | Records: [{ 31 | Sns: { 32 | Message: "trigger-email" 33 | } 34 | }] 35 | }); 36 | ``` 37 | 38 | ### API Gateway 39 | 40 | ```js 41 | import createEvent from "@serverless/event-mocks" 42 | 43 | const event = createEvent( 44 | "aws:apiGateway", 45 | { 46 | body: { 47 | first_name: "Sam", 48 | last_name: "Smith" 49 | } 50 | }); 51 | ``` 52 | 53 | ### S3 54 | 55 | ```js 56 | import createEvent from "@serverless/event-mocks" 57 | 58 | const event = createEvent( 59 | "aws:s3", 60 | { 61 | Records: [{ 62 | eventName: "ObjectCreated:Put", 63 | s3: { 64 | bucket: { 65 | name: "my-bucket-name" 66 | }, 67 | object: { 68 | key: "object-key" 69 | } 70 | } 71 | }] 72 | }); 73 | ``` 74 | 75 | ### Scheduled 76 | 77 | ```js 78 | import createEvent from "@serverless/event-mocks" 79 | 80 | const event = createEvent( 81 | "aws:scheduled", 82 | { 83 | region: "us-west-2" 84 | }); 85 | ``` 86 | 87 | ### Kinesis 88 | 89 | ```js 90 | import createEvent from "@serverless/event-mocks" 91 | 92 | const event = createEvent( 93 | "aws:kinesis", 94 | { 95 | data: new Buffer("this is test data").toString("base64") 96 | }); 97 | ``` 98 | 99 | ### Dynamo 100 | 101 | ```js 102 | import createEvent from "@serverless/event-mocks" 103 | 104 | const event = createEvent( 105 | "aws:dynamo", 106 | { 107 | Records: [ 108 | { 109 | eventID: "1", 110 | eventVersion: "1.0", 111 | dynamodb: { 112 | Keys: { 113 | Id: { 114 | N: "101" 115 | } 116 | }, 117 | NewImage: { 118 | Message: { 119 | S: "New item!" 120 | }, 121 | Id: { 122 | N: "101" 123 | } 124 | }, 125 | StreamViewType: "NEW_AND_OLD_IMAGES", 126 | SequenceNumber: "111", 127 | SizeBytes: 26 128 | }, 129 | awsRegion: "us-west-2", 130 | eventName: "INSERT", 131 | eventSourceARN: "arn:aws:dynamodb:us-east-1:123456789012:table/images", 132 | eventSource: "aws:dynamodb" 133 | } 134 | ] 135 | }); 136 | ``` 137 | 138 | ### Websocket event 139 | 140 | ```js 141 | const event = createEvent("aws:websocket", { 142 | body: { 143 | first_name: "Sam", 144 | last_name: "Smith", 145 | }, 146 | requestContext: { 147 | connectedAt: 123, 148 | connectionId: "abc123", 149 | }, 150 | }); 151 | ``` 152 | ### CloudWatch event 153 | 154 | ```js 155 | const event = createEvent("aws:cloudWatch", { 156 | "detail-type": "Something has been deleted.", 157 | "region": "us-east-1" 158 | }); 159 | ``` 160 | 161 | ### CloudWatchLog event 162 | 163 | ```js 164 | const event = createEvent("aws:cloudWatchLog", { 165 | awslogs: { 166 | data: "Some gzipped, then base64 encoded data", 167 | } 168 | }); 169 | ``` 170 | 171 | ### Alexa Skill event 172 | 173 | ```js 174 | const event = createEvent("aws:alexaSkill", { 175 | request: { 176 | type: "CanFulfillIntentRequest", 177 | }, 178 | context: { 179 | System: { 180 | device: { 181 | deviceId: "myDevice", 182 | }, 183 | }, 184 | }, 185 | } 186 | ``` 187 | 188 | ### Alexa SmartHome event 189 | ```js 190 | const event = createEvent("aws:alexaSmartHome", { 191 | payload: { 192 | switchControlAction: "TURN_OFF", 193 | }, 194 | } 195 | ``` 196 | 197 | ### IoT event 198 | ```js 199 | const event = createEvent("aws:iot", { 200 | this: { 201 | can: { 202 | be: "anything I want", 203 | }, 204 | } 205 | ``` 206 | 207 | ### Cognito Pool Event 208 | ```js 209 | const event = createEvent("aws:cognitoUserPool", { 210 | userName: "Aaron Stuyvenberg", 211 | } 212 | ``` 213 | -------------------------------------------------------------------------------- /globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.json' { 2 | const value: any 3 | export default value 4 | } 5 | -------------------------------------------------------------------------------- /lib/events/aws/alexa-skill-event-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "session": { 4 | "new": true, 5 | "sessionId": "amzn1.echo-api.session.123123123", 6 | "application": { 7 | "applicationId": "amzn1.ask.skill.123" 8 | }, 9 | "attributes": { 10 | "key": "this is an attribute" 11 | }, 12 | "user": { 13 | "userId": "amzn1.ask.account.abc", 14 | "accessToken": "Atza|AAAAAAAA...", 15 | "permissions": { 16 | "consentToken": "ZZZZZZZ..." 17 | } 18 | } 19 | }, 20 | "context": { 21 | "System": { 22 | "device": { 23 | "deviceId": "123456", 24 | "supportedInterfaces": { 25 | "AudioPlayer": {} 26 | } 27 | }, 28 | "application": { 29 | "applicationId": "amzn1.ask.skill.foobar" 30 | }, 31 | "user": { 32 | "userId": "amzn1.ask.account.user_name", 33 | "accessToken": "Atza|AAAAAAAA...", 34 | "permissions": { 35 | "consentToken": "ZZZZZZZ..." 36 | } 37 | }, 38 | "apiEndpoint": "https://api.amazonalexa.com", 39 | "apiAccessToken": "AxThk..." 40 | }, 41 | "AudioPlayer": { 42 | "playerActivity": "PLAYING", 43 | "token": "audioplayer-token", 44 | "offsetInMilliseconds": 0 45 | } 46 | }, 47 | "request": { 48 | "type": "LaunchRequest", 49 | "requestId": "1234-5678-abcd", 50 | "timestamp": "123123", 51 | "locale": "en-US" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/events/aws/alexa-smart-home-event-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "header": { 3 | "payloadVersion": "1", 4 | "namespace": "Control", 5 | "name": "SwitchOnOffRequest" 6 | }, 7 | "payload": { 8 | "switchControlAction": "TURN_ON", 9 | "appliance": { 10 | "additionalApplianceDetails": { 11 | "key2": "value2", 12 | "key1": "value1" 13 | }, 14 | "applianceId": "sampleId" 15 | }, 16 | "accessToken": "sampleAccessToken" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/events/aws/api-gateway-event-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "body": "", 3 | "path": "/test/hello", 4 | "headers": { 5 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 6 | "Accept-Encoding": "gzip, deflate, lzma, sdch, br", 7 | "Accept-Language": "en-US,en;q=0.8", 8 | "CloudFront-Forwarded-Proto": "https", 9 | "CloudFront-Is-Desktop-Viewer": "true", 10 | "CloudFront-Is-Mobile-Viewer": "false", 11 | "CloudFront-Is-SmartTV-Viewer": "false", 12 | "CloudFront-Is-Tablet-Viewer": "false", 13 | "CloudFront-Viewer-Country": "US", 14 | "Host": "wt6mne2s9k.execute-api.us-west-2.amazonaws.com", 15 | "Upgrade-Insecure-Requests": "1", 16 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48", 17 | "Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)", 18 | "X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==", 19 | "X-Forwarded-For": "192.168.100.1, 192.168.1.1", 20 | "X-Forwarded-Port": "443", 21 | "X-Forwarded-Proto": "https" 22 | }, 23 | "pathParameters": { 24 | "proxy": "hello" 25 | }, 26 | "multiValueHeaders": {}, 27 | "isBase64Encoded": false, 28 | "multiValueQueryStringParameters": {}, 29 | "requestContext": { 30 | "accountId": "123456789012", 31 | "resourceId": "us4z18", 32 | "stage": "test", 33 | "requestId": "41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9", 34 | "identity": { 35 | "accessKey": "", 36 | "apiKeyId": "", 37 | "cognitoIdentityPoolId": "", 38 | "accountId": "", 39 | "cognitoIdentityId": "", 40 | "caller": "", 41 | "apiKey": "", 42 | "sourceIp": "192.168.100.1", 43 | "cognitoAuthenticationType": "", 44 | "cognitoAuthenticationProvider": "", 45 | "userArn": "", 46 | "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48", 47 | "user": "" 48 | }, 49 | "path": "", 50 | "requestTimeEpoch": 0, 51 | "resourcePath": "/{proxy+}", 52 | "httpMethod": "GET", 53 | "apiId": "wt6mne2s9k" 54 | }, 55 | "resource": "/{proxy+}", 56 | "httpMethod": "GET", 57 | "queryStringParameters": { 58 | "name": "me" 59 | }, 60 | "stageVariables": { 61 | "stageVarName": "stageVarValue" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/events/aws/cloud-watch-event-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0", 3 | "id": "6a7e8feb-b491-4cf7-a9f1-bf3703467718", 4 | "detail-type": "EC2 Instance State-change Notification", 5 | "source": "aws.ec2", 6 | "account": "111122223333", 7 | "time": "2017-12-22T18:43:48Z", 8 | "region": "us-west-1", 9 | "resources": [ 10 | "arn:aws:ec2:us-west-1:123456789012:instance/ i-1234567890abcdef0" 11 | ], 12 | "detail": { 13 | "instance-id": " i-1234567890abcdef0", 14 | "state": "terminated" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/events/aws/cloud-watch-log-event-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "awslogs": { 3 | "data": "H4sIAIOmuFwAA8tJLVGvUqjKLFAoycgsBgAzQsm5DgAAAA==" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /lib/events/aws/cognito-user-pool-event-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "triggerSource": "string", 4 | "region": "us-east-1", 5 | "userPoolId": "abcd123", 6 | "userName": "myNameIsAJ", 7 | "callerContext": { 8 | "awsSdkVersion": "1", 9 | "clientId": "abc1234" 10 | }, 11 | "request": { 12 | "userAttributes": { 13 | "someAttr": "someValue" 14 | } 15 | }, 16 | "response": {} 17 | } 18 | -------------------------------------------------------------------------------- /lib/events/aws/dynamo-stream-event-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "eventID": "1", 5 | "eventVersion": "1.0", 6 | "dynamodb": { 7 | "Keys": { 8 | "Id": { 9 | "N": "101" 10 | } 11 | }, 12 | "NewImage": { 13 | "Message": { 14 | "S": "New item!" 15 | }, 16 | "Id": { 17 | "N": "101" 18 | } 19 | }, 20 | "StreamViewType": "NEW_AND_OLD_IMAGES", 21 | "SequenceNumber": "111", 22 | "SizeBytes": 26 23 | }, 24 | "awsRegion": "us-west-2", 25 | "eventName": "INSERT", 26 | "eventSourceARN": "arn:aws:dynamodb:us-east-1:123456789012:table/images", 27 | "eventSource": "aws:dynamodb" 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /lib/events/aws/kinesis-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "eventSource": "aws:kinesis", 5 | "eventVersion": "1.0", 6 | "eventID": "shardId-000000000000:49574408222142592692164662027912822768781511344925966338", 7 | "eventName": "aws:kinesis:record", 8 | "invokeIdentityArn": "arn:aws:iam::999999999999:role/lambda_kinesis", 9 | "awsRegion": "ap-northeast-1", 10 | "eventSourceARN": "arn:aws:kinesis:ap-northeast-1:999999999999:stream/test", 11 | "kinesis": { 12 | "kinesisSchemaVersion": "1.0", 13 | "partitionKey": "pk_7319", 14 | "sequenceNumber": "49574408222142592692164662027912822768781511344925966338", 15 | "data": "eyJldmVudF90eXBlIjoiZGFzaGJvYXJkX2V2ZW50cyIsImV2ZW50X3ZlcnNpb24iOjEsImV2ZW50X3RpbWVzdGFtcCI6MTQ5OTY3MjI0MjU0MCwiZXZlbnRfaWQiOiI5Yzc3NGFjMC02NTQyLTExZTctODg4OC1mNTQ4Y2Y2Mzg0NDMiLCJwYXlsb2FkIjp7InZpcnR1YWxfaWQiOjE5NzU1LCJib3hfaWQiOiJJTlRFLUVEOTYtRUQzNC05RjQyLTJDNkEiLCJ0eXBlIjo3LCJtZW1iZXJfaWQiOiIxNDk1MTkyMDkxOTcxIiwiZGV2aWNlX2lkIjoiMTQ6ZGQ6YTk6N2M6ZWE6YzQiLCJjYXRfaWQiOiIzIiwiY29udGVudCI6ODUyMjE1LCJjcmVhdGVkIjoxNDk5NjcyMjM4MDAwLCJzZWN1cml0eUxvZyI6W3siYXBwaWQiOjg1MjIxNSwibWFjIjoiMTQ6ZGQ6YTk6N2M6ZWE6YzQiLCJ0aW1lIjoxNDk5NjcyMjM4LCJuYW1lIjp7ImphX0pQIjoiVGFvYmFvIiwiZW5fVVMiOiJUYW9iYW8ifSwidXJsIjoiIiwiaWNvbiI6IiIsImNhdE5hbWUiOnsiamFfSlAiOiLjgrfjg6fjg4Pjg5Tjg7PjgrAv5bqD5ZGKIiwiZW5fVVMiOiJTaG9wcGluZyBvciBBZHZlcnRpc2VtZW50In0sImNhdF9pZCI6IjMifV19fQ==", 16 | "approximateArrivalTimestamp": 1499672242.6 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /lib/events/aws/s3-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "eventVersion": "2.0", 5 | "eventSource": "aws:s3", 6 | "awsRegion": "us-east-1", 7 | "eventTime": "2016-09-25T05:15:44.261Z", 8 | "eventName": "ObjectCreated:Put", 9 | "userIdentity": { 10 | "principalId": "AWS:AROAW5CA2KAGZPAWYRL7K:cli" 11 | }, 12 | "requestParameters": { 13 | "sourceIPAddress": "222.24.107.21" 14 | }, 15 | "responseElements": { 16 | "x-amz-request-id": "00093EEAA5C7G7F2", 17 | "x-amz-id-2": "9tTklyI/OEj4mco12PgsNksgxAV3KePn7WlNSq2rs+LXD3xFG0tlzgvtH8hClZzI963KYJgVnXw=" 18 | }, 19 | "s3": { 20 | "s3SchemaVersion": "1.0", 21 | "configurationId": "151dfa64-d57a-4383-85ac-620bce65f269", 22 | "bucket": { 23 | "name": "service-1474780369352-1", 24 | "ownerIdentity": { 25 | "principalId": "A3QLJ3P3P5QY05" 26 | }, 27 | "arn": "arn:aws:s3:::service-1474780369352-1" 28 | }, 29 | "object": { 30 | "key": "object", 31 | "size": 11, 32 | "eTag": "5eb63bbbe01eetd093cb22bb8f5acdc3", 33 | "sequencer": "0057E75D80IA35C3E0" 34 | } 35 | } 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /lib/events/aws/scheduled-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0", 3 | "id": "d77bcbc4-0b2b-4d45-9694-b1df99175cfb", 4 | "detail-type": "Scheduled Event", 5 | "source": "aws.events", 6 | "account": "123456789", 7 | "time": "2016-09-25T04:55:26Z", 8 | "region": "us-east-1", 9 | "resources": [ 10 | "arn:aws:events:us-east-1:123456789:rule/test-service-rule" 11 | ], 12 | "detail": {} 13 | } 14 | -------------------------------------------------------------------------------- /lib/events/aws/sns-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "EventSource": "aws:sns", 5 | "EventVersion": "1.0", 6 | "EventSubscriptionArn": "arn:aws:sns:us-east-1:123456789:service-1474781718017-1:fdaa4474-f0ff-4777-b1c4-79b96f5a504f", 7 | "Sns": { 8 | "Type": "Notification", 9 | "MessageId": "52ed5e3d-5fgf-56bf-923d-0e5c3b503c2a", 10 | "TopicArn": "arn:aws:sns:us-east-1:123456789:service-1474781718017-1", 11 | "Subject": "", 12 | "Message": "hello world", 13 | "Timestamp": "2016-09-25T05:37:51.150Z", 14 | "SignatureVersion": "1", 15 | "Signature": "V5QL/dhow62Thr9PXYsoHA7bOsDFkLdWZVd8D6LyptA6mrq0Mvldvj/XNtai3VaPp84G3bD2nQbiuwYbYpu9u9uHZ3PFMAxIcugV0dkOGWmYgKxSjPApItIoAgZyeH0HzcXHPEUXXO5dVT987jZ4eelD4hYLqBwgulSsECO9UDCdCS0frexiBHRGoLbWpX+2Nf2AJAL+olEEAAgxfiPEJ6J1ArzfvTFZXdd4XLAbrQe+4OeYD2dw39GBzGXQZemWDKf4d52kk+SwXY1ngaR4UfExQ10lDpKyfBVkSwroaq0pzbWFaxT2xrKIr4sk2s78BsPk0NBi55xA4k1E4tr9Pg==", 16 | "SigningCertUrl": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-b95095beb82e8f6a0e6b3aafc7f4149a.pem", 17 | "UnsubscribeUrl": "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:123456789:service-1474781718017-1:fdaa4474-f0ff-4777-b1c4-79b96f5a504f", 18 | "MessageAttributes": {} 19 | } 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /lib/events/aws/sqs-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", 5 | "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...", 6 | "body": "test", 7 | "attributes": { 8 | "ApproximateReceiveCount": "1", 9 | "SentTimestamp": "1545082649183", 10 | "SenderId": "AIDAIENQZJOLO23YVJ4VO", 11 | "ApproximateFirstReceiveTimestamp": "1545082649185" 12 | }, 13 | "messageAttributes": {}, 14 | "md5OfBody": "098f6bcd4621d373cade4e832627b4f6", 15 | "eventSource": "aws:sqs", 16 | "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue", 17 | "awsRegion": "us-east-2" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /lib/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import createEvent from "./index"; 3 | 4 | describe("creating a new SNS event", () => { 5 | it("should return a valid event", () => { 6 | const event = createEvent("aws:sns", { 7 | Records: [ 8 | { 9 | Sns: { 10 | Message: "trigger-email", 11 | }, 12 | }, 13 | ], 14 | } as any); 15 | expect(event.Records[0].Sns.Message).to.equal("trigger-email"); 16 | expect(event.Records[0].Sns.Type).to.equal("Notification"); 17 | }); 18 | }); 19 | 20 | describe("createSqsEvent()", () => { 21 | it("should return SQS mocked event", () => { 22 | const event = createEvent("aws:sqs", { 23 | Records: [ 24 | { 25 | body: JSON.stringify({ 26 | foo: "bar", 27 | }), 28 | }, 29 | ], 30 | } as any); 31 | 32 | expect(event.Records[0].body).to.equal("{\"foo\":\"bar\"}"); 33 | expect(event.Records[0].eventSource).to.equal("aws:sqs"); 34 | }); 35 | }); 36 | 37 | describe("createApigEvent()", () => { 38 | it("should return APIG mocked event", () => { 39 | const event = createEvent("aws:apiGateway", { 40 | body: JSON.stringify({ 41 | first_name: "Sam", 42 | last_name: "Smith", 43 | }), 44 | } as any); 45 | const parsedBody = JSON.parse(event.body || ""); 46 | 47 | expect(parsedBody.first_name).to.equal("Sam"); 48 | expect(parsedBody.last_name).to.equal("Smith"); 49 | expect(event.httpMethod).to.equal("GET"); 50 | }); 51 | }); 52 | 53 | describe("createWebsocketEvent()", () => { 54 | it("should return websocket mocked event", () => { 55 | const event = createEvent("aws:websocket", { 56 | body: JSON.stringify({ 57 | first_name: "Sam", 58 | last_name: "Smith", 59 | }), 60 | requestContext: { 61 | connectedAt: 123, 62 | connectionId: "abc123", 63 | }, 64 | } as any); 65 | const parsedBody = JSON.parse(event.body || ""); 66 | 67 | expect(parsedBody.first_name).to.equal("Sam"); 68 | expect(parsedBody.last_name).to.equal("Smith"); 69 | expect(event.requestContext.connectedAt).to.equal(123); 70 | expect(event.requestContext.connectionId).to.equal("abc123"); 71 | }); 72 | }); 73 | 74 | describe("createS3Event()", () => { 75 | it("should return S3 mocked event", () => { 76 | const event = createEvent("aws:s3", { 77 | Records: [ 78 | { 79 | s3: { 80 | bucket: { 81 | name: "my-bucket-name", 82 | }, 83 | object: { 84 | key: "object-key", 85 | }, 86 | }, 87 | }, 88 | ], 89 | } as any); 90 | 91 | expect(event.Records[0].s3.bucket.name).to.equal("my-bucket-name"); 92 | expect(event.Records[0].s3.object.key).to.equal("object-key"); 93 | expect(event.Records[0].eventName).to.equal("ObjectCreated:Put"); 94 | }); 95 | 96 | it("should return S3 mocked event without side-effect", () => { 97 | const event = createEvent("aws:s3", { 98 | Records: [ 99 | { 100 | s3: { 101 | bucket: { 102 | name: "my-bucket-name", 103 | }, 104 | object: { 105 | key: "object-key", 106 | }, 107 | }, 108 | }, 109 | ], 110 | } as any); 111 | 112 | const event2 = createEvent("aws:s3", { 113 | Records: [ 114 | { 115 | s3: { 116 | bucket: { 117 | name: "my-bucket-name", 118 | }, 119 | object: { 120 | key: "object-key-2", 121 | }, 122 | }, 123 | }, 124 | ], 125 | } as any); 126 | 127 | expect(event.Records[0].s3.bucket.name).to.equal("my-bucket-name"); 128 | expect(event.Records[0].s3.object.key).to.equal("object-key"); 129 | expect(event2.Records[0].s3.object.key).to.equal("object-key-2"); 130 | expect(event.Records[0].eventName).to.equal("ObjectCreated:Put"); 131 | }); 132 | }); 133 | 134 | describe("createScheduledEvent()", () => { 135 | it("should return Scheduled mocked event", () => { 136 | const event = createEvent("aws:scheduled", { 137 | region: "us-west-2", 138 | } as any); 139 | 140 | expect(event.region).to.equal("us-west-2"); 141 | expect(event["detail-type"]).to.equal("Scheduled Event"); 142 | }); 143 | }); 144 | 145 | describe("createKinesisEvent()", () => { 146 | it("should return Kinesis mocked event", () => { 147 | const event = createEvent("aws:kinesis", { 148 | Records: [ 149 | { 150 | kinesis: { 151 | data: Buffer.from("kinesis test").toString("base64"), 152 | }, 153 | }, 154 | ], 155 | } as any); 156 | 157 | expect( 158 | Buffer.from(event.Records[0].kinesis.data, "base64").toString("ascii"), 159 | ).to.equal("kinesis test"); 160 | }); 161 | }); 162 | 163 | describe("createCloudWatchEvent()", () => { 164 | it("should return a valid event", () => { 165 | const event = createEvent("aws:cloudWatch", { 166 | "detail-type": "Something has been deleted.", 167 | "region": "us-east-1", 168 | } as any); 169 | expect(event["detail-type"]).to.equal("Something has been deleted."); 170 | expect(event.region).to.equal("us-east-1"); 171 | }); 172 | }); 173 | 174 | describe("createCloudWatchLogEvent()", () => { 175 | it("should return a valid event", () => { 176 | const event = createEvent("aws:cloudWatchLog", { 177 | awslogs: { 178 | data: "Some gzipped, then base64 encoded data", 179 | }, 180 | }) as any; 181 | expect(event.awslogs.data).to.equal( 182 | "Some gzipped, then base64 encoded data", 183 | ); 184 | }); 185 | }); 186 | 187 | describe("createAlexaSkillEvent()", () => { 188 | it("should return a valid event", () => { 189 | const event = createEvent("aws:alexaSkill", { 190 | request: { 191 | type: "CanFulfillIntentRequest", 192 | }, 193 | context: { 194 | System: { 195 | device: { 196 | deviceId: "myDevice", 197 | }, 198 | }, 199 | }, 200 | } as any); 201 | expect(event.request.type).to.equal("CanFulfillIntentRequest"); 202 | expect(event.context.System.device.deviceId).to.equal("myDevice"); 203 | }); 204 | }); 205 | 206 | describe("createAlexaSmartHomeEvent()", () => { 207 | it("should return a valid event", () => { 208 | const event = createEvent("aws:alexaSmartHome", { 209 | payload: { 210 | switchControlAction: "TURN_OFF", 211 | }, 212 | } as any); 213 | expect(event.payload.switchControlAction).to.equal("TURN_OFF"); 214 | }); 215 | }); 216 | 217 | describe("createIotEvent()", () => { 218 | it("should return a valid event", () => { 219 | const event = createEvent("aws:iot", { 220 | this: { 221 | can: { 222 | be: "anything I want", 223 | }, 224 | }, 225 | } as any); 226 | expect(event.this.can.be).to.equal("anything I want"); 227 | }); 228 | }); 229 | 230 | describe("createCognitoPoolEvent()", () => { 231 | it("should return a valid event", () => { 232 | const event = createEvent("aws:cognitoUserPool", { 233 | userName: "notAJ", 234 | } as any); 235 | expect(event.userName).to.eql("notAJ"); 236 | }); 237 | }); 238 | -------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | import { merge, cloneDeep, Dictionary } from "lodash"; 2 | import { 3 | APIGatewayEvent, 4 | ScheduledEvent, 5 | S3Event, 6 | KinesisStreamEvent, 7 | DynamoDBStreamEvent, 8 | SQSEvent, 9 | SNSEvent, 10 | CloudWatchLogsEvent, 11 | CognitoUserPoolEvent, 12 | } from "aws-lambda"; 13 | import { 14 | AlexaSmartHomeEvent, 15 | AlexaSkillEvent, 16 | CloudWatchEvent, 17 | } from "aws-lambda"; 18 | 19 | import snsTemplate from "./events/aws/sns-template.json"; 20 | import sqsTemplate from "./events/aws/sqs-template.json"; 21 | import apiGatewayTemplate from "./events/aws/api-gateway-event-template.json"; 22 | import scheduledTemplate from "./events/aws/scheduled-template.json"; 23 | import s3Template from "./events/aws/s3-template.json"; 24 | import kinesisTemplate from "./events/aws/kinesis-template.json"; 25 | import dynamoTemplate from "./events/aws/dynamo-stream-event-template.json"; 26 | import cloudwatchLogEventTemplate from "./events/aws/cloud-watch-log-event-template.json"; 27 | import alexaSmartHomeEventTemplate from "./events/aws/alexa-smart-home-event-template.json"; 28 | import alexaSkillEventTemplate from "./events/aws/alexa-skill-event-template.json"; 29 | import cloudWatchEventTemplate from "./events/aws/cloud-watch-event-template.json"; 30 | import cognitoUserPoolEventTemplate from "./events/aws/cognito-user-pool-event-template.json"; 31 | 32 | type DeepPartial = T extends object 33 | ? { 34 | [P in keyof T]?: DeepPartial; 35 | } 36 | : T; 37 | 38 | export const dictionary = { 39 | "aws:sns": snsTemplate as DeepPartial, 40 | "aws:sqs": sqsTemplate as DeepPartial, 41 | "aws:apiGateway": apiGatewayTemplate as DeepPartial, 42 | "aws:scheduled": scheduledTemplate as DeepPartial, 43 | "aws:s3": s3Template as DeepPartial, 44 | "aws:kinesis": kinesisTemplate as DeepPartial, 45 | "aws:dynamo": dynamoTemplate as DeepPartial, 46 | "aws:cloudWatchLog": 47 | cloudwatchLogEventTemplate as DeepPartial, 48 | "aws:alexaSmartHome": 49 | alexaSmartHomeEventTemplate as DeepPartial, 50 | "aws:alexaSkill": alexaSkillEventTemplate as DeepPartial, 51 | "aws:cloudWatch": cloudWatchEventTemplate as DeepPartial, 52 | "aws:iot": {} as any, 53 | "aws:cognitoUserPool": 54 | cognitoUserPoolEventTemplate as DeepPartial, 55 | "aws:websocket": apiGatewayTemplate as DeepPartial, // Websockets are included in APIG typedef: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/32855/files 56 | }; 57 | 58 | export default function createEvent( 59 | eventType: T, 60 | body: typeof dictionary[T] 61 | ): typeof dictionary[T] { 62 | const event = dictionary[eventType]; 63 | let generatedEvent = {}; 64 | if (event) { 65 | generatedEvent = merge(cloneDeep(event), body); 66 | } 67 | return generatedEvent; 68 | } 69 | -------------------------------------------------------------------------------- /lib/types/aws-lambda/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aws-lambda' { 2 | export interface AlexaSmartHomeEvent { 3 | header: { [name: string]: string } 4 | payload: { 5 | switchControlAction: string 6 | appliance: { 7 | additionalApplianceDetails: { [name: string]: string } 8 | applianceId: string 9 | } 10 | accessToken: string 11 | } 12 | } 13 | 14 | export interface AlexaSkillEvent { 15 | request: { 16 | type: string 17 | } 18 | version: string 19 | session: AlexaSkillSession 20 | context: AlexaSkillContext 21 | } 22 | 23 | export interface AlexaSkillSession { 24 | new: boolean 25 | sessionId: string 26 | application: { 27 | applicationId: string 28 | } 29 | attributes: { 30 | [name: string]: string 31 | } 32 | user: AlexaSkillUser 33 | } 34 | 35 | export interface AlexaSkillContext { 36 | System: { 37 | device: { 38 | deviceId: string 39 | supportedInterfaces: { 40 | AudioPlayer: any 41 | } 42 | } 43 | application: { 44 | applicationId: string 45 | } 46 | user: AlexaSkillUser 47 | apiEndpoint: string 48 | apiAccessToken: string 49 | } 50 | AudioPlayer: { 51 | playerActivity: string 52 | token: string 53 | offsetInMilliseconds: number 54 | } 55 | } 56 | 57 | export interface AlexaSkillUser { 58 | userId: string 59 | accessToken: string 60 | permissions: { 61 | consentToken: string 62 | } 63 | } 64 | 65 | export interface AlexaSkillRequest { 66 | type: string 67 | requestId: string 68 | timestamp: string 69 | locale: string 70 | } 71 | 72 | export interface CloudWatchEvent { 73 | version: string 74 | id: string 75 | "detail-type": string 76 | source: string 77 | account: string 78 | time: string 79 | region: string 80 | resources: string[] 81 | detail: { 82 | "instance-id": string 83 | state: string 84 | } 85 | } 86 | } 87 | export {} 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@serverless/event-mocks", 3 | "version": "1.1.1", 4 | "description": "Event Mocks is a simple library designed to generate simple AWS events for testing and automation purposes.", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "build": "tsc -p ./", 8 | "lint": "tslint -p tsconfig.json", 9 | "lintfix": "tslint -p tsconfig.json --fix", 10 | "test": "ts-mocha lib/**/*.spec.ts" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "." 15 | }, 16 | "author": "Serverless, Inc.", 17 | "license": "Apache-2.0", 18 | "devDependencies": { 19 | "@types/aws-lambda": "^8.10.115", 20 | "@types/chai": "^4.3.5", 21 | "@types/mocha": "^5.2.7", 22 | "@types/node": "^11.15.54", 23 | "aws-lambda": "^0.1.2", 24 | "chai": "^4.3.7", 25 | "mocha": "^6.2.3", 26 | "ts-mocha": "^6.0.0", 27 | "ts-node": "^8.10.2", 28 | "tslint": "^5.20.1", 29 | "typescript": "^3.9.10" 30 | }, 31 | "dependencies": { 32 | "@types/lodash": "^4.14.194", 33 | "lodash": "^4.17.21" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "sourceRoot": "./lib", 5 | "moduleResolution": "node", 6 | "target": "es5", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "outDir": "./dist", 10 | "strict": true, 11 | "esModuleInterop": true, 12 | "resolveJsonModule": true 13 | }, 14 | "typeRoots": [ 15 | "node_modules/@types", 16 | "./types" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "jsRules": {}, 7 | "rules": { 8 | "ordered-imports": false, 9 | "max-line-length": [false], 10 | "no-string-literal": false, 11 | "object-literal-sort-keys": false, 12 | "no-empty": false, 13 | "no-unused-expression": false, 14 | "require-jsdoc": false, 15 | "no-trailing-whitespace": false, 16 | "member-ordering": false, 17 | "arrow-parens": false, 18 | "no-console": false, 19 | "no-empty-interface": false, 20 | "no-var-requires": false, 21 | "quotemark": [true, "double"], 22 | "semicolon": [true, "always"] 23 | }, 24 | "rulesDirectory": [], 25 | "plugins": [ 26 | { 27 | "name": "typescript-tslint-plugin", 28 | "alwaysShowRuleFailuresAsWarnings": false, 29 | "ignoreDefinitionFiles": true, 30 | "configFile": "../tslint.json", 31 | "suppressWhileTypeErrorsPresent": false, 32 | "mockTypeScriptVersion": false 33 | } 34 | ] 35 | } 36 | --------------------------------------------------------------------------------