Skip to content

Commit 574dcc4

Browse files
committed
Added event source mocks for @events, queues, @scheduled, @tables-streams
1 parent cf44fe0 commit 574dcc4

File tree

4 files changed

+98
-4
lines changed

4 files changed

+98
-4
lines changed

changelog.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Architect Lambda invoker plugin
2+
3+
---
4+
5+
## [0.1.0] 2022-03-27
6+
7+
### Added
8+
9+
- Added event source mocks for `@events`, `queues`, `@scheduled`, `@tables-streams`
10+
- Added warning for empty payloads on all invocations of pragmas not noted
11+
12+
---

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"lint": "eslint . --fix"
99
},
1010
"engines": {
11-
"node": ">=14"
11+
"node": ">=14.17.0"
1212
},
1313
"files": [
1414
"src/*"

src/event-mocks.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
let { randomUUID } = require('crypto')
2+
3+
// Sit back and enjoy AWS's hilarious mix of Pascal-case, camel-case, and lowcase, sometimes even within the same event sources
4+
module.exports = {
5+
events,
6+
queues,
7+
scheduled,
8+
tablesStreams,
9+
}
10+
11+
function events (Message) {
12+
return { Records: [ { Sns: { Message } } ] } // this is fine
13+
}
14+
15+
function queues (body) {
16+
return { Records: [ { body } ] } // also fine
17+
}
18+
19+
function scheduled () {
20+
return {
21+
version: 0,
22+
id: randomUUID(),
23+
'detail-type': 'Scheduled Event',
24+
source: 'aws.events',
25+
account: 123456789012,
26+
time: new Date().toISOString(),
27+
region: 'Sandbox',
28+
resources: [
29+
'arn:architect-sandbox'
30+
],
31+
detail: {}
32+
}
33+
}
34+
35+
function tablesStreams (eventName) {
36+
return {
37+
Records: [
38+
{
39+
eventID: randomUUID().replace(/-/g, '').substr(0, 32),
40+
eventName,
41+
eventVersion: '1.1',
42+
eventSource: 'aws:dynamodb',
43+
awsRegion: 'Sandbox',
44+
dynamodb: {
45+
ApproximateCreationDateTime: new Date() / 1000,
46+
// Keys + NewImage are in DynamoDB JSON, perhaps we can mock transform that later
47+
Keys: { NOT_MOCKED: true },
48+
NewImage: { NOT_MOCKED: true },
49+
SequenceNumber: 0,
50+
SizeBytes: 0,
51+
StreamViewType: 'NEW_AND_OLD_IMAGES'
52+
},
53+
eventSourceARN: 'arn:architect-sandbox'
54+
}
55+
]
56+
}
57+
}

src/index.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ let { updater } = require('@architect/utils')
44
let { prompt } = require('enquirer')
55
let colors = require('ansi-colors')
66
let update = updater('Invoker')
7+
let mock = require('./event-mocks')
78

89
module.exports = {
910
sandbox: {
1011
start: async ({ inventory: { inv }, invoke }) => {
12+
start()
1113
update.status(`Event invoker started, select an event to invoke by pressing 'i'`)
1214
let { cwd, preferences } = inv._project
1315
let jsonMocks = join(cwd, 'sandbox-invoke-mocks.json')
@@ -51,7 +53,7 @@ module.exports = {
5153
return
5254
}
5355

54-
let payload = {}
56+
let userPayload = {}
5557
let mocks
5658
let mockName = 'empty'
5759

@@ -78,7 +80,8 @@ module.exports = {
7880
let { pragma, name } = events[lambda]
7981

8082
// Present options for mocks (if any)
81-
if (mocks?.[pragma]?.[name]) {
83+
let mockable = ![ 'scheduled', 'tables-streams' ].includes(pragma)
84+
if (mocks?.[pragma]?.[name] && mockable) {
8285
let selection = await prompt({
8386
type: 'select',
8487
name: 'mock',
@@ -87,7 +90,27 @@ module.exports = {
8790
choices: [ ...Object.keys(mocks[pragma][name]), 'empty' ],
8891
}, options)
8992
mockName = selection.mock
90-
payload = mocks[pragma][name][mockName] || {}
93+
userPayload = mocks[pragma][name][mockName] || {}
94+
}
95+
96+
let payload
97+
/**/ if (pragma === 'events') payload = mock.events(userPayload)
98+
else if (pragma === 'queues') payload = mock.queues(userPayload)
99+
else if (pragma === 'scheduled') payload = mock.scheduled()
100+
else if (pragma === 'tables-streams') {
101+
let { eventName } = await prompt({
102+
type: 'select',
103+
name: 'eventName',
104+
message: 'Which kind of Dynamo Stream event do you want to invoke?',
105+
choices: [ 'INSERT', 'MODIFY', 'REMOVE' ]
106+
})
107+
payload = mock.tablesStreams(eventName)
108+
}
109+
else {
110+
if (!Object.keys(userPayload).length) {
111+
update.warning('Warning: real AWS event sources generally do not emit empty payloads')
112+
}
113+
payload = userPayload
91114
}
92115

93116
// Wrap it up and invoke!
@@ -119,6 +142,8 @@ function start () {
119142
process.stdin.resume()
120143
}
121144
}
145+
146+
// Super important to pause stdin, or Sandbox will hang forever in tests
122147
function end () {
123148
if (process.stdin.isTTY) {
124149
process.stdin.pause()

0 commit comments

Comments
 (0)