serverless-offline 9.2.1 → 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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "dedicatedTo": "Blue, a great migrating bird.",
3
3
  "name": "serverless-offline",
4
- "version": "9.2.1",
4
+ "version": "9.2.2",
5
5
  "description": "Emulate AWS λ and API Gateway locally when developing your Serverless project",
6
6
  "license": "MIT",
7
7
  "main": "./src/index.js",
@@ -49,12 +49,6 @@
49
49
  "schedule",
50
50
  "websocket"
51
51
  ],
52
- "files": [
53
- "src/**",
54
- "package.json",
55
- "LICENSE",
56
- "README.md"
57
- ],
58
52
  "author": "David Hérault <dherault@gmail.com> (https://github.com/dherault)",
59
53
  "maintainers": [
60
54
  "Bilal Soylu (https://github.com/Bilal-S)",
@@ -195,7 +189,7 @@
195
189
  "@hapi/h2o2": "^9.1.0",
196
190
  "@hapi/hapi": "^20.2.2",
197
191
  "@serverless/utils": "^6.7.0",
198
- "aws-sdk": "^2.1194.0",
192
+ "aws-sdk": "^2.1195.0",
199
193
  "boxen": "^7.0.0",
200
194
  "chalk": "^5.0.1",
201
195
  "execa": "^6.1.0",
@@ -227,7 +221,7 @@
227
221
  "lint-staged": "^13.0.3",
228
222
  "mocha": "^10.0.0",
229
223
  "prettier": "^2.7.1",
230
- "serverless": "^3.21.0",
224
+ "serverless": "^3.22.0",
231
225
  "standard-version": "^9.5.0"
232
226
  },
