@creator.co/wapi 1.7.1-alpha4 → 1.7.1
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/.eslintignore +3 -0
- package/.eslintrc.cjs +60 -0
- package/.github/workflows/npmpublish.yml +11 -0
- package/.github/workflows/prs.yml +13 -0
- package/dist/package-lock.json +2 -2
- package/dist/package.json +1 -1
- package/jest.config.ts +33 -0
- package/jest.smoke.config.ts +35 -0
- package/package.json +1 -1
- package/tests/API/Request.test.ts +273 -0
- package/tests/API/Response.test.ts +367 -0
- package/tests/API/Utils.test.ts +167 -0
- package/tests/BaseEvent/EventProcessor.test.ts +261 -0
- package/tests/BaseEvent/Process.test.ts +49 -0
- package/tests/BaseEvent/Transaction.test.ts +408 -0
- package/tests/Cache/Redis-client.test.ts +90 -0
- package/tests/Cache/Redis-cluster.test.ts +100 -0
- package/tests/Config/Config.test.ts +205 -0
- package/tests/Config/EnvironmentVar.test.ts +250 -0
- package/tests/Crypto/Crypto.test.ts +88 -0
- package/tests/Crypto/JWT.test.ts +92 -0
- package/tests/Database/DatabaseManager.test.ts +71 -0
- package/tests/Database/integrations/knex/KnexDatabase.test.ts +76 -0
- package/tests/Database/integrations/knex/KnexTransaction.test.ts +149 -0
- package/tests/Database/integrations/kysely/KyselyDatabase.test.ts +113 -0
- package/tests/Database/integrations/kysely/KyselyTransaction.test.ts +119 -0
- package/tests/Database/integrations/pg/PostgresDatabase.test.ts +76 -0
- package/tests/Database/integrations/pg/PostgresTransaction.test.ts +118 -0
- package/tests/Logger/Logger.test.ts +219 -0
- package/tests/Mailer/Mailer.test.ts +59 -0
- package/tests/Publisher/Publisher.test.ts +94 -0
- package/tests/Server/RouteResolver.test.ts +102 -0
- package/tests/Server/Router.test.ts +39 -0
- package/tests/Server/lib/ContainerServer.test.ts +531 -0
- package/tests/Server/lib/Server.test.ts +12 -0
- package/tests/Server/lib/container/GenericHandler.test.ts +131 -0
- package/tests/Server/lib/container/GenericHandlerEvent.test.ts +103 -0
- package/tests/Server/lib/container/HealthHandler.test.ts +30 -0
- package/tests/Server/lib/container/Proxy.test.ts +268 -0
- package/tests/Server/lib/container/Utils.test.ts +47 -0
- package/tests/Test.utils.ts +74 -0
- package/tests/Validation/Validator.test.ts +76 -0
- package/tsconfig.json +26 -0
- package/tsconfig.smoke.json +26 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
2
|
+
import { APIGatewayEvent, Context } from 'aws-lambda'
|
|
3
|
+
import { expect as c_expect } from 'chai'
|
|
4
|
+
|
|
5
|
+
import Response from '../../src/API/Response'
|
|
6
|
+
import Transaction from '../../src/BaseEvent/Transaction'
|
|
7
|
+
import Globals from '../../src/Globals'
|
|
8
|
+
import { observableTransaction, defaultHeaders } from '../Test.utils'
|
|
9
|
+
|
|
10
|
+
async function testResponse(r: Response<any>, body: any, optCode?: number, optHeaders?: any) {
|
|
11
|
+
const t = observableTransaction()
|
|
12
|
+
const context = t['context']
|
|
13
|
+
const buildR = await r.build(context, t, false)
|
|
14
|
+
c_expect(buildR).to.be.undefined
|
|
15
|
+
expect(t.responseProxy).toBeCalledTimes(1)
|
|
16
|
+
expect(context.fail).not.toBeCalled()
|
|
17
|
+
expect(context.done).not.toBeCalled()
|
|
18
|
+
expect(context.succeed).toHaveBeenCalledWith({
|
|
19
|
+
statusCode: optCode || 400,
|
|
20
|
+
headers: {
|
|
21
|
+
...defaultHeaders,
|
|
22
|
+
...(optHeaders || {}),
|
|
23
|
+
},
|
|
24
|
+
...(body
|
|
25
|
+
? {
|
|
26
|
+
body: JSON.stringify({
|
|
27
|
+
...body,
|
|
28
|
+
transactionID: 'unknown',
|
|
29
|
+
}),
|
|
30
|
+
}
|
|
31
|
+
: {}),
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe('Response basics', () => {
|
|
36
|
+
test('Null body', () => {
|
|
37
|
+
const r = new Response<null>(200, null)
|
|
38
|
+
c_expect(r.getCode()).to.be.equals(200)
|
|
39
|
+
c_expect(r.getBody()).to.be.null
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('String body', () => {
|
|
43
|
+
const r = new Response<string>(200, 'abc')
|
|
44
|
+
c_expect(r.getCode()).to.be.equals(200)
|
|
45
|
+
c_expect(r.getBody()).to.be.equals('abc')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('Generic body', () => {
|
|
49
|
+
const r = new Response<any>(200, { name: 'abc' })
|
|
50
|
+
r.appendIntoBody('name2', '123')
|
|
51
|
+
c_expect(r.getCode()).to.be.equals(200)
|
|
52
|
+
c_expect(r.getBody().name).to.be.equals('abc')
|
|
53
|
+
c_expect(r.getBody().name2).to.be.equals('123')
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('Append/validate header', () => {
|
|
57
|
+
const r = new Response<any>(200, {})
|
|
58
|
+
r.appendHeader('name2', '123')
|
|
59
|
+
c_expect(r['headers']['name2']).to.be.equals('123')
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
describe('Response build', () => {
|
|
64
|
+
test('Succeeds to transaction context', async () => {
|
|
65
|
+
const b = { name: 'abc' }
|
|
66
|
+
const r = new Response<any>(200, b)
|
|
67
|
+
r.appendHeader('abc', '123')
|
|
68
|
+
// do not use default, so we dont use proxy response for once
|
|
69
|
+
const t = new Transaction(
|
|
70
|
+
<APIGatewayEvent>(<unknown>{}),
|
|
71
|
+
<Context>(<unknown>{
|
|
72
|
+
done: jest.fn(),
|
|
73
|
+
fail: jest.fn(),
|
|
74
|
+
succeed: jest.fn(),
|
|
75
|
+
})
|
|
76
|
+
)
|
|
77
|
+
const context = t['context']
|
|
78
|
+
const buildR = await r.build(context, t, false)
|
|
79
|
+
c_expect(buildR).to.be.undefined
|
|
80
|
+
expect(context.fail).not.toBeCalled()
|
|
81
|
+
expect(context.done).not.toBeCalled()
|
|
82
|
+
expect(context.succeed).toHaveBeenCalledWith({
|
|
83
|
+
statusCode: 200,
|
|
84
|
+
headers: {
|
|
85
|
+
...defaultHeaders,
|
|
86
|
+
abc: '123',
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify({
|
|
89
|
+
...b,
|
|
90
|
+
transactionID: 'unknown',
|
|
91
|
+
}),
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('Succeeds with no context call', async () => {
|
|
96
|
+
const b = { name: 'abc' }
|
|
97
|
+
const r = new Response<any>(200, b)
|
|
98
|
+
const t = observableTransaction()
|
|
99
|
+
const context = t['context']
|
|
100
|
+
const buildR = await r.build(context, t, true)
|
|
101
|
+
c_expect(buildR).to.be.undefined
|
|
102
|
+
expect(context.fail).not.toBeCalled()
|
|
103
|
+
expect(context.done).not.toBeCalled()
|
|
104
|
+
expect(context.succeed).not.toBeCalled()
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('Succeeds to transaction context as RAW', async () => {
|
|
108
|
+
const b = { name: 'abc' }
|
|
109
|
+
const r = new Response<any>(200, b, {
|
|
110
|
+
rawBody: true,
|
|
111
|
+
})
|
|
112
|
+
const t = observableTransaction()
|
|
113
|
+
const context = t['context']
|
|
114
|
+
const buildR = await r.build(context, t, false)
|
|
115
|
+
c_expect(buildR).to.be.undefined
|
|
116
|
+
expect(context.fail).not.toBeCalled()
|
|
117
|
+
expect(context.done).not.toBeCalled()
|
|
118
|
+
expect(context.succeed).toHaveBeenCalledWith({
|
|
119
|
+
...b,
|
|
120
|
+
transactionID: 'unknown',
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
test('Succeeds to transaction piping', async () => {
|
|
125
|
+
const b = { name: 'abc' }
|
|
126
|
+
const r = new Response<any>(200, b, {
|
|
127
|
+
shouldStream: true,
|
|
128
|
+
})
|
|
129
|
+
const t = observableTransaction()
|
|
130
|
+
const context = t['context']
|
|
131
|
+
const buildR = await r.build(context, t, false)
|
|
132
|
+
await r.build(context, t, false) //pipe twice, should not affect
|
|
133
|
+
c_expect(buildR).to.be.undefined
|
|
134
|
+
expect(context.fail).not.toBeCalled()
|
|
135
|
+
expect(context.done).not.toBeCalled()
|
|
136
|
+
expect(context.succeed).toHaveBeenCalledTimes(1)
|
|
137
|
+
expect(context.succeed).toHaveBeenCalledWith({
|
|
138
|
+
statusCode: 200,
|
|
139
|
+
headers: {
|
|
140
|
+
...defaultHeaders,
|
|
141
|
+
},
|
|
142
|
+
body: {
|
|
143
|
+
...b,
|
|
144
|
+
},
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test('Failure to transaction context as RAW', async () => {
|
|
149
|
+
const b = { name: 'abc' }
|
|
150
|
+
const r = new Response<any>(400, b, {
|
|
151
|
+
rawBody: true,
|
|
152
|
+
})
|
|
153
|
+
const t = observableTransaction()
|
|
154
|
+
const context = t['context']
|
|
155
|
+
const buildR = await r.build(context, t, false)
|
|
156
|
+
c_expect(buildR).to.be.undefined
|
|
157
|
+
expect(context.done).not.toBeCalled()
|
|
158
|
+
expect(context.succeed).not.toBeCalled()
|
|
159
|
+
expect(context.fail).toHaveBeenCalledTimes(1)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
test('Failure exception to transaction context as RAW', async () => {
|
|
163
|
+
const b = { name: 'abc' }
|
|
164
|
+
const r = new Response<any>(400, b, {
|
|
165
|
+
rawBody: true,
|
|
166
|
+
throwOnErrors: true,
|
|
167
|
+
})
|
|
168
|
+
const t = observableTransaction()
|
|
169
|
+
const context = t['context']
|
|
170
|
+
let buildR: any = null,
|
|
171
|
+
exception = null
|
|
172
|
+
try {
|
|
173
|
+
buildR = await r.build(context, t, false)
|
|
174
|
+
} catch (e) {
|
|
175
|
+
exception = e
|
|
176
|
+
}
|
|
177
|
+
c_expect(buildR).to.be.null
|
|
178
|
+
c_expect(exception).to.not.be.null
|
|
179
|
+
expect(context.done).not.toBeCalled()
|
|
180
|
+
expect(context.succeed).not.toBeCalled()
|
|
181
|
+
expect(context.fail).not.toBeCalled()
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
test('Failure exception to transaction context as RAW and null body', async () => {
|
|
185
|
+
const b = null
|
|
186
|
+
const r = new Response<any>(400, b, {
|
|
187
|
+
rawBody: true,
|
|
188
|
+
throwOnErrors: true,
|
|
189
|
+
})
|
|
190
|
+
const t = observableTransaction()
|
|
191
|
+
const context = t['context']
|
|
192
|
+
let buildR: any = null,
|
|
193
|
+
exception = null
|
|
194
|
+
try {
|
|
195
|
+
buildR = await r.build(context, t, false)
|
|
196
|
+
} catch (e) {
|
|
197
|
+
exception = e
|
|
198
|
+
}
|
|
199
|
+
c_expect(buildR).to.be.null
|
|
200
|
+
c_expect(exception).to.not.be.null
|
|
201
|
+
expect(context.done).not.toBeCalled()
|
|
202
|
+
expect(context.succeed).not.toBeCalled()
|
|
203
|
+
expect(context.fail).not.toBeCalled()
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
test('Failure exception to transaction context as RAW and custom ero', async () => {
|
|
207
|
+
const b = { message: 'abc', error: 'error 123' }
|
|
208
|
+
const r = new Response<any>(400, b, {
|
|
209
|
+
rawBody: true,
|
|
210
|
+
throwOnErrors: true,
|
|
211
|
+
})
|
|
212
|
+
const t = observableTransaction()
|
|
213
|
+
const context = t['context']
|
|
214
|
+
let buildR: any = null,
|
|
215
|
+
exception = null
|
|
216
|
+
try {
|
|
217
|
+
buildR = await r.build(context, t, false)
|
|
218
|
+
} catch (e) {
|
|
219
|
+
exception = e
|
|
220
|
+
}
|
|
221
|
+
c_expect(buildR).to.be.null
|
|
222
|
+
c_expect(exception).to.not.be.null
|
|
223
|
+
expect(context.done).not.toBeCalled()
|
|
224
|
+
expect(context.succeed).not.toBeCalled()
|
|
225
|
+
expect(context.fail).not.toBeCalled()
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
describe('Response shortcuts', () => {
|
|
230
|
+
test('MissingParamResponse', async () => {
|
|
231
|
+
const pName = 'abc'
|
|
232
|
+
const r = Response.MissingParamResponse(pName)
|
|
233
|
+
await testResponse(r, {
|
|
234
|
+
err: `Invalid request. Path parameter ${pName} is missing.`,
|
|
235
|
+
errCode: Globals.ErrorCode_MissingParam,
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
test('MissingQueryResponse', async () => {
|
|
240
|
+
const pName = 'abc'
|
|
241
|
+
const r = Response.MissingQueryResponse(pName)
|
|
242
|
+
await testResponse(r, {
|
|
243
|
+
err: `Invalid request. Query parameter ${pName} is missing.`,
|
|
244
|
+
errCode: Globals.ErrorCode_MissingParam,
|
|
245
|
+
})
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
test('BadRequestResponse', async () => {
|
|
249
|
+
const message = 'abc'
|
|
250
|
+
const code = 'CODE'
|
|
251
|
+
const optBody = { additional: 123 }
|
|
252
|
+
const r = Response.BadRequestResponse(message, code, optBody)
|
|
253
|
+
await testResponse(r, {
|
|
254
|
+
err: message,
|
|
255
|
+
errCode: code,
|
|
256
|
+
...optBody,
|
|
257
|
+
})
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
test('BadRequestResponse no opts', async () => {
|
|
261
|
+
const message = 'abc'
|
|
262
|
+
const r = Response.BadRequestResponse(message)
|
|
263
|
+
await testResponse(r, {
|
|
264
|
+
err: message,
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
test('BadRequestResponseWithRollback', async () => {
|
|
269
|
+
const message = 'abc'
|
|
270
|
+
const code = 'CODE'
|
|
271
|
+
const optBody = { additional: 123 }
|
|
272
|
+
const r = Response.BadRequestResponseWithRollback(message, code, optBody)
|
|
273
|
+
await testResponse(r, {
|
|
274
|
+
err: message,
|
|
275
|
+
rollback: true,
|
|
276
|
+
errCode: code,
|
|
277
|
+
...optBody,
|
|
278
|
+
})
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
test('BadRequestResponseWithRollback no opts', async () => {
|
|
282
|
+
const message = 'abc'
|
|
283
|
+
const r = Response.BadRequestResponseWithRollback(message)
|
|
284
|
+
await testResponse(r, {
|
|
285
|
+
err: message,
|
|
286
|
+
rollback: true,
|
|
287
|
+
})
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
test('UnauthorizedResponse', async () => {
|
|
291
|
+
const message = 'abc'
|
|
292
|
+
const code = 'CODE'
|
|
293
|
+
const r = Response.UnauthorizedResponse(message, code)
|
|
294
|
+
await testResponse(
|
|
295
|
+
r,
|
|
296
|
+
{
|
|
297
|
+
err: message,
|
|
298
|
+
errCode: code,
|
|
299
|
+
},
|
|
300
|
+
401
|
|
301
|
+
)
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
test('UnauthorizedResponse no code', async () => {
|
|
305
|
+
const message = 'abc'
|
|
306
|
+
const r = Response.UnauthorizedResponse(message)
|
|
307
|
+
await testResponse(r, { err: message }, 401)
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
test('SuccessResponse', async () => {
|
|
311
|
+
const body = { additional: 123 }
|
|
312
|
+
const r = Response.SuccessResponse(body)
|
|
313
|
+
await testResponse(r, body, 200)
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
test('SuccessResponse null body', async () => {
|
|
317
|
+
const r = Response.SuccessResponse(null)
|
|
318
|
+
await testResponse(r, {}, 200)
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
test('SuccessNoContentResponse', async () => {
|
|
322
|
+
const r = Response.SuccessNoContentResponse()
|
|
323
|
+
await testResponse(r, null, 204)
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
test('SimpleResponse', async () => {
|
|
327
|
+
const r = Response.SimpleResponse(null)
|
|
328
|
+
await testResponse(r, null, 200)
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
test('SimpleResponse override statuscode', async () => {
|
|
332
|
+
const r = Response.SimpleResponse(null, 203)
|
|
333
|
+
await testResponse(r, null, 203)
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
test('RedirectResponse', async () => {
|
|
337
|
+
const url = 'https://google.com'
|
|
338
|
+
const r = Response.RedirectResponse(url)
|
|
339
|
+
await testResponse(r, null, 302, { Location: url })
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
test('SuccessStreamResponse', async () => {
|
|
343
|
+
const b = { name: 'abc' }
|
|
344
|
+
const r = Response.SuccessStreamResponse(b, 'test-stream')
|
|
345
|
+
const t = observableTransaction()
|
|
346
|
+
const context = t['context']
|
|
347
|
+
const buildR = await r.build(context, t, false)
|
|
348
|
+
await r.build(context, t, false) //pipe twice, should not affect
|
|
349
|
+
c_expect(buildR).to.be.undefined
|
|
350
|
+
expect(context.fail).not.toBeCalled()
|
|
351
|
+
expect(context.done).not.toBeCalled()
|
|
352
|
+
expect(context.succeed).toHaveBeenCalledTimes(1)
|
|
353
|
+
expect(context.succeed).toHaveBeenCalledWith({
|
|
354
|
+
statusCode: 200,
|
|
355
|
+
headers: {
|
|
356
|
+
...defaultHeaders,
|
|
357
|
+
'Content-Type': 'test-stream',
|
|
358
|
+
Connection: 'keep-alive',
|
|
359
|
+
},
|
|
360
|
+
body: {
|
|
361
|
+
...b,
|
|
362
|
+
},
|
|
363
|
+
})
|
|
364
|
+
})
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
export {}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { expect } from 'chai'
|
|
2
|
+
|
|
3
|
+
import Utils from '../../src/Util/Utils'
|
|
4
|
+
|
|
5
|
+
describe('isHybridlessContainer', () => {
|
|
6
|
+
test('Simple isHybridlessContainer test', () => {
|
|
7
|
+
const v = Utils.isHybridlessContainer()
|
|
8
|
+
expect(v).to.be.a('boolean')
|
|
9
|
+
// this is done, so tests are reliable based on the testing .env
|
|
10
|
+
expect(v).to.be[process.env.HYBRIDLESS_RUNTIME ? 'true' : 'false']
|
|
11
|
+
})
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
describe('isValidString', () => {
|
|
15
|
+
test('Empty string is not valid', () => {
|
|
16
|
+
const v = Utils.isValidString('')
|
|
17
|
+
expect(v).to.be.a('boolean')
|
|
18
|
+
expect(v).to.be.false
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('Number is not a valid string', () => {
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
const v = Utils.isValidString(12)
|
|
24
|
+
expect(v).to.be.a('boolean')
|
|
25
|
+
expect(v).to.be.false
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('Simple string is valid', () => {
|
|
29
|
+
const v = Utils.isValidString('abc')
|
|
30
|
+
expect(v).to.be.a('boolean')
|
|
31
|
+
expect(v).to.be.true
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
describe('parseIntNullIfNaN', () => {
|
|
36
|
+
test('Null if only chars', () => {
|
|
37
|
+
const v = Utils.parseIntNullIfNaN('abc')
|
|
38
|
+
expect(v).to.be.null
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('Null if chars with numbers', () => {
|
|
42
|
+
const v = Utils.parseIntNullIfNaN('abc123')
|
|
43
|
+
expect(v).to.be.null
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('Null if null', () => {
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
const v = Utils.parseIntNullIfNaN(null)
|
|
49
|
+
expect(v).to.be.null
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test('Not null if starts with numbers (js behavior)', () => {
|
|
53
|
+
const v = Utils.parseIntNullIfNaN('123abc')
|
|
54
|
+
expect(v).to.be.a('number')
|
|
55
|
+
expect(v).to.be.equals(123)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('Not null if numbers', () => {
|
|
59
|
+
const v = Utils.parseIntNullIfNaN('123')
|
|
60
|
+
expect(v).to.be.a('number')
|
|
61
|
+
expect(v).to.be.equals(123)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('Not null if number type', () => {
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
const v = Utils.parseIntNullIfNaN(123)
|
|
67
|
+
expect(v).to.be.a('number')
|
|
68
|
+
expect(v).to.be.equals(123)
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
describe('parseObjectNullIfEmpty', () => {
|
|
73
|
+
test('Null if only chars', () => {
|
|
74
|
+
const v = Utils.parseObjectNullIfEmpty('abc')
|
|
75
|
+
expect(v).to.be.null
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('Null if chars with numbers', () => {
|
|
79
|
+
const v = Utils.parseObjectNullIfEmpty('abc123')
|
|
80
|
+
expect(v).to.be.null
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('Null if null', () => {
|
|
84
|
+
// @ts-ignore
|
|
85
|
+
const v = Utils.parseObjectNullIfEmpty(null)
|
|
86
|
+
expect(v).to.be.null
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('Null if malformed object', () => {
|
|
90
|
+
const v = Utils.parseObjectNullIfEmpty('{d: 123}')
|
|
91
|
+
expect(v).to.be.null
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('Null if empty object', () => {
|
|
95
|
+
const v = Utils.parseObjectNullIfEmpty('{}')
|
|
96
|
+
expect(v).to.be.null
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('Not null if object with a key', () => {
|
|
100
|
+
const v = Utils.parseObjectNullIfEmpty('{"d": 123}')
|
|
101
|
+
expect(v).to.be.a('object')
|
|
102
|
+
expect(v?.['d']).to.be.equals(123)
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
describe('isValidNumber', () => {
|
|
107
|
+
test('Not a valid number if only chars', () => {
|
|
108
|
+
const v = Utils.isValidNumber('abc')
|
|
109
|
+
expect(v).to.be.false
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test('Not a valid number if only chars and numbers', () => {
|
|
113
|
+
const v = Utils.isValidNumber('abc123')
|
|
114
|
+
expect(v).to.be.false
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
test('Not a valid number if causes a crash on conversion', () => {
|
|
118
|
+
// @ts-ignore
|
|
119
|
+
const v = Utils.isValidNumber({
|
|
120
|
+
toString: () => {
|
|
121
|
+
throw new Error('Evil object')
|
|
122
|
+
},
|
|
123
|
+
})
|
|
124
|
+
expect(v).to.be.false
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('Valid number if numbers and chars after', () => {
|
|
128
|
+
const v = Utils.isValidNumber('123abc')
|
|
129
|
+
expect(v).to.be.true
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('Valid number if numbers', () => {
|
|
133
|
+
const v = Utils.isValidNumber('123')
|
|
134
|
+
expect(v).to.be.true
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
describe('caseInsensitiveObjectForKey', () => {
|
|
139
|
+
test('Get a key that is lowercase, asking uppercase', () => {
|
|
140
|
+
const v = Utils.caseInsensitiveObjectForKey({ abc: 123 }, 'ABC')
|
|
141
|
+
expect(v).to.be.a('number')
|
|
142
|
+
expect(v).to.be.equals(123)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('Get a key that is uppercase, asking lowercase', () => {
|
|
146
|
+
const v = Utils.caseInsensitiveObjectForKey({ ABC: 123 }, 'abc')
|
|
147
|
+
expect(v).to.be.a('number')
|
|
148
|
+
expect(v).to.be.equals(123)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
test('Fails gracefully if key is not found', () => {
|
|
152
|
+
const v = Utils.caseInsensitiveObjectForKey({ ABC: 123 }, 'asd')
|
|
153
|
+
expect(v).to.be.null
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('Fails gracefully for null object', () => {
|
|
157
|
+
const v = Utils.caseInsensitiveObjectForKey(null, 'abc')
|
|
158
|
+
expect(v).to.be.null
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('Fails gracefully for invalid object', () => {
|
|
162
|
+
const v = Utils.caseInsensitiveObjectForKey('', 'abc')
|
|
163
|
+
expect(v).to.be.null
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
export {}
|