From 8c5580a0e2e6e52785b0132128c36d679ddbe5d5 Mon Sep 17 00:00:00 2001 From: Andy Dennis <195526+scruffymongrel@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:35:21 +0100 Subject: [PATCH] feat: add `HttpResponse.html()` static method (#2140) Co-authored-by: Artem Zakharchenko --- src/core/HttpResponse.test.ts | 30 ++++++++++++++++ src/core/HttpResponse.ts | 19 +++++++++++ .../rest-api/response/body/body-html.mocks.ts | 13 +++++++ .../rest-api/response/body/body-html.test.ts | 17 ++++++++++ .../rest-api/response/body-html.node.test.ts | 34 +++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 test/browser/rest-api/response/body/body-html.mocks.ts create mode 100644 test/browser/rest-api/response/body/body-html.test.ts create mode 100644 test/node/rest-api/response/body-html.node.test.ts diff --git a/src/core/HttpResponse.test.ts b/src/core/HttpResponse.test.ts index 9e7bc1cee..d88984fa0 100644 --- a/src/core/HttpResponse.test.ts +++ b/src/core/HttpResponse.test.ts @@ -223,6 +223,36 @@ describe('HttpResponse.xml()', () => { }) }) +describe('HttpResponse.html()', () => { + it('creates an html response', async () => { + const response = HttpResponse.html('

Jane Doe

') + + expect(response.status).toBe(200) + expect(response.statusText).toBe('OK') + expect(response.body).toBeInstanceOf(ReadableStream) + expect(await response.text()).toBe('

Jane Doe

') + expect(Object.fromEntries(response.headers.entries())).toEqual({ + 'content-type': 'text/html', + }) + }) + + it('allows overriding the "Content-Type" response header', async () => { + const response = HttpResponse.html('

Jane Doe

', { + headers: { + 'Content-Type': 'text/html; charset=utf-8', + }, + }) + + expect(response.status).toBe(200) + expect(response.statusText).toBe('OK') + expect(response.body).toBeInstanceOf(ReadableStream) + expect(await response.text()).toBe('

Jane Doe

') + expect(Object.fromEntries(response.headers.entries())).toEqual({ + 'content-type': 'text/html; charset=utf-8', + }) + }) +}) + it('creates an array buffer response', async () => { const buffer = new TextEncoder().encode('hello world') const response = HttpResponse.arrayBuffer(buffer) diff --git a/src/core/HttpResponse.ts b/src/core/HttpResponse.ts index 5c22ca70a..ca62ca768 100644 --- a/src/core/HttpResponse.ts +++ b/src/core/HttpResponse.ts @@ -125,6 +125,25 @@ export class HttpResponse extends Response { return new HttpResponse(body, responseInit) } + /** + * Create a `Response` with a `Content-Type: "text/html"` body. + * @example + * HttpResponse.html(`

Jane Doe

`) + * HttpResponse.html(`
Main text
`, { status: 201 }) + */ + static html( + body?: BodyType | null, + init?: HttpResponseInit, + ): Response { + const responseInit = normalizeResponseInit(init) + + if (!responseInit.headers.has('Content-Type')) { + responseInit.headers.set('Content-Type', 'text/html') + } + + return new HttpResponse(body, responseInit) + } + /** * Create a `Response` with an `ArrayBuffer` body. * @example diff --git a/test/browser/rest-api/response/body/body-html.mocks.ts b/test/browser/rest-api/response/body/body-html.mocks.ts new file mode 100644 index 000000000..54b14da28 --- /dev/null +++ b/test/browser/rest-api/response/body/body-html.mocks.ts @@ -0,0 +1,13 @@ +import { http, HttpResponse } from 'msw' +import { setupWorker } from 'msw/browser' + +const worker = setupWorker( + http.get('/user', () => { + return HttpResponse.html(` +

+ Jane Doe +

`) + }), +) + +worker.start() diff --git a/test/browser/rest-api/response/body/body-html.test.ts b/test/browser/rest-api/response/body/body-html.test.ts new file mode 100644 index 000000000..ced50b85b --- /dev/null +++ b/test/browser/rest-api/response/body/body-html.test.ts @@ -0,0 +1,17 @@ +import { test, expect } from '../../../playwright.extend' + +test('responds with an HTML response body', async ({ loadExample, fetch }) => { + await loadExample(require.resolve('./body-html.mocks.ts')) + + const res = await fetch('/user') + const status = res.status() + const headers = await res.allHeaders() + const text = await res.text() + + expect(status).toBe(200) + expect(headers['content-type']).toBe('text/html') + expect(text).toEqual(` +

+ Jane Doe +

`) +}) diff --git a/test/node/rest-api/response/body-html.node.test.ts b/test/node/rest-api/response/body-html.node.test.ts new file mode 100644 index 000000000..f4969261d --- /dev/null +++ b/test/node/rest-api/response/body-html.node.test.ts @@ -0,0 +1,34 @@ +/** + * @vitest-environment node + */ +import { HttpResponse, http } from 'msw' +import { setupServer } from 'msw/node' + +const server = setupServer( + http.get('http://localhost/html', () => { + return HttpResponse.html(` +

+ Jane Doe +

`) + }), +) + +beforeAll(() => { + server.listen() +}) + +afterAll(() => { + server.close() +}) + +test('responds with an HTML response body', async () => { + const res = await fetch('http://localhost/html') + const text = await res.text() + + expect(res.status).toBe(200) + expect(res.headers.get('content-type')).toBe('text/html') + expect(text).toEqual(` +

+ Jane Doe +

`) +})