1 | 'use strict'
|
2 |
|
3 | const assert = require('chai').assert
|
4 | const path = require('path')
|
5 | const fs = require('fs-extra')
|
6 | const spawn = require('child_process').spawn
|
7 | const execSync = require('child_process').execSync
|
8 | const nodeLambdaPath = path.join(__dirname, '..', 'bin', 'node-lambda')
|
9 |
|
10 |
|
11 |
|
12 | describe('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
|
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)
|
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
|
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)
|
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)
|
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 | })
|