UNPKG

@tsed/platform-test-sdk

Version:
579 lines (578 loc) 21.8 kB
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 }); }); }); }