microsoft/typespec
Publicmirrored from https://github.com/microsoft/typespecAvailable
packages/http/test/responses.test.ts
114lines · modecode
| 1 | import { Model } from "@typespec/compiler"; |
| 2 | import { expectDiagnosticEmpty, expectDiagnostics } from "@typespec/compiler/testing"; |
| 3 | import { deepStrictEqual, ok, strictEqual } from "assert"; |
| 4 | import { compileOperations, getOperationsWithServiceNamespace } from "./test-host.js"; |
| 5 | |
| 6 | describe("http: responses", () => { |
| 7 | it("issues diagnostics for duplicate body decorator", async () => { |
| 8 | const [_, diagnostics] = await compileOperations( |
| 9 | ` |
| 10 | model Foo { |
| 11 | foo: string; |
| 12 | } |
| 13 | model Bar { |
| 14 | bar: string; |
| 15 | } |
| 16 | @route("/") |
| 17 | namespace root { |
| 18 | @get |
| 19 | op read(): { @body body1: Foo, @body body2: Bar }; |
| 20 | } |
| 21 | ` |
| 22 | ); |
| 23 | expectDiagnostics(diagnostics, [{ code: "@typespec/http/duplicate-body" }]); |
| 24 | }); |
| 25 | |
| 26 | it("issues diagnostics for invalid content types", async () => { |
| 27 | const [_, diagnostics] = await compileOperations( |
| 28 | ` |
| 29 | model Foo { |
| 30 | foo: string; |
| 31 | } |
| 32 | |
| 33 | model TextPlain { |
| 34 | contentType: "text/plain"; |
| 35 | } |
| 36 | |
| 37 | namespace root { |
| 38 | @route("/test1") |
| 39 | @get |
| 40 | op test1(): { @header contentType: string, @body body: Foo }; |
| 41 | @route("/test2") |
| 42 | @get |
| 43 | op test2(): { @header contentType: 42, @body body: Foo }; |
| 44 | @route("/test3") |
| 45 | @get |
| 46 | op test3(): { @header contentType: "application/json" | TextPlain, @body body: Foo }; |
| 47 | } |
| 48 | ` |
| 49 | ); |
| 50 | expectDiagnostics(diagnostics, [ |
| 51 | { code: "@typespec/http/content-type-string" }, |
| 52 | { code: "@typespec/http/content-type-string" }, |
| 53 | { code: "@typespec/http/content-type-string" }, |
| 54 | ]); |
| 55 | }); |
| 56 | |
| 57 | it("supports any casing for string literal 'Content-Type' header properties.", async () => { |
| 58 | const [routes, diagnostics] = await getOperationsWithServiceNamespace( |
| 59 | ` |
| 60 | model Foo {} |
| 61 | |
| 62 | @test |
| 63 | namespace Test { |
| 64 | @route("/test1") |
| 65 | @get |
| 66 | op test1(): { @header "content-Type": "text/html", @body body: Foo }; |
| 67 | |
| 68 | @route("/test2") |
| 69 | @get |
| 70 | op test2(): { @header "CONTENT-type": "text/plain", @body body: Foo }; |
| 71 | |
| 72 | @route("/test3") |
| 73 | @get |
| 74 | op test3(): { @header "content-type": "application/json", @body body: Foo }; |
| 75 | } |
| 76 | ` |
| 77 | ); |
| 78 | expectDiagnosticEmpty(diagnostics); |
| 79 | strictEqual(routes.length, 3); |
| 80 | deepStrictEqual(routes[0].responses[0].responses[0].body?.contentTypes, ["text/html"]); |
| 81 | deepStrictEqual(routes[1].responses[0].responses[0].body?.contentTypes, ["text/plain"]); |
| 82 | deepStrictEqual(routes[2].responses[0].responses[0].body?.contentTypes, ["application/json"]); |
| 83 | }); |
| 84 | |
| 85 | // Regression test for https://github.com/microsoft/typespec/issues/328 |
| 86 | it("empty response model becomes body if it has children", async () => { |
| 87 | const [routes, diagnostics] = await getOperationsWithServiceNamespace( |
| 88 | ` |
| 89 | @route("/") op read(): A; |
| 90 | |
| 91 | model A {} |
| 92 | |
| 93 | model B extends A { |
| 94 | foo: "B"; |
| 95 | b: string; |
| 96 | } |
| 97 | |
| 98 | model C extends A { |
| 99 | foo: "C"; |
| 100 | c: string; |
| 101 | } |
| 102 | |
| 103 | ` |
| 104 | ); |
| 105 | expectDiagnosticEmpty(diagnostics); |
| 106 | strictEqual(routes.length, 1); |
| 107 | const responses = routes[0].responses; |
| 108 | strictEqual(responses.length, 1); |
| 109 | const response = responses[0]; |
| 110 | const body = response.responses[0].body; |
| 111 | ok(body); |
| 112 | strictEqual((body.type as Model).name, "A"); |
| 113 | }); |
| 114 | }); |
| 115 | |