From 4fed1906acea6273691c05cdfdcdacf469ec9936 Mon Sep 17 00:00:00 2001 From: Patrick McElhaney Date: Tue, 28 May 2024 12:52:47 -0400 Subject: [PATCH] expand .json() to include text/json and XML; fixes #918 --- .changeset/hungry-emus-hope.md | 5 +++++ docs/usage.md | 6 +++--- src/server/response-builder.ts | 6 +++++- src/server/types.d.ts | 2 +- test/server/response-builder.test.ts | 10 ++++++++++ 5 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 .changeset/hungry-emus-hope.md diff --git a/.changeset/hungry-emus-hope.md b/.changeset/hungry-emus-hope.md new file mode 100644 index 00000000..ab412948 --- /dev/null +++ b/.changeset/hungry-emus-hope.md @@ -0,0 +1,5 @@ +--- +"counterfact": minor +--- + +expand the .json() shortcut to include variations of JSON and XML content types diff --git a/docs/usage.md b/docs/usage.md index c0fd3681..dc32d638 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -111,9 +111,9 @@ The `$.response` object is used to build a valid response for the URL and reques - `.random()` returns random data, using `examples` and other metadata from the OpenAPI document. - `.header(name, value)` adds a response header. It will only show up when a response header is expected and you haven't already provided it. - `.match(contentType, content)` is used to return content which matches the content type. If the API is intended to serve one of multiple content types, depending on the client's `Accepts:` header, you can chain multiple `match()` calls. -- `.json(content)` is shorthand for `.match("application/json", content)` -- `.text(content)` is shorthand for `.match("text/plain", content)` -- `.html(content)` is shorthand for `.match("text/html", content)` + - `.json(content)`, `.text(content)`, `.html(content)`, and `.xml(content)` are shorthands for the `match()` function, e.g. `.text(content)` is shorthand for `.match("text/plain", content)`. + - if the content type is XML, you can pass a JSON object, and Counterfact will automatically convert it to XML for you + - The `.json()` shortcut handles both JSON and XML. You can build a response by chaining one or more of these functions, e.g. diff --git a/src/server/response-builder.ts b/src/server/response-builder.ts index 70cdc524..0f7a408b 100644 --- a/src/server/response-builder.ts +++ b/src/server/response-builder.ts @@ -72,7 +72,11 @@ export function createResponseBuilder( }, json(this: ResponseBuilder, body: unknown) { - return this.match("application/json", body); + return this.match("application/json", body) + .match("text/json", body) + .match("text/x-json", body) + .match("application/xml", body) + .match("text/xml", body); }, match( diff --git a/src/server/types.d.ts b/src/server/types.d.ts index f992a176..9b10f35d 100644 --- a/src/server/types.d.ts +++ b/src/server/types.d.ts @@ -99,7 +99,7 @@ type GenericResponseBuilderInner< ? never : HeaderFunction; html: MaybeShortcut<"text/html", Response>; - json: MaybeShortcut<"application/json", Response>; + json: MaybeShortcut<"application/json" | "text/json" | "text/x-json" | "application/xml" | "text/xml", Response>; match: [keyof Response["content"]] extends [never] ? never : MatchFunction; diff --git a/test/server/response-builder.test.ts b/test/server/response-builder.test.ts index 6aedeae9..b861f91d 100644 --- a/test/server/response-builder.test.ts +++ b/test/server/response-builder.test.ts @@ -38,6 +38,16 @@ describe("a response builder", () => { expect(response?.content).toStrictEqual([ { body: "hello", type: "text/plain" }, { body: { hello: "world" }, type: "application/json" }, + { body: { hello: "world" }, type: "text/json" }, + { body: { hello: "world" }, type: "text/x-json" }, + { + body: "world", + type: "application/xml", + }, + { + body: "world", + type: "text/xml", + }, { body: "

Hello World

", type: "text/html" }, { body: "world",