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