serverless-offline 9.1.7 → 9.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/package.json +4 -10
  2. package/src/ServerlessOffline.js +3 -3
  3. package/src/lambda/LambdaFunction.js +1 -4
  4. package/src/lambda/handler-runner/HandlerRunner.js +3 -11
  5. package/src/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +9 -6
  6. package/src/lambda/handler-runner/child-process-runner/childProcessHelper.js +8 -5
  7. package/src/lambda/handler-runner/go-runner/GoRunner.js +3 -1
  8. package/src/lambda/handler-runner/in-process-runner/InProcessRunner.js +16 -34
  9. package/src/lambda/handler-runner/in-process-runner/aws-lambda-ric/UserFunction.js +359 -0
  10. package/src/lambda/{__tests__/fixtures → handler-runner/in-process-runner/aws-lambda-ric}/package.json +0 -0
  11. package/src/lambda/handler-runner/python-runner/PythonRunner.js +17 -19
  12. package/src/lambda/handler-runner/ruby-runner/RubyRunner.js +4 -1
  13. package/src/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +5 -6
  14. package/src/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +8 -5
  15. package/src/lambda/__tests__/LambdaContext.test.js +0 -30
  16. package/src/lambda/__tests__/LambdaFunction.test.js +0 -196
  17. package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsJSONObject.fixture.js +0 -47
  18. package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsNativeString.fixture.js +0 -46
  19. package/src/lambda/__tests__/fixtures/Lambda/package.json +0 -3
  20. package/src/lambda/__tests__/fixtures/lambdaFunction.fixture.js +0 -145
  21. package/src/lambda/__tests__/routes/invocations/InvocationsController.test.js +0 -42
  22. package/src/utils/__tests__/createUniqueId.test.js +0 -18
  23. package/src/utils/__tests__/formatToClfTime.test.js +0 -14
  24. package/src/utils/__tests__/generateHapiPath.test.js +0 -46
  25. package/src/utils/__tests__/lowerCaseKeys.test.js +0 -30
  26. package/src/utils/__tests__/parseHeaders.test.js +0 -13
  27. package/src/utils/__tests__/parseMultiValueHeaders.test.js +0 -24
  28. package/src/utils/__tests__/parseMultiValueQueryStringParameters.test.js +0 -159
  29. package/src/utils/__tests__/parseQueryStringParameters.test.js +0 -15
  30. package/src/utils/__tests__/splitHandlerPathAndName.test.js +0 -54
  31. package/src/utils/__tests__/unflatten.test.js +0 -32
@@ -2,9 +2,10 @@ import { spawn } from 'node:child_process'
2
2
  import { EOL, platform } from 'node:os'
3
3
  import { delimiter, dirname, join, relative, resolve } from 'node:path'
4
4
  import process, { cwd } from 'node:process'
5
- import readline from 'node:readline'
5
+ import { createInterface } from 'node:readline'
6
6
  import { fileURLToPath } from 'node:url'
7
7
  import { log } from '@serverless/utils/log.js'
8
+ import { splitHandlerPathAndName } from '../../../utils/index.js'
8
9
 
9
10
  const { parse, stringify } = JSON
10
11
  const { assign, hasOwn } = Object