233
227
  "peerDependencies": {
@@ -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,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 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: 'fixtures/lambdaFunction-fixture.asyncFunctionHandlerObject',
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,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,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }
@@ -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
- })
@@ -1,18 +0,0 @@
1
- import assert from 'node:assert'
2
- import createUniqueId from '../createUniqueId.js'
3
-
4
- describe('createUniqueId', () => {
5
- it('should be unique', () => {
6
- const items = 100000
7
- const set = new Set(Array.from(Array(items)).map(createUniqueId))
8
-
9
- assert.equal(set.size, items)
10
- })
11
-
12
- it('should be a 36 character string', () => {
13
- const id = createUniqueId()
14
-
15
- assert.equal(typeof id, 'string')
16
- assert.equal(id.length, 36)
17
- })
18
- })
@@ -1,14 +0,0 @@
1
- import assert from 'node:assert'
2
- import formatToClfTime from '../formatToClfTime.js'
3
-
4
- const { now } = Date
5
-
6
- describe('formatToClfTime', () => {
7
- it('should return "common log format" formatted time', () => {
8
- const millis = now()
9
- const result = formatToClfTime(millis)
10
-
11
- // expected: 17/Dec/1995:03:24:00 -0500 (with varying offset)
12
- assert.match(result, /([\w:/]+\s[+-]\d{4})/)
13
- })
14
- })
@@ -1,46 +0,0 @@
1
- import assert from 'node:assert'
2
- import generateHapiPath from '../generateHapiPath.js'
3
-
4
- const serverless = {
5
- service: {
6
- provider: {
7
- stage: 'dev',
8
- },
9
- },
10
- }
11
-
12
- describe('generateHapiPath', () => {
13
- it('should generate url starting with a slash', () => {
14
- const options = {}
15
- const result = generateHapiPath('users', options, serverless)
16
- assert.equal(result[0], '/')
17
- })
18
-
19
- it('should generate url with the stage prepended', () => {
20
- const options = {}
21
- const result = generateHapiPath('users', options, serverless)
22
- assert.equal(result, '/dev/users')
23
- })
24
-
25
- describe('when a prefix option is set', () => {
26
- it('the url should add the prefix', () => {
27
- const options = { prefix: 'some-prefix' }
28
- const result = generateHapiPath('users', options, serverless)
29
- assert.equal(result, '/some-prefix/dev/users')
30
- })
31
- })
32
-
33
- describe('when the noPrependStageInUrl option is set', () => {
34
- it('the url should omit the stage', () => {
35
- const options = { noPrependStageInUrl: true }
36
- const result = generateHapiPath('users', options, serverless)
37
- assert.equal(result, '/users')
38
- })
39
- })
40
-
41
- it('the stage from options should override stage from serverless config', () => {
42
- const options = { stage: 'prod' }
43
- const result = generateHapiPath('users', options, serverless)
44
- assert.equal(result, '/prod/users')
45
- })
46
- })
@@ -1,30 +0,0 @@
1
- import assert from 'node:assert'
2
- import lowerCaseKeys from '../lowerCaseKeys.js'
3
-
4
- describe('lowerCaseKeys', () => {
5
- it('should handle empty object', () => {
6
- const result = lowerCaseKeys({})
7
- assert.deepEqual(result, {})
8
- })
9
-
10
- it('should handle object with one key', () => {
11
- const result = lowerCaseKeys({ 'Some-Key': 'value' })
12
- assert.deepEqual(result, { 'some-key': 'value' })
13
- })
14
-
15
- it('should handle object with multiple keys', () => {
16
- const result = lowerCaseKeys({
17
- 'already-lowercase': 'cool',
18
- 'Another-Key': 'anotherValue',
19
- 'lOts-OF-CAPitaLs': 'ButThisIsNotTouched',
20
- 'Some-Key': 'value',
21
- })
22
-
23
- assert.deepEqual(result, {
24
- 'already-lowercase': 'cool',
25
- 'another-key': 'anotherValue',
26
- 'lots-of-capitals': 'ButThisIsNotTouched',
27
- 'some-key': 'value',
28
- })
29
- })
30
- })
@@ -1,13 +0,0 @@
1
- import assert from 'node:assert'
2
- // uses the same tests as parseMultiValueHeaders
3
- import tests from './parseMultiValueHeaders.test.js'
4
- import parseHeaders from '../parseHeaders.js'
5
-
6
- describe('parseQueryStringParameters', () => {
7
- tests.forEach(({ description, expected, param }) => {
8
- it(`should return ${description}`, () => {
9
- const result = parseHeaders(param)
10
- assert.deepEqual(result, expected)
11
- })
12
- })
13
- })
@@ -1,24 +0,0 @@
1
- import assert from 'node:assert'
2
- import parseMultiValueHeaders from '../parseMultiValueHeaders.js'
3
-
4
- // TODO need more tests
5
- const tests = [
6
- {
7
- description: 'no parameter (empty array)',
8
- expected: null,
9
- expectedMulti: null,
10
- param: [],
11
- },
12
- ]
13
-
14
- describe('parseMultiValueHeaders', () => {
15
- tests.forEach(({ description, expectedMulti, param }) => {
16
- it(`should return ${description}`, () => {
17
- const resultMulti = parseMultiValueHeaders(param)
18
- assert.deepEqual(resultMulti, expectedMulti)
19
- })
20
- })
21
- })
22
-
23
- // export tests for parseHeaders
24
- export default tests
@@ -1,159 +0,0 @@
1
- import assert from 'node:assert'
2
- import parseMultiValueQueryStringParameters from '../parseMultiValueQueryStringParameters.js'
3
-
4
- const tests = [
5
- {
6
- description: 'no parameter (empty string)',
7
- expected: null,
8
- expectedMulti: null,
9
- param: '',
10
- },
11
-
12
- {
13
- description: 'string parameter',
14
- expected: { foo: 'bar' },
15
- expectedMulti: { foo: ['bar'] },
16
- param: 'foo=bar',
17
- },
18
-
19
- {
20
- description: 'number parameter (no type casting)',
21
- expected: { foo: '1' },
22
- expectedMulti: { foo: ['1'] },
23
- param: 'foo=1',
24
- },
25
-
26
- {
27
- description: 'boolean parameter (no type casting)',
28
- expected: { foo: 'true' },
29
- expectedMulti: { foo: ['true'] },
30
- param: 'foo=true',
31
- },
32
-
33
- {
34
- description: 'multiple parameters',
35
- expected: { bar: 'test2', foo: 'test1' },
36
- expectedMulti: { bar: ['test2'], foo: ['test1'] },
37
- param: 'foo=test1&bar=test2',
38
- },
39
-
40
- {
41
- description: 'multiple parameters, same keys',
42
- expected: { foo: 'foobar' },
43
- expectedMulti: { foo: ['test', 'foobar'] },
44
- param: 'foo=test&foo=foobar',
45
- },
46
-
47
- {
48
- description: 'multiple parameters, same keys, different casing',
49
- expected: { foo: 'test', FOO: 'FOOBAR' },
50
- expectedMulti: { foo: ['test'], FOO: ['FOOBAR'] },
51
- param: 'foo=test&FOO=FOOBAR',
52
- },
53
-
54
- {
55
- description: 'multiple parameters, same keys, same values',
56
- expected: { foo: 'test' },
57
- expectedMulti: { foo: ['test', 'test'] },
58
- param: 'foo=test&foo=test',
59
- },
60
-
61
- {
62
- description: 'no value',
63
- expected: { foo: '' },
64
- expectedMulti: { foo: [''] },
65
- param: 'foo',
66
- },
67
-
68
- {
69
- description: 'no value with =',
70
- expected: { foo: '' },
71
- expectedMulti: { foo: [''] },
72
- param: 'foo=',
73
- },
74
-
75
- {
76
- description: 'no value with &',
77
- expected: { foo: '' },
78
- expectedMulti: { foo: [''] },
79
- param: 'foo&',
80
- },
81
-
82
- {
83
- description: 'no value with = and &',
84
- expected: { foo: '' },
85
- expectedMulti: { foo: [''] },
86
- param: 'foo=&',
87
- },
88
-
89
- {
90
- description: 'value is whitespace',
91
- expected: { foo: ' ' },
92
- expectedMulti: { foo: [' '] },
93
- param: 'foo=%20',
94
- },
95
-
96
- {
97
- description: 'key and value have whitespace',
98
- expected: { ' foo ': ' test ' },
99
- expectedMulti: { ' foo ': [' test '] },
100
- param: '%20foo%20=%20test%20',
101
- },
102
-
103
- {
104
- description: 'unicode',
105
- expected: { Σ: '😋' },
106
- expectedMulti: { Σ: ['😋'] },
107
- param: 'Σ=😋',
108
- },
109
-
110
- {
111
- description: 'encoded', // encodeURIComponent
112
- expected: { '?=/&:': '?=/&:' },
113
- expectedMulti: { '?=/&:': ['?=/&:'] },
114
- param: '%3F%3D%2F%26%3A=%3F%3D%2F%26%3A',
115
- },
116
-
117
- {
118
- description: 'end of line',
119
- expected: { '\n': '\n' },
120
- expectedMulti: { '\n': ['\n'] },
121
- param: '%0A=%0A',
122
- },
123
-
124
- // silly test section:
125
- {
126
- description: 'silly I.',
127
- expected: { test: '?' },
128
- expectedMulti: { test: ['?'] },
129
- param: 'test=?',
130
- },
131
-
132
- {
133
- description: 'silly II.',
134
- expected: { test: '/' },
135
- expectedMulti: { test: ['/'] },
136
- param: 'test=/',
137
- },
138
-
139
- {
140
- description: 'silly III.',
141
- expected: { test: '=' },
142
- expectedMulti: { test: ['='] },
143
- param: 'test==',
144
- },
145
- ]
146
-
147
- describe('parseMultiValueQueryStringParameters', () => {
148
- tests.forEach(({ description, expectedMulti, param }) => {
149
- const url = `foo?${param}`
150
-
151
- it(`should return ${description}`, () => {
152
- const resultMulti = parseMultiValueQueryStringParameters(url)
153
- assert.deepEqual(resultMulti, expectedMulti)
154
- })
155
- })
156
- })
157
-
158
- // export tests for parseQueryStringParameters
159
- export default tests
@@ -1,15 +0,0 @@
1
- import assert from 'node:assert'
2
- // uses the same tests as parseMultiValueQueryStringParameters
3
- import tests from './parseMultiValueQueryStringParameters.test.js'
4
- import parseQueryStringParameters from '../parseQueryStringParameters.js'
5
-
6
- describe('parseQueryStringParameters', () => {
7
- tests.forEach(({ description, expected, param }) => {
8
- const url = `/foo?${param}`
9
-
10
- it(`should return ${description}`, () => {
11
- const result = parseQueryStringParameters(url)
12
- assert.deepEqual(result, expected)
13
- })
14
- })
15
- })
@@ -1,54 +0,0 @@
1
- import assert from 'node:assert'
2
- import splitHandlerPathAndName from '../splitHandlerPathAndName.js'
3
-
4
- const tests = [
5
- {
6
- description: 'ruby handler with namespace resolution operator ::',
7
- expected: ['./src/somefolder/source', 'LambdaFunctions::Handler.process'],
8
- handler: './src/somefolder/source.LambdaFunctions::Handler.process',
9
- },
10
- {
11
- description: 'ruby handler with multiple namespace resolution operators ::',
12
- expected: [
13
- './src/somefolder/source',
14
- 'Functions::LambdaFunctions::Handler.process',
15
- ],
16
- handler:
17
- './src/somefolder/source.Functions::LambdaFunctions::Handler.process',
18
- },
19
- {
20
- description: 'ruby handler with namespace resolution operator ::, unnested',
21
- expected: ['source', 'LambdaFunctions::Handler.process'],
22
- handler: 'source.LambdaFunctions::Handler.process',
23
- },
24
- {
25
- description:
26
- 'ruby handler with multiple namespace resolution operators ::, unnested',
27
- expected: ['./source', 'Functions::LambdaFunctions::Handler.process'],
28
- handler: './source.Functions::LambdaFunctions::Handler.process',
29
- },
30
- {
31
- description: 'ruby handler from kernel',
32
- expected: ['./src/somefolder/function', 'handler'],
33
- handler: './src/somefolder/function.handler',
34
- },
35
- {
36
- description: 'generic handler',
37
- expected: ['./src/somefolder/.handlers/handler', 'run'],
38
- handler: './src/somefolder/.handlers/handler.run',
39
- },
40
- {
41
- description: 'generic handler, unnested',
42
- expected: ['handler', 'run'],
43
- handler: 'handler.run',
44
- },
45
- ]
46
-
47
- describe('splitHandlerPathAndName', () => {
48
- tests.forEach(({ description, expected, handler }) => {
49
- it(`should split ${description}`, () => {
50
- const result = splitHandlerPathAndName(handler)
51
- assert.deepEqual(result, expected)
52
- })
53
- })
54
- })
@@ -1,32 +0,0 @@
1
- import assert from 'node:assert'
2
- import unflatten from '../unflatten.js'
3
-
4
- describe('unflatten', () => {
5
- it('should work with empty array parameter', () => {
6
- const value = []
7
- const out = unflatten(value, 2)
8
- const expected = []
9
-
10
- assert.deepEqual(out, expected)
11
- })
12
-
13
- it('should work with single pair parameter', () => {
14
- const value = ['a', 1]
15
- const out = unflatten(value, 2)
16
- const expected = [['a', 1]]
17
-
18
- assert.deepEqual(out, expected)
19
- })
20
-
21
- it('should work with multiple pair parameters', () => {
22
- const value = ['a', 1, 'b', 2, 'c', 3]
23
- const out = unflatten(value, 2)
24
- const expected = [
25
- ['a', 1],
26
- ['b', 2],
27
- ['c', 3],
28
- ]
29
-
30
- assert.deepEqual(out, expected)
31
- })
32
- })