@tsed/platform-test-sdk 8.0.1 → 8.0.3
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 +15 -14
- package/src/components/PlatformTestSdk.ts +30 -0
- package/src/data/file.txt +1 -0
- package/src/data/response.data.json +3 -0
- package/src/data/swagger.json +32 -0
- package/src/errors/CustomBadRequest.ts +16 -0
- package/src/errors/CustomInternalError.ts +16 -0
- package/src/index.ts +40 -0
- package/src/interfaces/PlatformTestingSdkOpts.ts +10 -0
- package/src/interfaces/index.ts +4 -0
- package/src/modules/feature/FeatureModule.ts +10 -0
- package/src/modules/feature/controllers/FeatureController.ts +11 -0
- package/src/tests/exports.ts +71 -0
- package/src/tests/testAcceptMime.ts +99 -0
- package/src/tests/testAuth.ts +345 -0
- package/src/tests/testBodyParams.ts +488 -0
- package/src/tests/testCache.ts +283 -0
- package/src/tests/testChildrenControllers.ts +59 -0
- package/src/tests/testCookies.ts +41 -0
- package/src/tests/testCustom404.ts +35 -0
- package/src/tests/testDeepQueryParams.ts +125 -0
- package/src/tests/testErrors.ts +233 -0
- package/src/tests/testHandlers.ts +94 -0
- package/src/tests/testHeaderParams.ts +158 -0
- package/src/tests/testHeaders.ts +78 -0
- package/src/tests/testInheritanceController.ts +206 -0
- package/src/tests/testLocals.ts +53 -0
- package/src/tests/testLocation.ts +40 -0
- package/src/tests/testMiddlewares.ts +155 -0
- package/src/tests/testModule.ts +50 -0
- package/src/tests/testMulter.ts +158 -0
- package/src/tests/testPathParams.ts +127 -0
- package/src/tests/testQueryParams.ts +238 -0
- package/src/tests/testRedirect.ts +129 -0
- package/src/tests/testResponse.ts +533 -0
- package/src/tests/testResponseFilter.ts +106 -0
- package/src/tests/testRouting.ts +71 -0
- package/src/tests/testScopeRequest.ts +116 -0
- package/src/tests/testSession.ts +108 -0
- package/src/tests/testStatics.ts +63 -0
- package/src/tests/testStream.ts +62 -0
- package/src/tests/testView.ts +74 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import {Controller} from "@tsed/di";
|
|
2
|
+
import {NotFound} from "@tsed/exceptions";
|
|
3
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
4
|
+
import {Middleware, UseAuth} from "@tsed/platform-middlewares";
|
|
5
|
+
import {BodyParams, PathParams, QueryParams} from "@tsed/platform-params";
|
|
6
|
+
import {Description, Get, MaxLength, MinLength, Post, Property, Returns, Summary} from "@tsed/schema";
|
|
7
|
+
import SuperTest from "supertest";
|
|
8
|
+
import {v4} from "uuid";
|
|
9
|
+
import {afterAll, beforeAll, describe, expect, it} from "vitest";
|
|
10
|
+
|
|
11
|
+
import {PlatformTestingSdkOpts} from "../interfaces/index.js";
|
|
12
|
+
|
|
13
|
+
export class Resource {
|
|
14
|
+
@Property()
|
|
15
|
+
id: string;
|
|
16
|
+
|
|
17
|
+
@Property()
|
|
18
|
+
@MinLength(3)
|
|
19
|
+
@MaxLength(100)
|
|
20
|
+
name: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class BaseController<T extends {id: string}> {
|
|
24
|
+
resources: T[];
|
|
25
|
+
|
|
26
|
+
@Get("/:id")
|
|
27
|
+
@Summary("Return an element by his resource")
|
|
28
|
+
get(
|
|
29
|
+
@Description("Id of the resource")
|
|
30
|
+
@PathParams("id")
|
|
31
|
+
id: string
|
|
32
|
+
): Promise<any> {
|
|
33
|
+
const resource = this.resources.find((resource) => resource.id === id);
|
|
34
|
+
|
|
35
|
+
if (!resource) {
|
|
36
|
+
return Promise.reject(new NotFound("Not found"));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return Promise.resolve(resource);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@Get("/")
|
|
43
|
+
@Summary("Return all elements from a service")
|
|
44
|
+
list(): Promise<any[]> {
|
|
45
|
+
return Promise.resolve(this.resources);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Controller("/resources")
|
|
50
|
+
export class ResourcesCtrl extends BaseController<Resource> {
|
|
51
|
+
resources = [{id: "1", name: "John"}];
|
|
52
|
+
|
|
53
|
+
@Get("/:id")
|
|
54
|
+
@Summary("Return an element by his resource")
|
|
55
|
+
async get(
|
|
56
|
+
@Description("Id of the resource")
|
|
57
|
+
@PathParams("id")
|
|
58
|
+
id: string
|
|
59
|
+
): Promise<any> {
|
|
60
|
+
const resource = await super.get(id);
|
|
61
|
+
|
|
62
|
+
resource.name = resource.name + " hello You!";
|
|
63
|
+
|
|
64
|
+
return resource;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@Post("/")
|
|
68
|
+
@(Returns(201).Type(Resource))
|
|
69
|
+
post(@BodyParams() resource: Resource) {
|
|
70
|
+
resource.id = v4();
|
|
71
|
+
this.resources.push(resource);
|
|
72
|
+
|
|
73
|
+
return resource;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@Middleware()
|
|
78
|
+
class AuthMiddleware {
|
|
79
|
+
use() {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
abstract class AttachmentController {
|
|
85
|
+
@Get("/:parentID/attachments")
|
|
86
|
+
getAll(@PathParams("parentID") parentID: string) {
|
|
87
|
+
return `All attachments of ${parentID}`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@Controller("/findings")
|
|
92
|
+
@UseAuth(AuthMiddleware)
|
|
93
|
+
export class FindingsController extends AttachmentController {
|
|
94
|
+
@Get("/")
|
|
95
|
+
get() {
|
|
96
|
+
return "hello Finding";
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export abstract class TestBaseController {
|
|
101
|
+
@Get("/")
|
|
102
|
+
scenario3(@QueryParams("search") search: string) {
|
|
103
|
+
return {
|
|
104
|
+
search
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Get("/override")
|
|
109
|
+
scenario5(@QueryParams("q") q: string) {
|
|
110
|
+
return {data: q};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@Controller("/test")
|
|
115
|
+
export class TestChildController extends TestBaseController {
|
|
116
|
+
@Get("/:id")
|
|
117
|
+
scenario4(@PathParams("id") id: string): any {
|
|
118
|
+
return {id};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@Get("/override")
|
|
122
|
+
scenario5(@QueryParams("s") s: string) {
|
|
123
|
+
return {data: s};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function testInheritanceController(options: PlatformTestingSdkOpts) {
|
|
128
|
+
let request: SuperTest.Agent;
|
|
129
|
+
|
|
130
|
+
beforeAll(
|
|
131
|
+
PlatformTest.bootstrap(options.server, {
|
|
132
|
+
...options,
|
|
133
|
+
mount: {
|
|
134
|
+
"/rest": [ResourcesCtrl, FindingsController, TestChildController]
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
);
|
|
138
|
+
beforeAll(() => {
|
|
139
|
+
request = SuperTest(PlatformTest.callback());
|
|
140
|
+
});
|
|
141
|
+
afterAll(PlatformTest.reset);
|
|
142
|
+
|
|
143
|
+
describe("Scenario 1:", () => {
|
|
144
|
+
it("should return list", async () => {
|
|
145
|
+
const {body} = await request.get("/rest/resources").expect(200);
|
|
146
|
+
|
|
147
|
+
expect(body).toEqual([{id: "1", name: "John"}]);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("should return a resource", async () => {
|
|
151
|
+
const {body} = await request.get("/rest/resources/1").expect(200);
|
|
152
|
+
|
|
153
|
+
expect(body).toEqual({
|
|
154
|
+
id: "1",
|
|
155
|
+
name: "John hello You!"
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("should add a resource", async () => {
|
|
160
|
+
const {body} = await request
|
|
161
|
+
.post("/rest/resources")
|
|
162
|
+
.send({
|
|
163
|
+
name: "july"
|
|
164
|
+
})
|
|
165
|
+
.expect(201);
|
|
166
|
+
|
|
167
|
+
expect(body.name).toEqual("july");
|
|
168
|
+
expect(typeof body.id).toBe("string");
|
|
169
|
+
|
|
170
|
+
const {body: resource} = await request.get(`/rest/resources/${body.id}`).expect(200);
|
|
171
|
+
|
|
172
|
+
expect(resource.id).toEqual(body.id);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
describe("scenario2: FindingsController", () => {
|
|
177
|
+
it("should call /rest/findings/:parentID/attachments", async () => {
|
|
178
|
+
const {text} = await request.get("/rest/findings/1/attachments").expect(200);
|
|
179
|
+
|
|
180
|
+
expect(text).toEqual("All attachments of 1");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("should call /rest/findings", async () => {
|
|
184
|
+
const {text} = await request.get("/rest/findings").expect(200);
|
|
185
|
+
|
|
186
|
+
expect(text).toEqual("hello Finding");
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("Scenario3: should call inherited method", async () => {
|
|
191
|
+
const {body} = await request.get("/rest/test?search=test").expect(200);
|
|
192
|
+
expect(body).toEqual({
|
|
193
|
+
search: "test"
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("Scenario4: should the Child method", async () => {
|
|
198
|
+
const {body} = await request.get("/rest/test/1").expect(200);
|
|
199
|
+
expect(body).toEqual({id: "1"});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("Scenario5: should call the Child method and not the base method", async () => {
|
|
203
|
+
const {body} = await request.get("/rest/test/1").expect(200);
|
|
204
|
+
expect(body).toEqual({id: "1"});
|
|
205
|
+
});
|
|
206
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {Controller} from "@tsed/di";
|
|
2
|
+
import {PlatformContext, Req} from "@tsed/platform-http";
|
|
3
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
4
|
+
import {Middleware, Use} from "@tsed/platform-middlewares";
|
|
5
|
+
import {Context, Locals} from "@tsed/platform-params";
|
|
6
|
+
import {Get} from "@tsed/schema";
|
|
7
|
+
import SuperTest from "supertest";
|
|
8
|
+
import {afterAll, beforeAll, describe, expect, it} from "vitest";
|
|
9
|
+
|
|
10
|
+
import {PlatformTestingSdkOpts} from "../interfaces/index.js";
|
|
11
|
+
|
|
12
|
+
@Middleware()
|
|
13
|
+
class LocalsMiddleware {
|
|
14
|
+
use(@Req() request: any, @Locals() locals: any, @Context() ctx: PlatformContext) {
|
|
15
|
+
locals.id = "local-10909";
|
|
16
|
+
ctx.set("uid", "ctx-10909");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Controller("/locals")
|
|
21
|
+
class LocalsCtrl {
|
|
22
|
+
@Get("/scenario-1")
|
|
23
|
+
@Use(LocalsMiddleware)
|
|
24
|
+
public testStackMiddlewares(@Locals("id") id: any, @Context("uid") uid: string): any {
|
|
25
|
+
return {
|
|
26
|
+
id: `${id}-${uid}`
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function testLocals(options: PlatformTestingSdkOpts) {
|
|
32
|
+
let request: SuperTest.Agent;
|
|
33
|
+
beforeAll(
|
|
34
|
+
PlatformTest.bootstrap(options.server, {
|
|
35
|
+
...options,
|
|
36
|
+
mount: {
|
|
37
|
+
"/rest": [LocalsCtrl]
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
);
|
|
41
|
+
beforeAll(() => {
|
|
42
|
+
request = SuperTest(PlatformTest.callback());
|
|
43
|
+
});
|
|
44
|
+
afterAll(PlatformTest.reset);
|
|
45
|
+
|
|
46
|
+
describe("Scenario 1: GET /rest/locals/scenario-1", () => {
|
|
47
|
+
it("should call middleware and set a id in locals", async () => {
|
|
48
|
+
const {body}: any = await request.get("/rest/locals/scenario-1").expect(200);
|
|
49
|
+
|
|
50
|
+
expect(body.id).toEqual("local-10909-ctx-10909");
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {Controller} from "@tsed/di";
|
|
2
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
3
|
+
import {Get, Location} from "@tsed/schema";
|
|
4
|
+
import SuperTest from "supertest";
|
|
5
|
+
import {afterAll, beforeAll, expect, it} from "vitest";
|
|
6
|
+
|
|
7
|
+
import {PlatformTestingSdkOpts} from "../interfaces/index.js";
|
|
8
|
+
|
|
9
|
+
@Controller("/location")
|
|
10
|
+
class LocationCtrl {
|
|
11
|
+
@Get("/scenario-1")
|
|
12
|
+
@Location("/test")
|
|
13
|
+
testScenario1() {
|
|
14
|
+
return "Hello";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function testLocation(options: PlatformTestingSdkOpts) {
|
|
19
|
+
let request: SuperTest.Agent;
|
|
20
|
+
|
|
21
|
+
beforeAll(
|
|
22
|
+
PlatformTest.bootstrap(options.server, {
|
|
23
|
+
...options,
|
|
24
|
+
mount: {
|
|
25
|
+
"/rest": [LocationCtrl]
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
beforeAll(() => {
|
|
30
|
+
request = SuperTest(PlatformTest.callback());
|
|
31
|
+
});
|
|
32
|
+
afterAll(PlatformTest.reset);
|
|
33
|
+
|
|
34
|
+
it("Scenario1: GET /rest/location/scenario-1", async () => {
|
|
35
|
+
const response = await request.get("/rest/location/scenario-1").expect(200);
|
|
36
|
+
|
|
37
|
+
expect(response.text).toEqual("Hello");
|
|
38
|
+
expect(response.header.location).toEqual("/test");
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import "@tsed/ajv";
|
|
2
|
+
|
|
3
|
+
import {Controller} from "@tsed/di";
|
|
4
|
+
import {BadRequest, Exception, Unauthorized} from "@tsed/exceptions";
|
|
5
|
+
import {Err} from "@tsed/platform-http";
|
|
6
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
7
|
+
import {Middleware, MiddlewareMethods, Use, UseAfter, UseBefore} from "@tsed/platform-middlewares";
|
|
8
|
+
import {Context, QueryParams} from "@tsed/platform-params";
|
|
9
|
+
import {Get} from "@tsed/schema";
|
|
10
|
+
import SuperTest from "supertest";
|
|
11
|
+
import {afterAll, beforeAll, describe, expect, it} from "vitest";
|
|
12
|
+
|
|
13
|
+
import {PlatformTestingSdkOpts} from "../interfaces/index.js";
|
|
14
|
+
|
|
15
|
+
@Middleware()
|
|
16
|
+
class BeforeCustomMiddleware {
|
|
17
|
+
use(@Context() ctx: Context) {
|
|
18
|
+
ctx.set("stacks", ["UseBefore - Ctrl"]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@Middleware()
|
|
23
|
+
class BeforeEndpointCustomMiddleware {
|
|
24
|
+
use(@Context() ctx: Context) {
|
|
25
|
+
ctx.get("stacks").push("UseBefore - endpoint");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Middleware()
|
|
30
|
+
class AfterCustomMiddleware {
|
|
31
|
+
use(@Context() ctx: Context) {
|
|
32
|
+
ctx.get("stacks").push("UseAfter - Ctrl");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Middleware()
|
|
37
|
+
class UseCustomMiddleware {
|
|
38
|
+
use(@Context() ctx: Context) {
|
|
39
|
+
ctx.get("stacks").push("Use - Ctrl");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Middleware()
|
|
44
|
+
class AfterEndpointCustomMiddleware {
|
|
45
|
+
use(@Context() ctx: Context) {
|
|
46
|
+
ctx.get("stacks").push("UseAfter - endpoint");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@Middleware()
|
|
51
|
+
class UseMiddleware {
|
|
52
|
+
use(@Context() ctx: Context) {
|
|
53
|
+
ctx.get("stacks").push("Use - Ctrl");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Middleware()
|
|
58
|
+
class UseEndpointMiddleware {
|
|
59
|
+
use(@Context() ctx: Context) {
|
|
60
|
+
ctx.get("stacks").push("Use - endpoint");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@Middleware()
|
|
65
|
+
export class CatchErrorMiddleware implements MiddlewareMethods {
|
|
66
|
+
use(@Err() err: Exception) {
|
|
67
|
+
if ([401].includes(err.status)) {
|
|
68
|
+
throw new BadRequest("Bad format");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@Controller("/middlewares")
|
|
76
|
+
@UseBefore(BeforeCustomMiddleware)
|
|
77
|
+
@UseAfter(AfterCustomMiddleware)
|
|
78
|
+
@UseAfter(CatchErrorMiddleware)
|
|
79
|
+
@Use(UseCustomMiddleware)
|
|
80
|
+
class TestMiddlewaresCtrl {
|
|
81
|
+
@Get("/scenario-1")
|
|
82
|
+
@UseBefore(BeforeEndpointCustomMiddleware)
|
|
83
|
+
@UseAfter(AfterEndpointCustomMiddleware)
|
|
84
|
+
@Use(UseEndpointMiddleware)
|
|
85
|
+
scenario1(@Context() context: Context) {
|
|
86
|
+
context.get("stacks").push("endpoint");
|
|
87
|
+
|
|
88
|
+
return {stacks: context.get("stacks")};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@Get("/scenario-2")
|
|
92
|
+
scenario2(@QueryParams("test") test: string) {
|
|
93
|
+
if (test === "error") {
|
|
94
|
+
throw new Unauthorized("Unauthorized");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
hello: "world"
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function testMiddlewares(options: PlatformTestingSdkOpts) {
|
|
104
|
+
let request: SuperTest.Agent;
|
|
105
|
+
|
|
106
|
+
beforeAll(
|
|
107
|
+
PlatformTest.bootstrap(options.server, {
|
|
108
|
+
...options,
|
|
109
|
+
mount: {
|
|
110
|
+
"/rest": [TestMiddlewaresCtrl]
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
beforeAll(() => {
|
|
115
|
+
request = SuperTest(PlatformTest.callback());
|
|
116
|
+
});
|
|
117
|
+
afterAll(PlatformTest.reset);
|
|
118
|
+
|
|
119
|
+
describe("Scenario 1: GET /rest/middlewares/scenario-1", () => {
|
|
120
|
+
it("should call all middlewares", async () => {
|
|
121
|
+
const response = await request.get("/rest/middlewares/scenario-1").expect(200);
|
|
122
|
+
|
|
123
|
+
expect(response.body).toEqual({
|
|
124
|
+
stacks: [
|
|
125
|
+
"UseBefore - Ctrl",
|
|
126
|
+
"UseBefore - endpoint",
|
|
127
|
+
"Use - Ctrl",
|
|
128
|
+
"Use - endpoint",
|
|
129
|
+
"endpoint",
|
|
130
|
+
"UseAfter - endpoint",
|
|
131
|
+
"UseAfter - Ctrl"
|
|
132
|
+
]
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
describe("Scenario 2: GET /rest/middlewares/scenario-2", () => {
|
|
137
|
+
it("should call the endpoint without triggering middleware", async () => {
|
|
138
|
+
const response = await request.get("/rest/middlewares/scenario-2").expect(200);
|
|
139
|
+
|
|
140
|
+
expect(response.body).toEqual({
|
|
141
|
+
hello: "world"
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
it("should call the endpoint, throw an error and transform the error by calling the error middleware", async () => {
|
|
145
|
+
const response = await request.get("/rest/middlewares/scenario-2?test=error").expect(400);
|
|
146
|
+
|
|
147
|
+
expect(response.body).toEqual({
|
|
148
|
+
errors: [],
|
|
149
|
+
message: "Bad format",
|
|
150
|
+
name: "BAD_REQUEST",
|
|
151
|
+
status: 400
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {Controller} from "@tsed/di";
|
|
2
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
3
|
+
import {Get} from "@tsed/schema";
|
|
4
|
+
import SuperTest from "supertest";
|
|
5
|
+
import {afterAll, beforeAll, describe, expect, it} from "vitest";
|
|
6
|
+
|
|
7
|
+
import {PlatformTestingSdkOpts} from "../interfaces/index.js";
|
|
8
|
+
import {FeatureModule} from "../modules/feature/FeatureModule.js";
|
|
9
|
+
|
|
10
|
+
@Controller("/root")
|
|
11
|
+
class TestRootCtrl {
|
|
12
|
+
@Get("/")
|
|
13
|
+
testScenario1() {
|
|
14
|
+
return "From root";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function testModule(options: PlatformTestingSdkOpts) {
|
|
19
|
+
let request: SuperTest.Agent;
|
|
20
|
+
|
|
21
|
+
beforeAll(
|
|
22
|
+
PlatformTest.bootstrap(options.server, {
|
|
23
|
+
...options,
|
|
24
|
+
mount: {
|
|
25
|
+
"/rest": [TestRootCtrl]
|
|
26
|
+
},
|
|
27
|
+
imports: [FeatureModule]
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
beforeAll(() => {
|
|
31
|
+
request = SuperTest(PlatformTest.callback());
|
|
32
|
+
});
|
|
33
|
+
afterAll(PlatformTest.reset);
|
|
34
|
+
|
|
35
|
+
describe("Scenario1: GET /rest/root", () => {
|
|
36
|
+
it("should get content from root controller", async () => {
|
|
37
|
+
const response = await request.get("/rest/root").expect(200);
|
|
38
|
+
|
|
39
|
+
expect(response.text).toEqual("From root");
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe("Scenario2: GET /rest/features", () => {
|
|
44
|
+
it("should get content from a module with his controller", async () => {
|
|
45
|
+
const response = await request.get("/rest/features").expect(200);
|
|
46
|
+
|
|
47
|
+
expect(response.text).toEqual("From feature");
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {Controller} from "@tsed/di";
|
|
2
|
+
import {MulterOptions, MultipartFile, PlatformMulterFile} from "@tsed/platform-http";
|
|
3
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
4
|
+
import {BodyParams} from "@tsed/platform-params";
|
|
5
|
+
import {CollectionOf, Post, Property, Required, Status} from "@tsed/schema";
|
|
6
|
+
import multer, {FileFilterCallback} from "multer";
|
|
7
|
+
import {dirname, join} from "path";
|
|
8
|
+
import readPkgUp from "read-pkg-up";
|
|
9
|
+
import SuperTest from "supertest";
|
|
10
|
+
import {afterAll, beforeAll, describe, expect, it, vi} from "vitest";
|
|
11
|
+
|
|
12
|
+
import {PlatformTestingSdkOpts} from "../interfaces/index.js";
|
|
13
|
+
|
|
14
|
+
const rootDir = import.meta.dirname; // automatically replaced by import.meta.dirname on build
|
|
15
|
+
|
|
16
|
+
export class Task {
|
|
17
|
+
@Property()
|
|
18
|
+
id: string;
|
|
19
|
+
|
|
20
|
+
@Property()
|
|
21
|
+
title: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class Event {
|
|
25
|
+
@Property()
|
|
26
|
+
@Required()
|
|
27
|
+
id: string;
|
|
28
|
+
|
|
29
|
+
@CollectionOf(Task)
|
|
30
|
+
tasks: Task[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const fileFilterStub = vi.fn();
|
|
34
|
+
const fileFilter = (req: any, file: PlatformMulterFile, callback: FileFilterCallback) => {
|
|
35
|
+
fileFilterStub();
|
|
36
|
+
callback(null, true);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function getFileConfig(): any {
|
|
40
|
+
return {
|
|
41
|
+
storage: multer.diskStorage({
|
|
42
|
+
destination: (req: any, _fileItem, cb) => {
|
|
43
|
+
const path = `${rootDir}/../.tmp`;
|
|
44
|
+
cb(null, path);
|
|
45
|
+
}
|
|
46
|
+
}),
|
|
47
|
+
fileFilter
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Controller("/multer")
|
|
52
|
+
export class TestMulterController {
|
|
53
|
+
@Post("/scenario-1")
|
|
54
|
+
@Status(201)
|
|
55
|
+
@MulterOptions({dest: `${rootDir}/../.tmp`})
|
|
56
|
+
uploadWithName(@Required() @MultipartFile("media") media: PlatformMulterFile) {
|
|
57
|
+
return media.originalname;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Post("/scenario-2")
|
|
61
|
+
@Status(201)
|
|
62
|
+
@MulterOptions({dest: `${rootDir}/../.tmp`})
|
|
63
|
+
uploadWithPayload(@MultipartFile("media") media: PlatformMulterFile, @BodyParams("form_id") formId: string) {
|
|
64
|
+
return {
|
|
65
|
+
file: media.originalname,
|
|
66
|
+
formId
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@Post("/scenario-3")
|
|
71
|
+
@Status(201)
|
|
72
|
+
@MulterOptions(getFileConfig())
|
|
73
|
+
uploadWithOptions(@MultipartFile("media") media: PlatformMulterFile) {
|
|
74
|
+
return {
|
|
75
|
+
file: media.originalname
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function testMulter(options: PlatformTestingSdkOpts) {
|
|
81
|
+
let request: SuperTest.Agent;
|
|
82
|
+
|
|
83
|
+
const buffer = Buffer.from("test content");
|
|
84
|
+
|
|
85
|
+
const pkg = readPkgUp.sync({
|
|
86
|
+
cwd: import.meta.dirname
|
|
87
|
+
});
|
|
88
|
+
const rootDir = join(dirname(pkg?.path || ""), "src");
|
|
89
|
+
|
|
90
|
+
beforeAll(
|
|
91
|
+
PlatformTest.bootstrap(options.server, {
|
|
92
|
+
...options,
|
|
93
|
+
mount: {
|
|
94
|
+
"/rest": [TestMulterController]
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
);
|
|
98
|
+
beforeAll(() => {
|
|
99
|
+
request = SuperTest(PlatformTest.callback());
|
|
100
|
+
});
|
|
101
|
+
afterAll(PlatformTest.reset);
|
|
102
|
+
beforeAll(() => {
|
|
103
|
+
vi.resetAllMocks();
|
|
104
|
+
});
|
|
105
|
+
describe("Scenario 1: POST /rest/multer/scenario-1", () => {
|
|
106
|
+
it("should upload file with multer", async () => {
|
|
107
|
+
const result = await request.post("/rest/multer/scenario-1").attach("media", `${rootDir}/data/file.txt`).expect(201);
|
|
108
|
+
|
|
109
|
+
expect(result.text).toEqual("file.txt");
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("should throw an exception when there is no file", async () => {
|
|
113
|
+
const result = await request.post("/rest/multer/scenario-1").expect(400);
|
|
114
|
+
|
|
115
|
+
expect(result.body).toEqual({
|
|
116
|
+
name: "REQUIRED_VALIDATION_ERROR",
|
|
117
|
+
message: "Bad request on parameter \"request.files.media.0\".\nIt should have required parameter 'media.0'",
|
|
118
|
+
status: 400,
|
|
119
|
+
errors: [
|
|
120
|
+
{
|
|
121
|
+
dataPath: ".media.0",
|
|
122
|
+
requestPath: "files",
|
|
123
|
+
keyword: "required",
|
|
124
|
+
message: "It should have required parameter 'media.0'",
|
|
125
|
+
modelName: "files",
|
|
126
|
+
params: {missingProperty: "media.0"},
|
|
127
|
+
schemaPath: "#/required"
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe("Scenario 2: POST /rest/multer/scenario-2", () => {
|
|
134
|
+
it("should upload file with multer", async () => {
|
|
135
|
+
const result = await request
|
|
136
|
+
.post("/rest/multer/scenario-2")
|
|
137
|
+
.attach("media", `${rootDir}/data/file.txt`)
|
|
138
|
+
.field({
|
|
139
|
+
form_id: "form_id"
|
|
140
|
+
})
|
|
141
|
+
.expect(201);
|
|
142
|
+
|
|
143
|
+
expect(result.body).toEqual({file: "file.txt", formId: "form_id"});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe("Scenario 3: POST /rest/multer/scenario-3", () => {
|
|
147
|
+
it("should upload file with multer", async () => {
|
|
148
|
+
const result = await request.post("/rest/multer/scenario-3").attach("media", `${rootDir}/data/file.txt`).field({}).expect(201);
|
|
149
|
+
|
|
150
|
+
expect(result.body).toEqual({
|
|
151
|
+
file: "file.txt"
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// filterFilter is called
|
|
155
|
+
expect(fileFilterStub).toBeCalled();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}
|