UNPKG

10.8 kBJavaScriptView Raw
1'use strict'
2
3const assert = require('chai').assert
4const path = require('path')
5const fs = require('fs-extra')
6const spawn = require('child_process').spawn
7const execSync = require('child_process').execSync
8const nodeLambdaPath = path.join(__dirname, '..', 'bin', 'node-lambda')
9
10/* global before, after, describe, it */
11// The reason for specifying the node command in this test is to support Windows.
12describe('bin/node-lambda', () => {
13 describe('node-lambda run', () => {
14 const _testMain = (expectedValues, done) => {
15 const run = spawn('node', [
16 nodeLambdaPath, 'run',
17 '--handler', '__test.handler',
18 '--eventFile', 'event.json'
19 ])
20 let stdoutString = ''
21 let stderrString = ''
22 run.stdout.on('data', (data) => {
23 stdoutString += data.toString().replace(/\r|\n/g, '')
24 })
25 run.stderr.on('data', (data) => {
26 stderrString += data.toString().replace(/\r|\n/g, '')
27 })
28
29 run.on('exit', (code) => {
30 if (expectedValues.stdoutRegExp) {
31 assert.match(stdoutString, expectedValues.stdoutRegExp)
32 }
33 if (expectedValues.stderrRegExp) {
34 assert.match(stderrString, expectedValues.stderrRegExp)
35 }
36 assert.equal(code, expectedValues.exitCode)
37 done()
38 })
39 }
40
41 const _generateEventFile = (eventObj) => {
42 fs.writeFileSync('event.json', JSON.stringify(eventObj))
43 }
44
45 before(() => {
46 execSync(`node ${nodeLambdaPath} setup`)
47 fs.copy(path.join(__dirname, 'handler', 'index.js'), '__test.js')
48 })
49
50 after(() => {
51 [
52 '.env',
53 'context.json',
54 'event.json',
55 'deploy.env',
56 'event_sources.json',
57 '__test.js'
58 ].forEach((file) => fs.unlinkSync(file))
59 })
60
61 describe('node-lambda run (Handler only sync processing)', () => {
62 const eventObj = {
63 asyncTest: false,
64 callbackWaitsForEmptyEventLoop: true // True is the default value of Lambda
65 }
66
67 it('`node-lambda run` exitCode is `0` (callback(null))', (done) => {
68 _generateEventFile(Object.assign(eventObj, {
69 callbackCode: 'callback(null);'
70 }))
71 _testMain({ stdoutRegExp: /Success:$/, exitCode: 0 }, done)
72 })
73
74 it('`node-lambda run` exitCode is `0` (callback(null, "text"))', (done) => {
75 _generateEventFile(Object.assign(eventObj, {
76 callbackCode: 'callback(null, "text");'
77 }))
78 _testMain({ stdoutRegExp: /Success:"text"$/, exitCode: 0 }, done)
79 })
80
81 it('`node-lambda run` exitCode is `255` (callback(new Error("e")))', (done) => {
82 _generateEventFile(Object.assign(eventObj, {
83 callbackCode: 'callback(new Error("e"));'
84 }))
85 _testMain({ stdoutRegExp: /Error: Error: e$/, exitCode: 255 }, done)
86 })
87 })
88
89 describe('node-lambda run (Handler includes async processing)', () => {
90 describe('callbackWaitsForEmptyEventLoop = true', function () {
91 this.timeout(5000) // give it time to setTimeout
92
93 const eventObj = {
94 asyncTest: true,
95 callbackWaitsForEmptyEventLoop: true
96 }
97
98 it('`node-lambda run` exitCode is `0` (callback(null))', (done) => {
99 _generateEventFile(Object.assign(eventObj, {
100 callbackCode: 'callback(null);'
101 }))
102 _testMain({ stdoutRegExp: /Success:sleep 3500 msec$/, exitCode: 0 }, done)
103 })
104
105 it('`node-lambda run` exitCode is `0` (callback(null, "text"))', (done) => {
106 _generateEventFile(Object.assign(eventObj, {
107 callbackCode: 'callback(null, "text");'
108 }))
109 _testMain({ stdoutRegExp: /Success:"text"sleep 3500 msec$/, exitCode: 0 }, done)
110 })
111
112 it('`node-lambda run` exitCode is `255` (callback(new Error("e")))', (done) => {
113 _generateEventFile(Object.assign(eventObj, {
114 callbackCode: 'callback(new Error("e"));'
115 }))
116 _testMain({ stdoutRegExp: /Error: Error: esleep 3500 msec$/, exitCode: 255 }, done)
117 })
118 })
119
120 describe('callbackWaitsForEmptyEventLoop = false', () => {
121 const eventObj = {
122 asyncTest: true,
123 callbackWaitsForEmptyEventLoop: false
124 }
125
126 it('`node-lambda run` exitCode is `0` (callback(null))', (done) => {
127 _generateEventFile(Object.assign(eventObj, {
128 callbackCode: 'callback(null);'
129 }))
130 _testMain({ stdoutRegExp: /Success:$/, exitCode: 0 }, done)
131 })
132
133 it('`node-lambda run` exitCode is `0` (callback(null, "text"))', (done) => {
134 _generateEventFile(Object.assign(eventObj, {
135 callbackCode: 'callback(null, "text");'
136 }))
137 _testMain({ stdoutRegExp: /Success:"text"$/, exitCode: 0 }, done)
138 })
139
140 it('`node-lambda run` exitCode is `255` (callback(new Error("e")))', (done) => {
141 _generateEventFile(Object.assign(eventObj, {
142 callbackCode: 'callback(new Error("e"));'
143 }))
144 _testMain({ stdoutRegExp: /Error: Error: e$/, exitCode: 255 }, done)
145 })
146 })
147 })
148
149 describe('node-lambda run (Runtime is not supported)', () => {
150 const eventObj = {
151 asyncTest: false,
152 callbackWaitsForEmptyEventLoop: true // True is the default value of Lambda
153 }
154
155 before(() => {
156 process.env.AWS_RUNTIME = 'test'
157 })
158 after(() => {
159 process.env.AWS_RUNTIME = 'nodejs14.x'
160 })
161
162 it('`node-lambda run` exitCode is `254` (callback(null))', (done) => {
163 _generateEventFile(Object.assign(eventObj, {
164 callbackCode: 'callback(null);'
165 }))
166 _testMain({
167 stderrRegExp: /^Runtime \[test\] is not supported\.$/,
168 exitCode: 254
169 }, done)
170 })
171 })
172
173 describe('node-lambda run (Multiple events))', () => {
174 const eventObj = [{
175 asyncTest: false,
176 callbackWaitsForEmptyEventLoop: true,
177 callbackCode: 'callback(null);',
178 no: 1
179 }, {
180 asyncTest: false,
181 callbackWaitsForEmptyEventLoop: true,
182 callbackCode: 'callback(null);',
183 no: 2
184 }, {
185 asyncTest: false,
186 callbackWaitsForEmptyEventLoop: true,
187 callbackCode: 'callback(null);',
188 no: 3
189 }]
190
191 it('`node-lambda run` exitCode is `0`', function (done) {
192 this.timeout(10000) // give it time to multiple executions
193 _generateEventFile(eventObj)
194 _testMain({
195 stdoutRegExp: /no: 1.+no: 2.+no: 3.+Success:/,
196 exitCode: 0
197 }, done)
198 })
199 })
200
201 describe('node-lambda run (disable Multiple events))', () => {
202 const eventObj = [{
203 asyncTest: false,
204 callbackWaitsForEmptyEventLoop: true,
205 callbackCode: 'callback(null);',
206 no: 1
207 }, {
208 asyncTest: false,
209 callbackWaitsForEmptyEventLoop: true,
210 callbackCode: 'callback(null);',
211 no: 2
212 }, {
213 asyncTest: false,
214 callbackWaitsForEmptyEventLoop: true,
215 callbackCode: 'callback(null);',
216 no: 3
217 }]
218
219 it('`node-lambda run` exitCode is `0`', function (done) {
220 this.timeout(10000) // give it time to multiple executions
221
222 _generateEventFile(eventObj)
223 const run = spawn('node', [
224 nodeLambdaPath, 'run',
225 '--handler', 'index.handler',
226 '--eventFile', 'event.json',
227 '-M', 'false'
228 ])
229 let stdoutString = ''
230 run.stdout.on('data', (data) => {
231 stdoutString += data.toString().replace(/\r|\n|\s/g, '')
232 })
233
234 run.on('exit', (code) => {
235 const expected = 'Runningindex.handler==================================event' +
236 '[{asyncTest:false,callbackWaitsForEmptyEventLoop:true,callbackCode:\'callback(null);\',no:1},' +
237 '{asyncTest:false,callbackWaitsForEmptyEventLoop:true,callbackCode:\'callback(null);\',no:2},' +
238 '{asyncTest:false,callbackWaitsForEmptyEventLoop:true,callbackCode:\'callback(null);\',no:3}]' +
239 '==================================Stoppingindex.handlerSuccess:'
240
241 assert.equal(stdoutString, expected)
242 assert.equal(code, 0)
243 done()
244 })
245 })
246 })
247
248 describe('node-lambda run (API Gateway events))', () => {
249 const eventObj = {
250 asyncTest: false,
251 callbackWaitsForEmptyEventLoop: true,
252 callbackCode: 'callback(null);'
253 }
254
255 it('`node-lambda run` exitCode is `0`', function (done) {
256 _generateEventFile(eventObj)
257 const run = spawn('node', [
258 nodeLambdaPath, 'run',
259 '--handler', 'index.handler',
260 '--eventFile', 'event.json',
261 '--apiGateway'
262 ])
263 let stdoutString = ''
264 run.stdout.on('data', (data) => {
265 stdoutString += data.toString().replace(/\r|\n|\s/g, '')
266 })
267
268 run.on('exit', (code) => {
269 const expected = '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!EmulateonlythebodyoftheAPIGatewayevent.' +
270 '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Runningindex.handler==================================event' +
271 '{body:\'{"asyncTest":false,"callbackWaitsForEmptyEventLoop":true,"callbackCode":"callback(null);"}\'}' +
272 '==================================Stoppingindex.handlerSuccess:'
273 assert.equal(stdoutString, expected)
274 assert.equal(code, 0)
275 done()
276 })
277 })
278 })
279 })
280
281 describe('node-lambda duplicate check of short option', () => {
282 const duplicateCheckTestFunc = (type, done) => {
283 const cmd = spawn('node', [nodeLambdaPath, type, '-h'])
284 let stdoutString = ''
285 cmd.stdout.on('data', (data) => {
286 stdoutString += data.toString()
287 })
288
289 cmd.on('exit', (code) => {
290 assert.equal(code, 0)
291
292 const shortOptions = stdoutString.split('\n').filter(line => {
293 return line.match(/^\s+-/)
294 }).map(line => {
295 return line.split(/\s+/)[1]
296 })
297 const uniqueShortOptions = shortOptions.filter((option, index, array) => {
298 return array.indexOf(option) === index
299 })
300 assert.equal(shortOptions.length, uniqueShortOptions.length)
301 done()
302 })
303 }
304
305 ['deploy', 'run', 'setup'].forEach(type => {
306 it(`cmd:${type}`, (done) => {
307 duplicateCheckTestFunc(type, done)
308 })
309 })
310 })
311
312 describe('node-lambda --version', () => {
313 const packageJson = require(path.join(__dirname, '..', 'package.json'))
314 it('The current version is displayed', () => {
315 const ret = execSync(`node ${nodeLambdaPath} --version`)
316 assert.equal(ret.toString().trim(), packageJson.version)
317 })
318 })
319})