diff --git a/test/fixtures/.redocly.yml b/test/fixtures/.redocly.yml index 5ff6072..e6c192a 100644 --- a/test/fixtures/.redocly.yml +++ b/test/fixtures/.redocly.yml @@ -10,3 +10,7 @@ apis: root: ./path-fragments.api.yml openapi-ts: output: ./path-fragments.api.ts + request-body: + root: ./request-body.api.yml + openapi-ts: + output: ./request-body.api.ts diff --git a/test/fixtures/request-body.api.yml b/test/fixtures/request-body.api.yml new file mode 100644 index 0000000..52e655e --- /dev/null +++ b/test/fixtures/request-body.api.yml @@ -0,0 +1,71 @@ +openapi: 3.0.2 +info: + title: Request Body API + version: 1.0.0 +servers: + - url: http://localhost:3000 +paths: + /resource: + get: + summary: Get Resource + operationId: getResource + responses: + 200: + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/Resource" + post: + summary: Create Resource + operationId: createResource + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/NewResource" + responses: + 201: + description: Created + content: + application/json: + schema: + $ref: "#/components/schemas/Resource" + patch: + summary: Patch Resource + operationId: patchResource + requestBody: + required: false + content: + application/json: + schema: + $ref: "#/components/schemas/NewResource" + responses: + 200: + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/Resource" +components: + schemas: + Resource: + allOf: + - $ref: "#/components/schemas/NewResource" + - type: object + required: + - id + properties: + id: + type: string + NewResource: + type: object + required: + - name + - value + properties: + name: + type: string + value: + type: integer diff --git a/test/no-content.test.ts b/test/no-content.test.ts index da2c7b1..485992e 100644 --- a/test/no-content.test.ts +++ b/test/no-content.test.ts @@ -3,7 +3,7 @@ import { describe, expect, expectTypeOf, test } from "vitest"; import { createOpenApiHttp } from "../exports/main.js"; import type { paths } from "./fixtures/no-content.api.js"; -describe("Given an OpenAPI schema with a no-content endpoint", () => { +describe("Given an OpenAPI schema endpoint with no-content", () => { const http = createOpenApiHttp({ baseUrl: "*" }); test("When the DELETE method is mocked, Then empty responses can be returned", async () => { diff --git a/test/path-fragments.test.ts b/test/path-fragments.test.ts index 94b2e6d..01d4f3e 100644 --- a/test/path-fragments.test.ts +++ b/test/path-fragments.test.ts @@ -3,7 +3,7 @@ import { createOpenApiHttp } from "../exports/main.js"; import type { paths } from "./fixtures/path-fragments.api.js"; import { HttpResponse } from "msw"; -describe("Given an OpenAPI schema with an endpoint that contains path fragments", () => { +describe("Given an OpenAPI schema endpoint that contains path fragments", () => { const http = createOpenApiHttp({ baseUrl: "*" }); test("When a endpoint is mocked, Then OpenAPI path fragments can be parsed by the handler", async () => { diff --git a/test/request-body.test.ts b/test/request-body.test.ts new file mode 100644 index 0000000..738fb75 --- /dev/null +++ b/test/request-body.test.ts @@ -0,0 +1,58 @@ +import { describe, expect, expectTypeOf, test } from "vitest"; +import { createOpenApiHttp } from "../src/openapi-http.js"; +import type { paths } from "./fixtures/request-body.api.js"; +import { HttpResponse, type StrictRequest } from "msw"; + +describe("Given an OpenAPI schema endpoint with request content", () => { + const http = createOpenApiHttp({ baseUrl: "*" }); + + test("When a request contains content, Then the content can be used in the response", async () => { + const request = new Request(new URL("/resource", "http://localhost:3000"), { + method: "post", + body: JSON.stringify({ name: "test-name", value: 16 }), + }); + + const handler = http.post("/resource", async ({ request }) => { + const newResource = await request.json(); + return HttpResponse.json( + { ...newResource, id: "test-id" }, + { status: 201 }, + ); + }); + const result = await handler.run({ request }); + + const responseBody = await result?.response?.json(); + expect(result?.response?.status).toBe(201); + expect(responseBody).toStrictEqual({ + id: "test-id", + name: "test-name", + value: 16, + }); + }); + + test("When a request is expected to contain content, Then the content is strict-typed", () => { + type Endpoint = typeof http.post<"/resource">; + const resolver = expectTypeOf().parameter(1); + const request = resolver.parameter(0).toHaveProperty("request"); + + request.toEqualTypeOf>(); + }); + + test("When a request content is optional, Then the content is strict-typed with optional", () => { + type Endpoint = typeof http.patch<"/resource">; + const resolver = expectTypeOf().parameter(1); + const request = resolver.parameter(0).toHaveProperty("request"); + + request.toEqualTypeOf< + StrictRequest<{ name: string; value: number } | undefined> + >(); + }); + + test("When a request is not expected to contain content, Then the content is undefined", () => { + type Endpoint = typeof http.get<"/resource">; + const resolver = expectTypeOf().parameter(1); + const request = resolver.parameter(0).toHaveProperty("request"); + + request.toEqualTypeOf>(); + }); +});