@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.
- package/.github/workflows/npmpublish.yml +11 -19
- package/.github/workflows/prs.yml +13 -0
- package/jest.config.ts +39 -0
- package/package.json +15 -4
- package/src/API/Request.ts +120 -10
- package/src/API/Response.ts +236 -8
- package/src/API/Utils.ts +56 -1
- package/src/BaseEvent/EventProcessor.ts +84 -11
- package/src/BaseEvent/Process.ts +62 -1
- package/src/BaseEvent/Transaction.ts +5 -8
- package/src/Config/Configuration.ts +111 -5
- package/src/Config/EnvironmentVar.ts +90 -1
- package/src/Crypto/Crypto.ts +77 -18
- package/src/Crypto/JWT.ts +49 -3
- package/src/Globals.ts +141 -3
- package/src/Logger/Logger.ts +173 -19
- package/src/Mailer/Mailer.ts +95 -0
- package/src/Publisher/Publisher.ts +50 -4
- package/src/Server/RouteResolver.ts +142 -0
- package/src/Server/Router.ts +77 -0
- package/src/Server/lib/ContainerServer.ts +48 -1
- package/src/Server/lib/Server.ts +78 -38
- package/src/Server/lib/container/GenericHandler.ts +7 -5
- package/src/Server/lib/container/GenericHandlerEvent.ts +59 -17
- package/src/Server/lib/container/HealthHandler.ts +1 -1
- package/src/Server/lib/container/Proxy.ts +92 -11
- package/src/Server/lib/container/Utils.ts +16 -25
- package/src/Validation/Validator.ts +18 -2
- package/tests/API/Request.test.ts +263 -0
- package/tests/API/Response.test.ts +372 -0
- package/tests/API/Utils.test.ts +157 -0
- package/tests/BaseEvent/EventProcessor.test.ts +278 -0
- package/tests/BaseEvent/Process.test.ts +49 -0
- package/tests/BaseEvent/Transaction.test.ts +231 -0
- package/tests/Config/Config.test.ts +193 -0
- package/tests/Config/EnvironmentVar.test.ts +223 -0
- package/tests/Crypto/Crypto.test.ts +90 -0
- package/tests/Crypto/JWT.test.ts +92 -0
- package/tests/Logger/Logger.test.ts +108 -0
- package/tests/Mailer/Mailer.test.ts +67 -0
- package/tests/Publisher/Publisher.test.ts +60 -0
- package/tests/Server/RouteResolver.test.ts +106 -0
- package/tests/Server/Router.test.ts +38 -0
- package/tests/Server/lib/ContainerServer.test.ts +329 -0
- package/tests/Server/lib/Server.test.ts +12 -0
- package/tests/Server/lib/container/GenericHandler.test.ts +141 -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 +278 -0
- package/tests/Server/lib/container/Utils.test.ts +48 -0
- package/tests/Test.utils.ts +95 -0
- package/tests/Validation/Validator.test.ts +88 -0
- package/tests/main.test.ts +15 -0
- package/tsconfig.json +1 -0
- package/dist/index.d.ts +0 -11
- package/dist/index.js +0 -24
- package/dist/index.js.map +0 -1
- package/dist/package.json +0 -53
- package/dist/src/API/Request.d.ts +0 -21
- package/dist/src/API/Request.js +0 -86
- package/dist/src/API/Request.js.map +0 -1
- package/dist/src/API/Response.d.ts +0 -39
- package/dist/src/API/Response.js +0 -232
- package/dist/src/API/Response.js.map +0 -1
- package/dist/src/API/Utils.d.ts +0 -8
- package/dist/src/API/Utils.js +0 -49
- package/dist/src/API/Utils.js.map +0 -1
- package/dist/src/BaseEvent/EventProcessor.d.ts +0 -13
- package/dist/src/BaseEvent/EventProcessor.js +0 -151
- package/dist/src/BaseEvent/EventProcessor.js.map +0 -1
- package/dist/src/BaseEvent/Process.d.ts +0 -12
- package/dist/src/BaseEvent/Process.js +0 -114
- package/dist/src/BaseEvent/Process.js.map +0 -1
- package/dist/src/BaseEvent/Transaction.d.ts +0 -29
- package/dist/src/BaseEvent/Transaction.js +0 -248
- package/dist/src/BaseEvent/Transaction.js.map +0 -1
- package/dist/src/Config/Configuration.d.ts +0 -34
- package/dist/src/Config/Configuration.js +0 -93
- package/dist/src/Config/Configuration.js.map +0 -1
- package/dist/src/Config/EnvironmentVar.d.ts +0 -17
- package/dist/src/Config/EnvironmentVar.js +0 -152
- package/dist/src/Config/EnvironmentVar.js.map +0 -1
- package/dist/src/Crypto/Crypto.d.ts +0 -8
- package/dist/src/Crypto/Crypto.js +0 -84
- package/dist/src/Crypto/Crypto.js.map +0 -1
- package/dist/src/Crypto/JWT.d.ts +0 -16
- package/dist/src/Crypto/JWT.js +0 -49
- package/dist/src/Crypto/JWT.js.map +0 -1
- package/dist/src/Globals.d.ts +0 -21
- package/dist/src/Globals.js +0 -35
- package/dist/src/Globals.js.map +0 -1
- package/dist/src/Logger/Logger.d.ts +0 -34
- package/dist/src/Logger/Logger.js +0 -345
- package/dist/src/Logger/Logger.js.map +0 -1
- package/dist/src/Mailer/Mailer.d.ts +0 -12
- package/dist/src/Mailer/Mailer.js +0 -234
- package/dist/src/Mailer/Mailer.js.map +0 -1
- package/dist/src/Publisher/Publisher.d.ts +0 -10
- package/dist/src/Publisher/Publisher.js +0 -109
- package/dist/src/Publisher/Publisher.js.map +0 -1
- package/dist/src/Server/Router.d.ts +0 -27
- package/dist/src/Server/Router.js +0 -22
- package/dist/src/Server/Router.js.map +0 -1
- package/dist/src/Server/lib/ContainerServer.d.ts +0 -11
- package/dist/src/Server/lib/ContainerServer.js +0 -103
- package/dist/src/Server/lib/ContainerServer.js.map +0 -1
- package/dist/src/Server/lib/Server.d.ts +0 -9
- package/dist/src/Server/lib/Server.js +0 -141
- package/dist/src/Server/lib/Server.js.map +0 -1
- package/dist/src/Server/lib/container/GenericHandler.d.ts +0 -4
- package/dist/src/Server/lib/container/GenericHandler.js +0 -136
- package/dist/src/Server/lib/container/GenericHandler.js.map +0 -1
- package/dist/src/Server/lib/container/GenericHandlerEvent.d.ts +0 -14
- package/dist/src/Server/lib/container/GenericHandlerEvent.js +0 -164
- package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +0 -1
- package/dist/src/Server/lib/container/HealthHandler.d.ts +0 -3
- package/dist/src/Server/lib/container/HealthHandler.js +0 -44
- package/dist/src/Server/lib/container/HealthHandler.js.map +0 -1
- package/dist/src/Server/lib/container/Proxy.d.ts +0 -15
- package/dist/src/Server/lib/container/Proxy.js +0 -157
- package/dist/src/Server/lib/container/Proxy.js.map +0 -1
- package/dist/src/Server/lib/container/Utils.d.ts +0 -6
- package/dist/src/Server/lib/container/Utils.js +0 -109
- package/dist/src/Server/lib/container/Utils.js.map +0 -1
- package/dist/src/Validation/Validator.d.ts +0 -5
- package/dist/src/Validation/Validator.js +0 -31
- package/dist/src/Validation/Validator.js.map +0 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { SESClient, SendRawEmailCommand } from "@aws-sdk/client-ses"
|
|
2
|
+
import { mockClient } from "aws-sdk-client-mock"
|
|
3
|
+
import { expect } from "chai"
|
|
4
|
+
|
|
5
|
+
import Mailer from "../../src/Mailer/Mailer"
|
|
6
|
+
|
|
7
|
+
const SESMock = mockClient(SESClient)
|
|
8
|
+
|
|
9
|
+
describe("SendRaw", () => {
|
|
10
|
+
// reset mock
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
SESMock.reset()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const provider = new Mailer("dev+tests@creator.co", "ca-central-1")
|
|
16
|
+
|
|
17
|
+
test("Send raw with success", async () => {
|
|
18
|
+
const messageId = "id-123"
|
|
19
|
+
SESMock.on(SendRawEmailCommand).resolves({
|
|
20
|
+
MessageId: messageId,
|
|
21
|
+
})
|
|
22
|
+
const res = await provider.sendRawEmail(
|
|
23
|
+
"test@test.com",
|
|
24
|
+
"My message",
|
|
25
|
+
"My subject",
|
|
26
|
+
)
|
|
27
|
+
expect(res).is.not.null
|
|
28
|
+
console.log(res)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test("Send raw with success", async () => {
|
|
32
|
+
const messageId = "id-123"
|
|
33
|
+
const from = "test@test.com"
|
|
34
|
+
const to = "test@test2.com"
|
|
35
|
+
const msg = "My message"
|
|
36
|
+
const subject = "My subject"
|
|
37
|
+
const cc = "test@test3.com"
|
|
38
|
+
const replyTo = "test@test4.com"
|
|
39
|
+
SESMock.on(SendRawEmailCommand).resolves({
|
|
40
|
+
MessageId: messageId,
|
|
41
|
+
})
|
|
42
|
+
const res = await provider.sendRawEmail(to, msg, subject, cc, from, replyTo)
|
|
43
|
+
expect(res).is.not.null
|
|
44
|
+
console.log(res)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test("Send raw with failure", async () => {
|
|
48
|
+
SESMock.on(SendRawEmailCommand).rejects(new Error("failed!"))
|
|
49
|
+
let res: any = null,
|
|
50
|
+
err: any = null
|
|
51
|
+
try {
|
|
52
|
+
res = await provider.sendRawEmail(
|
|
53
|
+
"test@test.com",
|
|
54
|
+
"My message",
|
|
55
|
+
"My subject",
|
|
56
|
+
)
|
|
57
|
+
} catch (e) {
|
|
58
|
+
err = e
|
|
59
|
+
}
|
|
60
|
+
expect(res).is.null
|
|
61
|
+
expect(err?.message).to.be.equals("failed!")
|
|
62
|
+
expect(res).is.null
|
|
63
|
+
console.log(res)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
export {}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { SNSClient, PublishCommand } from "@aws-sdk/client-sns"
|
|
2
|
+
import { mockClient } from "aws-sdk-client-mock"
|
|
3
|
+
import { expect } from "chai"
|
|
4
|
+
|
|
5
|
+
import Publisher from "../../src/Publisher/Publisher"
|
|
6
|
+
|
|
7
|
+
const SNSMock = mockClient(SNSClient)
|
|
8
|
+
|
|
9
|
+
describe("Encryption", () => {
|
|
10
|
+
// reset mock
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
SNSMock.reset()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const provider = new Publisher({
|
|
16
|
+
region: "ca-central-1",
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test("Publishes with success", async () => {
|
|
20
|
+
const msg = { text: "123" }
|
|
21
|
+
const topic = "123"
|
|
22
|
+
const messageId = "id-123"
|
|
23
|
+
SNSMock.on(PublishCommand, {
|
|
24
|
+
Message: JSON.stringify(msg),
|
|
25
|
+
TopicArn: topic,
|
|
26
|
+
}).resolves({
|
|
27
|
+
MessageId: messageId,
|
|
28
|
+
})
|
|
29
|
+
const res = await provider.publishOnTopic(msg, topic)
|
|
30
|
+
expect(res).is.not.null
|
|
31
|
+
expect(res.MessageId).to.be.equals(messageId)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test("Publishes with success (additional props)", async () => {
|
|
35
|
+
const msg = { text: "123" }
|
|
36
|
+
const topic = "123"
|
|
37
|
+
const messageId = "id-123"
|
|
38
|
+
SNSMock.on(PublishCommand, {
|
|
39
|
+
Message: JSON.stringify(msg),
|
|
40
|
+
TopicArn: topic,
|
|
41
|
+
}).resolves({
|
|
42
|
+
MessageId: messageId,
|
|
43
|
+
})
|
|
44
|
+
const res = await provider.publishOnTopic(msg, topic, {
|
|
45
|
+
FifoGroup: 123,
|
|
46
|
+
})
|
|
47
|
+
expect(res).is.not.null
|
|
48
|
+
expect(res.MessageId).to.be.equals(messageId)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test("Publish failure", async () => {
|
|
52
|
+
const msg = { text: "123" }
|
|
53
|
+
const topic = "123"
|
|
54
|
+
SNSMock.on(PublishCommand).rejects(new Error("failed!"))
|
|
55
|
+
const res = await provider.publishOnTopic(msg, topic)
|
|
56
|
+
expect(res).is.null
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
export {}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Route } from "../../src/Server/Router"
|
|
2
|
+
import RouteResolver from "../../src/Server/RouteResolver"
|
|
3
|
+
|
|
4
|
+
const mockRoute = (method: Method, path: string) =>
|
|
5
|
+
({
|
|
6
|
+
method: method,
|
|
7
|
+
path: path,
|
|
8
|
+
}) as any as Route
|
|
9
|
+
|
|
10
|
+
type Method =
|
|
11
|
+
| Lowercase<"GET" | "POST" | "PUT" | "DELETE">
|
|
12
|
+
| Uppercase<"GET" | "POST" | "PUT" | "DELETE">
|
|
13
|
+
|
|
14
|
+
describe("RouteResolver", () => {
|
|
15
|
+
test("no routes configured", () => {
|
|
16
|
+
parameterizedTest({}, () => [
|
|
17
|
+
["GET", "/", undefined],
|
|
18
|
+
["GET", "", undefined],
|
|
19
|
+
["GET", "hjdah", undefined],
|
|
20
|
+
])
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test("one route, case insensitive", () => {
|
|
24
|
+
parameterizedTest(
|
|
25
|
+
{
|
|
26
|
+
route: mockRoute("get", "/"),
|
|
27
|
+
},
|
|
28
|
+
(routes) => [
|
|
29
|
+
["GET", "/", routes.route],
|
|
30
|
+
["get", "/", routes.route],
|
|
31
|
+
["GET", "", routes.route],
|
|
32
|
+
["GET", "hjdah", undefined],
|
|
33
|
+
["POST", "/", undefined],
|
|
34
|
+
["DELETE", "/", undefined],
|
|
35
|
+
],
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test("basic matching", () => {
|
|
40
|
+
parameterizedTest(
|
|
41
|
+
{
|
|
42
|
+
getBase: mockRoute("GET", "/"),
|
|
43
|
+
getA: mockRoute("GET", "/a"),
|
|
44
|
+
getB: mockRoute("GET", "/b"),
|
|
45
|
+
postBase: mockRoute("POST", "/"),
|
|
46
|
+
postA: mockRoute("POST", "/a"),
|
|
47
|
+
variable: mockRoute("GET", "/:a"),
|
|
48
|
+
getAb: mockRoute("GET", "/a/b"),
|
|
49
|
+
},
|
|
50
|
+
(routes) => [
|
|
51
|
+
["GET", "/", routes.getBase],
|
|
52
|
+
["GET", "/a", routes.getA],
|
|
53
|
+
["GET", "/b", routes.getB],
|
|
54
|
+
["POST", "/", routes.postBase],
|
|
55
|
+
["POST", "/a", routes.postA],
|
|
56
|
+
["GET", "/c", routes.variable],
|
|
57
|
+
["GET", "/a/b", routes.getAb],
|
|
58
|
+
],
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
test("path variables", () => {
|
|
63
|
+
parameterizedTest(
|
|
64
|
+
{
|
|
65
|
+
path_vars: mockRoute("get", "/base/:a/:b/:c"),
|
|
66
|
+
abc: mockRoute("get", "/base/a/b/c"),
|
|
67
|
+
abcd: mockRoute("get", "/base/a/b/c/d"),
|
|
68
|
+
abc_path: mockRoute("get", "/base/a/b/c/:d"),
|
|
69
|
+
},
|
|
70
|
+
(routes) => [
|
|
71
|
+
["GET", "/base/1/2/3", routes.path_vars],
|
|
72
|
+
["GET", "/base/a/b/c", routes.abc],
|
|
73
|
+
["GET", "/base/a/b/c/d", routes.abcd],
|
|
74
|
+
["GET", "/base/a/b/c/u", routes.abc_path],
|
|
75
|
+
["GET", "/base/a/b", undefined],
|
|
76
|
+
["GET", "/base/a/b/c/d/e", undefined],
|
|
77
|
+
["GET", "/base/a/b/c/d/e/f", undefined],
|
|
78
|
+
],
|
|
79
|
+
)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
test("fails to construct with duplicate routes", () => {
|
|
83
|
+
expect(
|
|
84
|
+
() =>
|
|
85
|
+
new RouteResolver({
|
|
86
|
+
routes: [
|
|
87
|
+
mockRoute("GET", "/a/b/c/:d/:e/b"),
|
|
88
|
+
mockRoute("GET", "/a/b/c/:jshj/:e/b"),
|
|
89
|
+
],
|
|
90
|
+
}),
|
|
91
|
+
).toThrowError("Duplicate route: GET: /a/b/c/:jshj/:e/b")
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const parameterizedTest = <T extends { [k: string]: Route }>(
|
|
96
|
+
routes: T,
|
|
97
|
+
tests: (routes: T) => [Method, string, Route?][],
|
|
98
|
+
) => {
|
|
99
|
+
const underTest = new RouteResolver({
|
|
100
|
+
routes: Object.values(routes),
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
tests(routes).forEach(([method, path, expected]) =>
|
|
104
|
+
expect(underTest.resolveRoute(method, path)).toBe(expected),
|
|
105
|
+
)
|
|
106
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { expect } from "chai"
|
|
2
|
+
|
|
3
|
+
import ContainerServer from "../../src/Server/lib/ContainerServer"
|
|
4
|
+
import Server from "../../src/Server/lib/Server"
|
|
5
|
+
import Router from "../../src/Server/Router"
|
|
6
|
+
|
|
7
|
+
describe("Router basics", () => {
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
let mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
|
|
10
|
+
beforeAll(() => {
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
|
|
13
|
+
})
|
|
14
|
+
afterAll(() => {
|
|
15
|
+
mockExit.mockRestore()
|
|
16
|
+
})
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
mockExit.mockReset()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test("Serverless server", async () => {
|
|
22
|
+
process.env["HYBRIDLESS_RUNTIME"] = undefined
|
|
23
|
+
const router = new Router({ routes: [] })
|
|
24
|
+
expect(router.getExport()).to.not.be.undefined
|
|
25
|
+
expect(router["server"]).to.be.an.instanceof(Server)
|
|
26
|
+
expect(router["server"]).to.not.be.an.instanceof(ContainerServer)
|
|
27
|
+
})
|
|
28
|
+
test("Container server", async () => {
|
|
29
|
+
process.env["HYBRIDLESS_RUNTIME"] = "true"
|
|
30
|
+
const router = new Router({ routes: [] })
|
|
31
|
+
expect(router.getExport()).to.not.be.undefined
|
|
32
|
+
expect(router["server"]).to.be.an.instanceof(Server)
|
|
33
|
+
expect(router["server"]).to.be.an.instanceof(ContainerServer)
|
|
34
|
+
await router["server"]["stop"]()
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
export {}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { expect as j_expect } from "@jest/globals"
|
|
2
|
+
import { expect } from "chai"
|
|
3
|
+
import * as request from "supertest"
|
|
4
|
+
import { z } from "zod"
|
|
5
|
+
|
|
6
|
+
import Response from "../../../src/API/Response"
|
|
7
|
+
import Globals from "../../../src/Globals"
|
|
8
|
+
import ContainerServer from "../../../src/Server/lib/ContainerServer"
|
|
9
|
+
import { defaultUrl } from "../../Test.utils"
|
|
10
|
+
|
|
11
|
+
export const ViewSchema = z.object({
|
|
12
|
+
id: z.string(),
|
|
13
|
+
content: z.string(),
|
|
14
|
+
createdAt: z.string(),
|
|
15
|
+
updatedAt: z.string(),
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
describe("Container server routing", () => {
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
let mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
|
|
21
|
+
beforeAll(() => {
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
|
|
24
|
+
})
|
|
25
|
+
afterAll(() => {
|
|
26
|
+
mockExit.mockRestore()
|
|
27
|
+
})
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
mockExit.mockReset()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test("Health & 404 handler", async () => {
|
|
33
|
+
const server = new ContainerServer({ routes: [] })
|
|
34
|
+
await server.start()
|
|
35
|
+
// Health check
|
|
36
|
+
const res = await request(defaultUrl)
|
|
37
|
+
.get(Globals.Listener_HTTP_DefaultHealthCheckRoute)
|
|
38
|
+
.expect("Content-Type", "text/html; charset=utf-8")
|
|
39
|
+
.expect(200)
|
|
40
|
+
expect(res.text).to.be.equals("Healthy!")
|
|
41
|
+
// Not handled
|
|
42
|
+
await request(defaultUrl)
|
|
43
|
+
.get(`/abc`)
|
|
44
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
45
|
+
.expect(404)
|
|
46
|
+
|
|
47
|
+
// Unload
|
|
48
|
+
await server.stop("Error")
|
|
49
|
+
j_expect(mockExit).toHaveBeenCalledTimes(1)
|
|
50
|
+
j_expect(mockExit).toBeCalledWith(1)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test("Simple route", async () => {
|
|
54
|
+
const server = new ContainerServer({
|
|
55
|
+
routes: [
|
|
56
|
+
{
|
|
57
|
+
path: "/abc",
|
|
58
|
+
method: "get",
|
|
59
|
+
handler: async () => {
|
|
60
|
+
return Response.SimpleResponse({ name: "abc" })
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
})
|
|
65
|
+
await server.start()
|
|
66
|
+
// Health check
|
|
67
|
+
const res = await request(defaultUrl)
|
|
68
|
+
.get(Globals.Listener_HTTP_DefaultHealthCheckRoute)
|
|
69
|
+
.expect("Content-Type", "text/html; charset=utf-8")
|
|
70
|
+
.expect(200)
|
|
71
|
+
expect(res.text).to.be.equals("Healthy!")
|
|
72
|
+
// Found route
|
|
73
|
+
const resG = await request(defaultUrl)
|
|
74
|
+
.get(`/abc`)
|
|
75
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
76
|
+
.expect(200)
|
|
77
|
+
expect(resG.body["name"]).to.be.deep.equals("abc")
|
|
78
|
+
expect(resG.body["transactionID"]).to.not.be.null
|
|
79
|
+
// Found route, but not method
|
|
80
|
+
await request(defaultUrl)
|
|
81
|
+
.post(`/abc`)
|
|
82
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
83
|
+
.expect(404)
|
|
84
|
+
// Not found route
|
|
85
|
+
await request(defaultUrl)
|
|
86
|
+
.get(`/abc/123`)
|
|
87
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
88
|
+
.expect(404)
|
|
89
|
+
// Unload
|
|
90
|
+
await server.stop("Error")
|
|
91
|
+
j_expect(mockExit).toHaveBeenCalledTimes(1)
|
|
92
|
+
j_expect(mockExit).toBeCalledWith(1)
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
describe("Container server basics", () => {
|
|
97
|
+
// @ts-ignore
|
|
98
|
+
let mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
|
|
99
|
+
beforeAll(() => {
|
|
100
|
+
// @ts-ignore
|
|
101
|
+
mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
|
|
102
|
+
})
|
|
103
|
+
afterAll(() => {
|
|
104
|
+
mockExit.mockRestore()
|
|
105
|
+
})
|
|
106
|
+
beforeEach(() => {
|
|
107
|
+
mockExit.mockReset()
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test("Starts with exports", async () => {
|
|
111
|
+
const server = new ContainerServer({ routes: [] })
|
|
112
|
+
server.getExport()
|
|
113
|
+
return new Promise((resolve) => {
|
|
114
|
+
setTimeout(async () => {
|
|
115
|
+
// Health check
|
|
116
|
+
const res = await request(defaultUrl)
|
|
117
|
+
.get(Globals.Listener_HTTP_DefaultHealthCheckRoute)
|
|
118
|
+
.expect("Content-Type", "text/html; charset=utf-8")
|
|
119
|
+
.expect(200)
|
|
120
|
+
expect(res.text).to.be.equals("Healthy!")
|
|
121
|
+
// Unload
|
|
122
|
+
await server.stop()
|
|
123
|
+
j_expect(mockExit).toHaveBeenCalledTimes(1)
|
|
124
|
+
j_expect(mockExit).toBeCalledWith(0)
|
|
125
|
+
resolve(null)
|
|
126
|
+
}, 2000)
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
test("Stops if process sends message SIGINT", async () => {
|
|
131
|
+
const server = new ContainerServer({ routes: [] })
|
|
132
|
+
await server.start()
|
|
133
|
+
process.emit("SIGINT")
|
|
134
|
+
return new Promise((resolve) => {
|
|
135
|
+
setTimeout(async () => {
|
|
136
|
+
j_expect(mockExit).toHaveBeenCalledTimes(1)
|
|
137
|
+
j_expect(mockExit).toBeCalledWith(0)
|
|
138
|
+
resolve(null)
|
|
139
|
+
}, 2000)
|
|
140
|
+
})
|
|
141
|
+
}, 10000)
|
|
142
|
+
|
|
143
|
+
test("Stops if process sends message unhandledRejection", async () => {
|
|
144
|
+
const server = new ContainerServer({ routes: [] })
|
|
145
|
+
await server.start()
|
|
146
|
+
// @ts-ignore
|
|
147
|
+
process.emit("unhandledRejection")
|
|
148
|
+
return new Promise((resolve) => {
|
|
149
|
+
setTimeout(async () => {
|
|
150
|
+
j_expect(mockExit).toHaveBeenCalledTimes(1)
|
|
151
|
+
j_expect(mockExit).toBeCalledWith(0)
|
|
152
|
+
resolve(null)
|
|
153
|
+
}, 2000)
|
|
154
|
+
})
|
|
155
|
+
}, 10000)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
describe("Container server validation", () => {
|
|
159
|
+
// @ts-ignore
|
|
160
|
+
let mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
|
|
161
|
+
beforeAll(() => {
|
|
162
|
+
// @ts-ignore
|
|
163
|
+
mockExit = jest.spyOn(process, "exit").mockImplementation(() => {})
|
|
164
|
+
})
|
|
165
|
+
afterAll(() => {
|
|
166
|
+
mockExit.mockRestore()
|
|
167
|
+
})
|
|
168
|
+
beforeEach(() => {
|
|
169
|
+
mockExit.mockReset()
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
function validateValidationFailure(res: any, failureCount?: number) {
|
|
173
|
+
expect(res.body["err"]).to.be.equals(Globals.ErrorResponseValidationFail)
|
|
174
|
+
expect(res.body["errCode"]).to.be.equals(Globals.ErrorCode_InvalidInput)
|
|
175
|
+
expect(res.body["transactionID"]).to.not.be.null
|
|
176
|
+
expect(res.body["transactionID"]).to.be.an("string")
|
|
177
|
+
expect(res.body["validationFailure"]?.length).to.be.equals(
|
|
178
|
+
failureCount || 4,
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
test("Validates empty body", async () => {
|
|
183
|
+
const server = new ContainerServer({
|
|
184
|
+
routes: [
|
|
185
|
+
{
|
|
186
|
+
path: "/abc",
|
|
187
|
+
method: "post",
|
|
188
|
+
inputSchema: ViewSchema,
|
|
189
|
+
handler: async () => {
|
|
190
|
+
return Response.SimpleResponse({ name: "abc" })
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
})
|
|
195
|
+
await server.start()
|
|
196
|
+
// Validation fails, empty body
|
|
197
|
+
const resG = await request(defaultUrl)
|
|
198
|
+
.post(`/abc`)
|
|
199
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
200
|
+
.expect(400)
|
|
201
|
+
validateValidationFailure(resG)
|
|
202
|
+
await server.stop()
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
test("Validates empty string body", async () => {
|
|
206
|
+
const server = new ContainerServer({
|
|
207
|
+
routes: [
|
|
208
|
+
{
|
|
209
|
+
path: "/abc",
|
|
210
|
+
method: "post",
|
|
211
|
+
inputSchema: ViewSchema,
|
|
212
|
+
handler: async () => {
|
|
213
|
+
return Response.SimpleResponse({ name: "abc" })
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
})
|
|
218
|
+
await server.start()
|
|
219
|
+
// Validation fails, empty body
|
|
220
|
+
const resG = await request(defaultUrl)
|
|
221
|
+
.post(`/abc`)
|
|
222
|
+
.send("")
|
|
223
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
224
|
+
.expect(400)
|
|
225
|
+
validateValidationFailure(resG)
|
|
226
|
+
await server.stop()
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
test("Validates empty object body", async () => {
|
|
230
|
+
const server = new ContainerServer({
|
|
231
|
+
routes: [
|
|
232
|
+
{
|
|
233
|
+
path: "/abc",
|
|
234
|
+
method: "post",
|
|
235
|
+
inputSchema: ViewSchema,
|
|
236
|
+
handler: async () => {
|
|
237
|
+
return Response.SimpleResponse({ name: "abc" })
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
})
|
|
242
|
+
await server.start()
|
|
243
|
+
// Validation fails, empty body
|
|
244
|
+
const resG = await request(defaultUrl)
|
|
245
|
+
.post(`/abc`)
|
|
246
|
+
.send({})
|
|
247
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
248
|
+
.expect(400)
|
|
249
|
+
validateValidationFailure(resG)
|
|
250
|
+
await server.stop()
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
test("Validates missing props body", async () => {
|
|
254
|
+
const server = new ContainerServer({
|
|
255
|
+
routes: [
|
|
256
|
+
{
|
|
257
|
+
path: "/abc",
|
|
258
|
+
method: "post",
|
|
259
|
+
inputSchema: ViewSchema,
|
|
260
|
+
handler: async () => {
|
|
261
|
+
return Response.SimpleResponse({ name: "abc" })
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
})
|
|
266
|
+
await server.start()
|
|
267
|
+
// Validation fails, empty body
|
|
268
|
+
const resG = await request(defaultUrl)
|
|
269
|
+
.post(`/abc`)
|
|
270
|
+
.send({ id: "123" })
|
|
271
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
272
|
+
.expect(400)
|
|
273
|
+
validateValidationFailure(resG, 3)
|
|
274
|
+
await server.stop()
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
test("Validates wrong type props body", async () => {
|
|
278
|
+
const server = new ContainerServer({
|
|
279
|
+
routes: [
|
|
280
|
+
{
|
|
281
|
+
path: "/abc",
|
|
282
|
+
method: "post",
|
|
283
|
+
inputSchema: ViewSchema,
|
|
284
|
+
handler: async () => {
|
|
285
|
+
return Response.SimpleResponse({ name: "abc" })
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
],
|
|
289
|
+
})
|
|
290
|
+
await server.start()
|
|
291
|
+
// Validation fails, empty body
|
|
292
|
+
const resG = await request(defaultUrl)
|
|
293
|
+
.post(`/abc`)
|
|
294
|
+
.send({ id: 123 })
|
|
295
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
296
|
+
.expect(400)
|
|
297
|
+
validateValidationFailure(resG)
|
|
298
|
+
await server.stop()
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
test("Validates successfully", async () => {
|
|
302
|
+
const server = new ContainerServer({
|
|
303
|
+
routes: [
|
|
304
|
+
{
|
|
305
|
+
path: "/abc",
|
|
306
|
+
method: "post",
|
|
307
|
+
inputSchema: ViewSchema,
|
|
308
|
+
handler: async () => {
|
|
309
|
+
return Response.SimpleResponse({ name: "abc" })
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
})
|
|
314
|
+
await server.start()
|
|
315
|
+
// Validation fails, empty body
|
|
316
|
+
await request(defaultUrl)
|
|
317
|
+
.post(`/abc`)
|
|
318
|
+
.send({
|
|
319
|
+
id: "123",
|
|
320
|
+
content: "123",
|
|
321
|
+
createdAt: new Date(),
|
|
322
|
+
updatedAt: new Date(),
|
|
323
|
+
})
|
|
324
|
+
.expect("Content-Type", "application/json; charset=utf-8")
|
|
325
|
+
.expect(200)
|
|
326
|
+
await server.stop()
|
|
327
|
+
})
|
|
328
|
+
})
|
|
329
|
+
export {}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { expect } from "chai"
|
|
2
|
+
|
|
3
|
+
import Server from "../../../src/Server/lib/Server"
|
|
4
|
+
|
|
5
|
+
describe("Server basics", () => {
|
|
6
|
+
test("Works", async () => {
|
|
7
|
+
const server = new Server({ routes: [] })
|
|
8
|
+
expect(server.getExport()).to.not.be.undefined
|
|
9
|
+
})
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
export {}
|