@@ -16,18 +17,15 @@ export default class PythonRunner {
16
17
 
17
18
  #env = null
18
19
 
19
- #handlerName = null
20
-
21
- #handlerPath = null
20
+ #handlerProcess = null
22
21
 
23
22
  #runtime = null
24
23
 
25
24
  constructor(funOptions, env) {
26
- const { handlerName, handlerPath, runtime } = funOptions
25
+ const { handler, runtime } = funOptions
26
+ const [handlerPath, handlerName] = splitHandlerPathAndName(handler)
27
27
 
28
28
  this.#env = env
29
- this.#handlerName = handlerName
30
- this.#handlerPath = handlerPath
31
29
  this.#runtime = platform() === 'win32' ? 'python.exe' : runtime
32
30
 
33
31
  if (process.env.VIRTUAL_ENV) {
@@ -42,13 +40,13 @@ export default class PythonRunner {
42
40
 
43
41
  const [pythonExecutable] = this.#runtime.split('.')
44
42
 
45
- this.handlerProcess = spawn(
43
+ this.#handlerProcess = spawn(
46
44
  pythonExecutable,
47
45
  [
48
46
  '-u',
49
47
  resolve(__dirname, 'invoke.py'),
50
- relative(cwd(), this.#handlerPath),
51
- this.#handlerName,
48
+ relative(cwd(), handlerPath),
49
+ handlerName,
52
50
  ],
53
51
  {
54
52
  env: assign(process.env, this.#env),
@@ -56,14 +54,14 @@ export default class PythonRunner {
56
54
  },
57
55
  )
58
56
 
59
- this.handlerProcess.stdout.readline = readline.createInterface({
60
- input: this.handlerProcess.stdout,
57
+ this.#handlerProcess.stdout.readline = createInterface({
58
+ input: this.#handlerProcess.stdout,
61
59
  })
62
60
  }
63
61
 
64
62
  // () => void
65
63
  cleanup() {
66
- this.handlerProcess.kill()
64
+ this.#handlerProcess.kill()
67
65
  }
68
66
 
69
67
  #parsePayload(value) {
@@ -117,8 +115,8 @@ export default class PythonRunner {
117
115
  try {
118
116
  const parsed = this.#parsePayload(line.toString())
119
117
  if (parsed) {
120
- this.handlerProcess.stdout.readline.removeListener('line', onLine)
121
- this.handlerProcess.stderr.removeListener('data', onErr)
118
+ this.#handlerProcess.stdout.readline.removeListener('line', onLine)
119
+ this.#handlerProcess.stderr.removeListener('data', onErr)
122
120
  return accept(parsed)
123
121
  }
124
122
  return null
@@ -127,12 +125,12 @@ export default class PythonRunner {
127
125
  }
128
126
  }
129
127
 
130
- this.handlerProcess.stdout.readline.on('line', onLine)
131
- this.handlerProcess.stderr.on('data', onErr)
128
+ this.#handlerProcess.stdout.readline.on('line', onLine)
129
+ this.#handlerProcess.stderr.on('data', onErr)
132
130
 
133
131
  process.nextTick(() => {
134
- this.handlerProcess.stdin.write(input)
135
- this.handlerProcess.stdin.write('\n')
132
+ this.#handlerProcess.stdin.write(input)
133
+ this.#handlerProcess.stdin.write('\n')
136
134
  })
137
135
  })
138
136
  }
@@ -4,6 +4,7 @@ import { cwd } from 'node:process'
4
4
  import { fileURLToPath } from 'node:url'
5
5
  import { log } from '@serverless/utils/log.js'
6
6
  import { execa } from 'execa'
7
+ import { splitHandlerPathAndName } from '../../../utils/index.js'
7
8
 
8
9
  const { parse, stringify } = JSON
9
10
  const { hasOwn } = Object
@@ -20,7 +21,9 @@ export default class RubyRunner {
20
21
  #handlerPath = null
21
22
 
22
23
  constructor(funOptions, env) {
23
- const { handlerName, handlerPath } = funOptions
24
+ const [handlerPath, handlerName] = splitHandlerPathAndName(
25
+ funOptions.handler,
26
+ )
24
27
 
25
28
  this.#env = env
26
29
  this.#handlerName = handlerName
@@ -8,18 +8,17 @@ const workerThreadHelperPath = resolve(__dirname, './workerThreadHelper.js')
8
8
  export default class WorkerThreadRunner {
9
9
  #workerThread = null
10
10
 
11
- constructor(funOptions /* options */, env) {
12
- // this._options = options
13
-
14
- const { functionKey, handlerName, handlerPath, timeout } = funOptions
11
+ constructor(funOptions, env) {
12
+ const { codeDir, functionKey, handler, servicePath, timeout } = funOptions
15
13
 
16
14
  this.#workerThread = new Worker(workerThreadHelperPath, {
17
15
  // don't pass process.env from the main process!
18
16
  env,
19
17
  workerData: {
18
+ codeDir,
20
19
  functionKey,
21
- handlerName,
22
- handlerPath,
20
+ handler,
21
+ servicePath,
23
22
  timeout,
24
23
  },
25
24
  })
@@ -2,18 +2,21 @@ import { env } from 'node:process'
2
2
  import { parentPort, workerData } from 'node:worker_threads'
3
3
  import InProcessRunner from '../in-process-runner/index.js'
4
4
 
5
- const { functionKey, handlerName, handlerPath, timeout } = workerData
5
+ const { functionKey, handler, servicePath, timeout, codeDir } = workerData
6
6
 
7
7
  parentPort.on('message', async (messageData) => {
8
8
  const { context, event, port } = messageData
9
9
 
10
10
  // TODO we could probably cache this in the module scope?
11
11
  const inProcessRunner = new InProcessRunner(
12
- functionKey,
13
- handlerPath,
14
- handlerName,
12
+ {
13
+ codeDir,
14
+ functionKey,
15
+ handler,
16
+ servicePath,
17
+ timeout,
18
+ },
15
19
  env,
16
- timeout,
17
20
  )
18
21
 
19
22
  let result
@@ -1,30 +0,0 @@
1
- import assert from 'node:assert'
2
- import LambdaContext from '../LambdaContext.js'
3
-
4
- describe('LambdaContext', () => {
5
- it('should create LambdaContext with correct values', () => {
6
- const functionName = 'foo'
7
- const memorySize = 512
8
- const requestId = 'abc123'
9
-
10
- const lambdaContext = new LambdaContext(functionName, memorySize)
11
- lambdaContext.setRequestId(requestId)
12
- const context = lambdaContext.create()
13
-
14
- const expected = {
15
- awsRequestId: 'abc123',
16
- callbackWaitsForEmptyEventLoop: true,
17
- clientContext: undefined,
18
- functionName: 'foo',
19
- functionVersion: '$LATEST',
20
- identity: undefined,
21
- invokedFunctionArn: 'offline_invokedFunctionArn_for_foo',
22
- logGroupName: 'offline_logGroupName_for_foo',
23
- logStreamName: 'offline_logStreamName_for_foo',
24
- memoryLimitInMB: '512',
25
- }
26
-
27
- // expect(context).toEqual(expected)
28
- assert.deepEqual(context, expected)
29
- })
30
- })
@@ -1,196 +0,0 @@
1
- import assert from 'node:assert'
2
- import { dirname, resolve } from 'node:path'
3
- // import { performance } from 'node:perf_hooks'
4
- import { fileURLToPath } from 'node:url'
5
- import LambdaFunction from '../LambdaFunction.js'
6
- import { DEFAULT_LAMBDA_TIMEOUT } from '../../config/index.js'
7
-
8
- const __dirname = dirname(fileURLToPath(import.meta.url))
9
-
10
- describe('LambdaFunction', () => {
11
- const functionName = 'foo'
12
-
13
- const serverless = {
14
- config: {
15
- serverlessPath: '',
16
- servicePath: resolve(__dirname),
17
- },
18
- service: {
19
- provider: {
20
- runtime: 'nodejs12.x',
21
- },
22
- },
23
- }
24
-
25
- describe('Handler tests', () => {
26
- ;[
27
- {
28
- description: 'should return result when handler is context.done',
29
- expected: 'foo',
30
- handler: 'fixtures/lambdaFunction.fixture.contextDoneHandler',
31
- },
32
- {
33
- description:
34
- 'should return result when handler is context.done which is deferred',
35
- expected: 'foo',
36
- handler: 'fixtures/lambdaFunction.fixture.contextDoneHandlerDeferred',
37
- },
38
- {
39
- description: 'should return result when handler is context.succeed',
40
- expected: 'foo',
41
- handler: 'fixtures/lambdaFunction.fixture.contextSucceedHandler',
42
- },
43
- {
44
- description:
45
- 'should return result when handler is context.succeed which is deferred',
46
- expected: 'foo',
47
- handler:
48
- 'fixtures/lambdaFunction.fixture.contextSucceedHandlerDeferred',
49
- },
50
- {
51
- description: 'should return result when handler is a callback',
52
- expected: 'foo',
53
- handler: 'fixtures/lambdaFunction.fixture.callbackHandler',
54
- },
55
- {
56
- description:
57
- 'should return result when handler is a callback which is deferred',
58
- expected: 'foo',
59
- handler: 'fixtures/lambdaFunction.fixture.callbackHandlerDeferred',
60
- },
61
- {
62
- description: 'should return result when handler returns a promise',
63
- expected: 'foo',
64
- handler: 'fixtures/lambdaFunction.fixture.promiseHandler',
65
- },
66
- {
67
- description:
68
- 'should return result when handler returns a promise which is deferred',
69
- expected: 'foo',
70
- handler: 'fixtures/lambdaFunction.fixture.promiseHandlerDeferred',
71
- },
72
- {
73
- description: 'should return result when handler is an async function',
74
- expected: 'foo',
75
- handler: 'fixtures/lambdaFunction.fixture.asyncFunctionHandler',
76
- },
77
- // NOTE: mix and matching of callbacks and promises is not recommended,
78
- // nonetheless, we test some of the behaviour to match AWS execution precedence
79
- {
80
- description:
81
- 'should return result when handler returns a callback but defines a callback parameter',
82
- expected: 'Hello Promise!',
83
- handler:
84
- 'fixtures/lambdaFunction.fixture.promiseWithDefinedCallbackHandler',
85
- },
86
- {
87
- description:
88
- 'should return result when handler calls context.succeed and context.done',
89
- expected: 'Hello Context.succeed!',
90
- handler:
91
- 'fixtures/lambdaFunction.fixture.contextSucceedWithContextDoneHandler',
92
- },
93
- {
94
- description:
95
- 'should return result when handler calls callback and context.done',
96
- expected: 'Hello Callback!',
97
- handler:
98
- 'fixtures/lambdaFunction.fixture.callbackWithContextDoneHandler',
99
- },
100
- {
101
- description:
102
- 'should return result when handler calls callback and returns Promise',
103
- expected: 'Hello Callback!',
104
- handler: 'fixtures/lambdaFunction.fixture.callbackWithPromiseHandler',
105
- },
106
- {
107
- description:
108
- 'should return result when handler calls callback inside returned Promise',
109
- expected: 'Hello Callback!',
110
- handler: 'fixtures/lambdaFunction.fixture.callbackInsidePromiseHandler',
111
- },
112
- ].forEach(({ description, expected, handler }) => {
113
- it(description, async () => {
114
- const functionDefinition = {
115
- handler,
116
- }
117
- const options = {}
118
- const lambdaFunction = new LambdaFunction(
119
- functionName,
120
- functionDefinition,
121
- serverless,
122
- options,
123
- )
124
- const result = await lambdaFunction.runHandler()
125
-
126
- await lambdaFunction.cleanup()
127
-
128
- assert.equal(result, expected)
129
- })
130
- })
131
- })
132
-
133
- it('should pass remaining time to LambdaContext', async () => {
134
- const functionDefinition = {
135
- handler: 'fixtures/lambdaFunction.fixture.remainingExecutionTimeHandler',
136
- }
137
- const options = {}
138
- const lambdaFunction = new LambdaFunction(
139
- functionName,
140
- functionDefinition,
141
- serverless,
142
- options,
143
- )
144
- const [first, second, third] = await lambdaFunction.runHandler()
145
-
146
- await lambdaFunction.cleanup()
147
-
148
- // handler "pauses" for 100 ms
149
- assert.ok(first > second - 100)
150
- assert.ok(second > third - 200)
151
- })
152
-
153
- it.skip('should use default lambda timeout when timeout is not provided', async () => {
154
- const functionDefinition = {
155
- handler: 'fixtures/lambdaFunction.fixture.defaultTimeoutHandler',
156
- }
157
- const options = {}
158
- const lambdaFunction = new LambdaFunction(
159
- functionName,
160
- functionDefinition,
161
- serverless,
162
- options,
163
- )
164
- const remainingTime = await lambdaFunction.runHandler()
165
-
166
- await lambdaFunction.cleanup()
167
-
168
- assert.ok(remainingTime < DEFAULT_LAMBDA_TIMEOUT * 1000)
169
-
170
- // result might be flaky/unreliable:
171
- // (assmuning handler runs no longer than 1 s)
172
- assert.ok(remainingTime + 1000 > DEFAULT_LAMBDA_TIMEOUT * 1000)
173
- })
174
-
175
- // // might run flaky (unreliable)
176
- // test('executionTimeInMillis should return execution time', async () => {
177
- // const functionDefinition = {
178
- // handler: 'fixtures/lambdaFunction.fixture.executionTimeInMillisHandler',
179
- // }
180
- // const options = {}
181
- // const lambdaFunction = new LambdaFunction(
182
- // functionName,
183
- // functionDefinition,
184
- // provider,
185
- // config,
186
- // options,
187
- // )
188
- // const timerStart = performance.now()
189
- // await lambdaFunction.runHandler()
190
- // const timerEnd = performance.now()
191
- //
192
- // expect(lambdaFunction.executionTimeInMillis).toBeLessThanOrEqual(
193
- // timerEnd - timerStart + 10,
194
- // )
195
- // })
196
- })
@@ -1,47 +0,0 @@
1
- import { dirname, resolve } from 'node:path'
2
- import { fileURLToPath } from 'node:url'
3
- import LambdaFunction from '../../../LambdaFunction.js'
4
-
5
- const __dirname = dirname(fileURLToPath(import.meta.url))
6
-
7
- export default class LambdaFunctionThatReturnsJSONObject {
8
- #lambdaFunction
9
-
10
- options = {}
11
-
12
- serverless = {
13
- config: {
14
- serverlessPath: '',
15
- servicePath: resolve(__dirname),
16
- },
17
- service: {
18
- provider: {
19
- runtime: 'nodejs12.x',
20
- },
21
- },
22
- }
23
-
24
- listFunctionNames() {
25
- return ['foo']
26
- }
27
-
28
- getByFunctionName(functionName) {
29
- const functionDefinition = {
30
- handler:
31
- '../../fixtures/lambdaFunction.fixture.asyncFunctionHandlerObject',
32
- }
33
-
34
- this.#lambdaFunction = new LambdaFunction(
35
- functionName,
36
- functionDefinition,
37
- this.serverless,
38
- this.options,
39
- )
40
-
41
- return this.#lambdaFunction
42
- }
43
-
44
- async cleanup() {
45
- await this.#lambdaFunction.cleanup()
46
- }
47
- }
@@ -1,46 +0,0 @@
1
- import { dirname, resolve } from 'node:path'
2
- import { fileURLToPath } from 'node:url'
3
- import LambdaFunction from '../../../LambdaFunction.js'
4
-
5
- const __dirname = dirname(fileURLToPath(import.meta.url))
6
-
7
- export default class LambdaFunctionThatReturnsNativeString {
8
- #lambdaFunction
9
-
10
- options = {}
11
-
12
- serverless = {
13
- config: {
14
- serverlessPath: '',
15
- servicePath: resolve(__dirname),
16
- },
17
- service: {
18
- provider: {
19
- runtime: 'nodejs12.x',
20
- },
21
- },
22
- }
23
-
24
- listFunctionNames() {
25
- return ['foo']
26
- }
27
-
28
- getByFunctionName(functionName) {
29
- const functionDefinition = {
30
- handler: '../../fixtures/lambdaFunction.fixture.asyncFunctionHandler',
31
- }
32
-
33
- this.#lambdaFunction = new LambdaFunction(
34
- functionName,
35
- functionDefinition,
36
- this.serverless,
37
- this.options,
38
- )
39
-
40
- return this.#lambdaFunction
41
- }
42
-
43
- async cleanup() {
44
- await this.#lambdaFunction.cleanup()
45
- }
46
- }
@@ -1,3 +0,0 @@
1
- {
2
- "type": "module"
3
- }
@@ -1,145 +0,0 @@
1
- 'use strict'
2
-
3
- exports.contextDoneHandler = function contextDoneHandler(event, context) {
4
- context.done(null, 'foo')
5
- }
6
-
7
- exports.contextDoneHandlerDeferred = function contextDoneHandlerDeferred(
8
- event,
9
- context,
10
- ) {
11
- setTimeout(() => context.done(null, 'foo'), 100)
12
- }
13
-
14
- exports.contextSucceedHandler = function contextSucceedHandler(event, context) {
15
- context.succeed('foo')
16
- }
17
-
18
- exports.contextSucceedHandlerDeferred = function contextSucceedHandlerDeferred(
19
- event,
20
- context,
21
- ) {
22
- setTimeout(() => context.succeed('foo'), 100)
23
- }
24
-
25
- exports.callbackHandler = function callbackHandler(event, context, callback) {
26
- callback(null, 'foo')
27
- }
28
-
29
- exports.callbackHandlerDeferred = function callbackHandlerDeferred(
30
- event,
31
- context,
32
- callback,
33
- ) {
34
- setTimeout(() => callback(null, 'foo'), 100)
35
- }
36
-
37
- exports.promiseHandler = function promiseHandler() {
38
- return Promise.resolve('foo')
39
- }
40
-
41
- exports.promiseHandlerDeferred = function promiseDeferred() {
42
- return new Promise((resolve) => {
43
- setTimeout(() => resolve('foo'), 100)
44
- })
45
- }
46
-
47
- exports.asyncFunctionHandler = async function asyncFunctionHandler() {
48
- return 'foo'
49
- }
50
-
51
- exports.asyncFunctionHandlerObject = async function asyncFunctionHandler() {
52
- return {
53
- foo: 'bar',
54
- }
55
- }
56
-
57
- // we deliberately test the case where a 'callback' is defined
58
- // in the handler, but a promise is being returned to protect from a
59
- // potential naive implementation, e.g.
60
- //
61
- // const { promisify } = 'utils'
62
- // const promisifiedHandler = handler.length === 3 ? promisify(handler) : handler
63
- //
64
- // if someone would return a promise, but also defines callback, without using it
65
- // the handler would not be returning anything
66
- exports.promiseWithDefinedCallbackHandler =
67
- function promiseWithDefinedCallbackHandler(
68
- event, // eslint-disable-line no-unused-vars
69
- context, // eslint-disable-line no-unused-vars
70
- callback, // eslint-disable-line no-unused-vars
71
- ) {
72
- return Promise.resolve('Hello Promise!')
73
- }
74
-
75
- exports.contextSucceedWithContextDoneHandler =
76
- function contextSucceedWithContextDoneHandler(event, context) {
77
- context.succeed('Hello Context.succeed!')
78
-
79
- context.done(null, 'Hello Context.done!')
80
- }
81
-
82
- exports.callbackWithContextDoneHandler =
83
- function callbackWithContextDoneHandler(event, context, callback) {
84
- callback(null, 'Hello Callback!')
85
-
86
- context.done(null, 'Hello Context.done!')
87
- }
88
-
89
- exports.callbackWithPromiseHandler = function callbackWithPromiseHandler(
90
- event,
91
- context,
92
- callback,
93
- ) {
94
- callback(null, 'Hello Callback!')
95
-
96
- return Promise.resolve('Hello Promise!')
97
- }
98
-
99
- exports.callbackInsidePromiseHandler = function callbackInsidePromiseHandler(
100
- event,
101
- context,
102
- callback,
103
- ) {
104
- return new Promise((resolve) => {
105
- callback(null, 'Hello Callback!')
106
-
107
- resolve('Hello Promise!')
108
- })
109
- }
110
-
111
- exports.requestIdHandler = async function requestIdHandler(event, context) {
112
- return context.awsRequestId
113
- }
114
-
115
- exports.remainingExecutionTimeHandler =
116
- async function remainingExecutionTimeHandler(event, context) {
117
- const first = context.getRemainingTimeInMillis()
118
-
119
- await new Promise((resolve) => {
120
- setTimeout(resolve, 100)
121
- })
122
-
123
- const second = context.getRemainingTimeInMillis()
124
-
125
- await new Promise((resolve) => {
126
- setTimeout(resolve, 200)
127
- })
128
-
129
- const third = context.getRemainingTimeInMillis()
130
-
131
- return [first, second, third]
132
- }
133
-
134
- exports.defaultTimeoutHandler = async function defaultTimeoutHandler(
135
- event,
136
- context,
137
- ) {
138
- return context.getRemainingTimeInMillis()
139
- }
140
-
141
- exports.executionTimeInMillisHandler = function executionTimeInMillisHandler() {
142
- return new Promise((resolve) => {
143
- setTimeout(resolve, 100)
144
- })
145
- }
@@ -1,42 +0,0 @@
1
- import assert from 'node:assert'
2
- import InvocationsController from '../../../routes/invocations/InvocationsController.js'
3
- import LambdaFunctionThatReturnsJSONObject from '../../fixtures/Lambda/LambdaFunctionThatReturnsJSONObject.fixture.js'
4
- import LambdaFunctionThatReturnsNativeString from '../../fixtures/Lambda/LambdaFunctionThatReturnsNativeString.fixture.js'
5
-
6
- describe('InvocationController', () => {
7
- const functionName = 'foo'
8
-
9
- describe('when event type is "RequestResponse"', () => {
10
- const eventType = 'RequestResponse'
11
-
12
- it('should return json object if lambda response is json', async () => {
13
- const expected = {
14
- Payload: {
15
- foo: 'bar',
16
- },
17
- StatusCode: 200,
18
- }
19
-
20
- const lambdaFunction = new LambdaFunctionThatReturnsJSONObject()
21
- const invocationController = new InvocationsController(lambdaFunction)
22
- const result = await invocationController.invoke(functionName, eventType)
23
- await lambdaFunction.cleanup()
24
-
25
- assert.deepEqual(result, expected)
26
- })
27
-
28
- it('should wrap native string responses with ""', async () => {
29
- const expected = {
30
- Payload: '"foo"',
31
- StatusCode: 200,
32
- }
33
-
34
- const lambdaFunction = new LambdaFunctionThatReturnsNativeString()
35
- const invocationController = new InvocationsController(lambdaFunction)
36
- const result = await invocationController.invoke(functionName, eventType)
37
- await lambdaFunction.cleanup()
38
-
39
- assert.deepEqual(result, expected)
40
- })
41
- })
42
- })