@tsed/platform-test-sdk
Version:
Package to test platform adapter integration with Ts.ED
579 lines (578 loc) • 21.8 kB
JavaScript
import { __decorate, __metadata, __param } from "tslib";
import "@tsed/ajv";
import { Controller } from "@tsed/di";
import { PlatformTest } from "@tsed/platform-http/testing";
import { BodyParams, Context, HeaderParams, RawBodyParams } from "@tsed/platform-params";
import { Consumes, Default, Description, GenericOf, Generics, Maximum, Minimum, Nullable, Post, Property, Required, Status } from "@tsed/schema";
import SuperTest from "supertest";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["TITLE"] = 0] = "TITLE";
MyEnum[MyEnum["AGE"] = 1] = "AGE";
})(MyEnum || (MyEnum = {}));
class NestedModel {
}
__decorate([
Property(),
__metadata("design:type", String)
], NestedModel.prototype, "id", void 0);
class NullModel {
}
__decorate([
Property(),
__metadata("design:type", String)
], NullModel.prototype, "prop1", void 0);
__decorate([
Property(),
__metadata("design:type", Number)
], NullModel.prototype, "prop2", void 0);
__decorate([
Property(),
__metadata("design:type", Date)
], NullModel.prototype, "prop3", void 0);
__decorate([
Nullable(NestedModel),
__metadata("design:type", NestedModel)
], NullModel.prototype, "prop4", void 0);
class FindQuery {
}
__decorate([
Property(),
__metadata("design:type", String)
], FindQuery.prototype, "a", void 0);
__decorate([
Property(),
__metadata("design:type", String)
], FindQuery.prototype, "b", void 0);
let PaginationQuery = class PaginationQuery {
};
__decorate([
Minimum(0),
Default(0),
__metadata("design:type", Number)
], PaginationQuery.prototype, "offset", void 0);
__decorate([
Minimum(1),
Maximum(1000),
Default(50),
__metadata("design:type", Number)
], PaginationQuery.prototype, "limit", void 0);
__decorate([
Property("T"),
__metadata("design:type", Object)
], PaginationQuery.prototype, "where", void 0);
PaginationQuery = __decorate([
Generics("T")
], PaginationQuery);
class Param1Type {
}
__decorate([
Required(),
__metadata("design:type", String)
], Param1Type.prototype, "value1", void 0);
class Param2Type {
}
__decorate([
Required(),
__metadata("design:type", String)
], Param2Type.prototype, "value2", void 0);
export class TestModel {
}
__decorate([
Required(),
__metadata("design:type", String)
], TestModel.prototype, "name", void 0);
let TestBodyParamsCtrl = class TestBodyParamsCtrl {
testScenario1(contentType, payload) {
return { payload, contentType };
}
testScenario2(value) {
return { value };
}
testScenario3(value) {
return { value };
}
testScenario4(value) {
return { value };
}
testScenario4b(value) {
return { value };
}
testScenario4c(value) {
return { value };
}
testScenario5(raw, payload, context) {
return { value: raw.toString("utf8") };
}
testScenario6(type) {
return { type };
}
testScenario7(value) {
return { value };
}
testScenario8(model) {
return { model };
}
testScenario9(q) {
return { q };
}
testScenario10(param1, param2) {
return { param1, param2 };
}
testScenario11(client_id) {
return { client_id };
}
testScenario12(payload) {
return { payload };
}
};
__decorate([
Post("/scenario-1"),
Status(201),
Description("retrieve body and header content-type"),
__param(0, HeaderParams("Content-type")),
__param(1, BodyParams()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", void 0)
], TestBodyParamsCtrl.prototype, "testScenario1", null);
__decorate([
Post("/scenario-2"),
Description("Extract field from body payload as string[]"),
__param(0, BodyParams("test")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array]),
__metadata("design:returntype", Object)
], TestBodyParamsCtrl.prototype, "testScenario2", null);
__decorate([
Post("/scenario-3"),
Description("Extract body payload as string[]"),
__param(0, BodyParams()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array]),
__metadata("design:returntype", Object)
], TestBodyParamsCtrl.prototype, "testScenario3", null);
__decorate([
Post("/scenario-4"),
Description("Extract field from body payload as string[] with required annotation"),
__param(0, Required()),
__param(0, BodyParams("test")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array]),
__metadata("design:returntype", Object)
], TestBodyParamsCtrl.prototype, "testScenario4", null);
__decorate([
Post("/scenario-4b"),
Description("Extract field from body payload as string"),
__param(0, Required()),
__param(0, BodyParams("test")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Object)
], TestBodyParamsCtrl.prototype, "testScenario4b", null);
__decorate([
Post("/scenario-4c"),
Description("Extract field from body payload as number with required annotation"),
__param(0, Required()),
__param(0, BodyParams("test")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number]),
__metadata("design:returntype", Object)
], TestBodyParamsCtrl.prototype, "testScenario4c", null);
__decorate([
Post("/scenario-5"),
Description("Extract raw body payload as Buffer"),
__param(0, RawBodyParams()),
__param(1, BodyParams()),
__param(2, Context()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Buffer, Object, Object]),
__metadata("design:returntype", Object)
], TestBodyParamsCtrl.prototype, "testScenario5", null);
__decorate([
Post("/scenario-6"),
__param(0, BodyParams("type", String)),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Object)
], TestBodyParamsCtrl.prototype, "testScenario6", null);
__decorate([
Post("/scenario-7"),
__param(0, BodyParams("test")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Object)
], TestBodyParamsCtrl.prototype, "testScenario7", null);
__decorate([
Post("/scenario-8"),
__param(0, BodyParams()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [NullModel]),
__metadata("design:returntype", void 0)
], TestBodyParamsCtrl.prototype, "testScenario8", null);
__decorate([
Post("/scenario-9"),
__param(0, BodyParams()),
__param(0, GenericOf(FindQuery)),
__metadata("design:type", Function),
__metadata("design:paramtypes", [PaginationQuery]),
__metadata("design:returntype", void 0)
], TestBodyParamsCtrl.prototype, "testScenario9", null);
__decorate([
Post("/scenario-10"),
__param(0, Required()),
__param(0, BodyParams("param1", Param1Type)),
__param(1, Required()),
__param(1, BodyParams("param2", Param2Type)),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Param1Type,
Param2Type]),
__metadata("design:returntype", void 0)
], TestBodyParamsCtrl.prototype, "testScenario10", null);
__decorate([
Post("/scenario-11"),
Consumes("application/x-www-form-urlencoded"),
__param(0, Required()),
__param(0, BodyParams("client_id")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", void 0)
], TestBodyParamsCtrl.prototype, "testScenario11", null);
__decorate([
Post("/scenario-12"),
Description("Test payload given to BodyParams with any type to emulate metadata less behavior"),
__param(0, BodyParams(TestModel)),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], TestBodyParamsCtrl.prototype, "testScenario12", null);
TestBodyParamsCtrl = __decorate([
Controller("/body-params")
], TestBodyParamsCtrl);
export function testBodyParams(options) {
let request;
beforeAll(PlatformTest.bootstrap(options.server, {
...options,
mount: {
"/rest": [TestBodyParamsCtrl]
}
}));
beforeAll(() => {
request = SuperTest(PlatformTest.callback());
});
afterAll(PlatformTest.reset);
describe("Scenario 1: POST /rest/body-params/scenario-1", () => {
it("should return a 201 response", async () => {
const response = await request
.post("/rest/body-params/scenario-1")
.set({
"Content-Type": "application/json"
})
.send({
id: "id"
})
.expect(201);
expect(response.body).toEqual({
contentType: "application/json",
payload: {
id: "id"
}
});
});
});
describe("Scenario2: with expression Array<string>", () => {
it("should return value", async () => {
const response = await request
.post("/rest/body-params/scenario-2")
.send({
test: ["value"]
})
.expect(200);
expect(response.body).toEqual({ value: ["value"] });
});
it("should return an empty array (1)", async () => {
const response = await request.post("/rest/body-params/scenario-2").send().expect(200);
expect(response.body).toEqual({});
});
it("should return an empty value (2)", async () => {
const response = await request.post("/rest/body-params/scenario-2").send({}).expect(200);
expect(response.body).toEqual({});
});
});
describe("Scenario3: without expression Array<string>", () => {
it("should return value", async () => {
const response = await request.post("/rest/body-params/scenario-3").send(["value"]).expect(200);
expect(response.body).toEqual({ value: ["value"] });
});
it("should return an empty array (1)", async () => {
const response = await request.post("/rest/body-params/scenario-3").send({}).expect(200);
expect(response.body).toEqual({ value: [{}] });
});
});
describe("Scenario4: with expression required Array<string>", () => {
it("should return value", async () => {
const response = await request
.post("/rest/body-params/scenario-4")
.send({ test: ["value"] })
.expect(200);
expect(response.body).toEqual({ value: ["value"] });
});
it("should throw an exception", async () => {
const response = await request.post("/rest/body-params/scenario-4").send().expect(400);
expect(response.body).toEqual({
name: "REQUIRED_VALIDATION_ERROR",
message: "Bad request on parameter \"request.body.test\".\nIt should have required parameter 'test'",
status: 400,
errors: [
{
requestPath: "body",
dataPath: ".test",
keyword: "required",
message: "It should have required parameter 'test'",
modelName: "body",
params: { missingProperty: "test" },
schemaPath: "#/required"
}
]
});
});
});
describe("Scenario4b: with expression required String", () => {
it("should return value", async () => {
const response = await request.post("/rest/body-params/scenario-4b").send({ test: "value" }).expect(200);
expect(response.body).toEqual({ value: "value" });
});
it("should throw an exception when nothing is sent", async () => {
const response = await request.post("/rest/body-params/scenario-4b").send().expect(400);
expect(response.body).toEqual({
name: "REQUIRED_VALIDATION_ERROR",
message: "Bad request on parameter \"request.body.test\".\nIt should have required parameter 'test'",
status: 400,
errors: [
{
requestPath: "body",
dataPath: ".test",
keyword: "required",
message: "It should have required parameter 'test'",
modelName: "body",
params: { missingProperty: "test" },
schemaPath: "#/required"
}
]
});
});
it("should throw an exception when nothing is an empty string is sent", async () => {
const response = await request.post("/rest/body-params/scenario-4b").send({ test: "" }).expect(400);
expect(response.body).toEqual({
name: "REQUIRED_VALIDATION_ERROR",
message: "Bad request on parameter \"request.body.test\".\nIt should have required parameter 'test'",
status: 400,
errors: [
{
dataPath: ".test",
requestPath: "body",
keyword: "required",
message: "It should have required parameter 'test'",
modelName: "body",
params: { missingProperty: "test" },
schemaPath: "#/required"
}
]
});
});
});
describe("Scenario4c: with expression required Number", () => {
it("should return value (with 1)", async () => {
const response = await request.post("/rest/body-params/scenario-4c").send({ test: 1 }).expect(200);
expect(response.body).toEqual({ value: 1 });
});
it("should return value (with 0)", async () => {
const response = await request.post("/rest/body-params/scenario-4c").send({ test: 0 }).expect(200);
expect(response.body).toEqual({ value: 0 });
});
it("should throw an exception when nothing is sent", async () => {
const response = await request.post("/rest/body-params/scenario-4b").send().expect(400);
expect(response.body).toEqual({
name: "REQUIRED_VALIDATION_ERROR",
message: "Bad request on parameter \"request.body.test\".\nIt should have required parameter 'test'",
status: 400,
errors: [
{
dataPath: ".test",
requestPath: "body",
keyword: "required",
message: "It should have required parameter 'test'",
modelName: "body",
params: { missingProperty: "test" },
schemaPath: "#/required"
}
]
});
});
});
describe("Scenario5: with raw payload", () => {
it("should return value", async () => {
const response = await request.post("/rest/body-params/scenario-5").send('{"test": ["value"]}').expect(200);
expect(response.body).toEqual({
value: '{"test": ["value"]}'
});
});
});
describe("Scenario6: Enum", () => {
it("should return value", async () => {
const response = await request.post("/rest/body-params/scenario-6").send({
type: "TITLE"
});
expect(response.body).toEqual({
type: "TITLE"
});
});
});
describe("Scenario7: payload with Null", () => {
it("should return value", async () => {
const response = await request.post("/rest/body-params/scenario-7").send({
test: null
});
expect(response.body).toEqual({
value: null
});
});
});
describe("Scenario8: payload with props to null", () => {
it("should return value with null value", async () => {
const response = await request.post("/rest/body-params/scenario-8").send({
prop1: null,
prop2: null,
prop3: null,
prop4: null
});
expect(response.body).toEqual({
model: {
prop1: null,
prop2: null,
prop3: null,
prop4: null
}
});
});
});
describe("Scenario9: payload with Generics", () => {
it("should return value", async () => {
const response = await request
.post("/rest/body-params/scenario-9")
.send({
offset: 0,
limit: 10,
where: {
a: "ca",
b: "cb"
}
})
.expect(200);
expect(response.body).toEqual({
q: {
limit: 10,
offset: 0,
where: {
a: "ca",
b: "cb"
}
}
});
});
it("should throw a bad request", async () => {
const response = await request
.post("/rest/body-params/scenario-9")
.send({
offset: 0,
limit: 0,
where: {
a: "ca",
b: "cb"
}
})
.expect(400);
expect(response.body).toEqual({
errors: [
{
data: 0,
requestPath: "body",
dataPath: ".limit",
instancePath: "/limit",
keyword: "minimum",
message: "must be >= 1",
modelName: "PaginationQuery",
params: {
comparison: ">=",
limit: 1
},
schemaPath: "#/definitions/PaginationQuery/properties/limit/minimum"
}
],
message: 'Bad request on parameter "request.body".\nPaginationQuery.limit must be >= 1. Given value: 0',
name: "AJV_VALIDATION_ERROR",
status: 400
});
});
});
describe("Scenario10: validate two payload", () => {
it("should throw a Bad request if body params is missing (1)", async () => {
await request
.post("/rest/body-params/scenario-10")
.send({ param1: {}, param2: { value2: "value" } })
.expect(400);
});
it("should throw a Bad request if body params is missing (2)", async () => {
await request.post("/rest/body-params/scenario-10").send({ param1: {}, param2: {} }).expect(400);
});
it("should throw a Bad request if body params is missing (3)", async () => {
await request
.post("/rest/body-params/scenario-10")
.send({ param1: { value: "value" }, param2: {} })
.expect(400);
});
it("should throw a Bad request if body params is missing (4)", async () => {
await request.post("/rest/body-params/scenario-10").send({}).expect(400);
});
it("should validate the body params", async () => {
await request
.post("/rest/body-params/scenario-10")
.send({ param1: { value1: "value" }, param2: { value2: "value" } })
.expect(200);
});
});
describe("Scenario11: validate application/x-www-form-urlencoded body", () => {
it("should validate the body params", async () => {
await request
.post("/rest/body-params/scenario-11")
.set("Content-Type", "application/x-www-form-urlencoded")
.send("client_id=id&grant_type=grant")
.expect(200);
});
});
describe("Scenario12: validate payload with any type", () => {
it("should throw a Bad Request if the payload is invalid", async () => {
const response = await request.post("/rest/body-params/scenario-12").send({}).expect(400);
expect(response.body).toEqual({
errors: [
{
dataPath: ".name",
instancePath: "",
keyword: "required",
message: "must have required property 'name'",
modelName: "TestModel",
params: {
missingProperty: "name"
},
requestPath: "body",
schemaPath: "#/required"
}
],
message: 'Bad request on parameter "request.body".\nTestModel must have required property \'name\'. Given value: "undefined"',
name: "AJV_VALIDATION_ERROR",
status: 400
});
});
});
}