From 996915a435801719c1b0563fa81e379be435e98d Mon Sep 17 00:00:00 2001 From: Artem Zakharchenko Date: Thu, 20 Jan 2022 18:42:09 +0100 Subject: [PATCH] feat(fromOpenApi): support response headers (#14) * chore(tsconfig): remove path aliases * feat(fromOpenApi): support response headers --- src/fromOpenApi/fromOpenApi.ts | 23 +++++++++-- test/oas/oas-response-headers.test.ts | 59 +++++++++++++++++++++++++++ test/traffic/utils/index.ts | 2 +- tsconfig.json | 7 +--- 4 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 test/oas/oas-response-headers.test.ts diff --git a/src/fromOpenApi/fromOpenApi.ts b/src/fromOpenApi/fromOpenApi.ts index 473d3d4..def01c7 100644 --- a/src/fromOpenApi/fromOpenApi.ts +++ b/src/fromOpenApi/fromOpenApi.ts @@ -121,9 +121,26 @@ function createResponseResolver( const transformers: ResponseTransformer[] = [] transformers.push(ctx.status(Number(status))) - /** - * @todo Support "response.headers" schema. - */ + // Set response headers. + if (response.headers) { + for (const [headerName, headerDefinition] of Object.entries( + response.headers, + )) { + invariant( + !('$ref' in headerDefinition), + 'Failed to generate mock response headers: found an unresolved reference', + headerDefinition, + ) + + const headerSchema = headerDefinition.schema as OpenAPIV3.SchemaObject + const headerValue = evolveJsonSchema(headerSchema) + if (!headerValue) { + continue + } + + transformers.push(ctx.set(headerName, toString(headerValue))) + } + } if ('content' in response && response.content != null) { let body: unknown diff --git a/test/oas/oas-response-headers.test.ts b/test/oas/oas-response-headers.test.ts new file mode 100644 index 0000000..852addb --- /dev/null +++ b/test/oas/oas-response-headers.test.ts @@ -0,0 +1,59 @@ +import fetch from 'cross-fetch' +import { Headers } from 'headers-utils' +import { fromOpenApi } from '../../src/fromOpenApi/fromOpenApi' +import { createOpenApiSpec } from '../../test/support/createOpenApiSpec' +import { withHandlers } from '../support/withHandlers' + +it('supports response headers', async () => { + const handlers = await fromOpenApi( + createOpenApiSpec({ + paths: { + '/user': { + get: { + responses: { + 200: { + headers: { + 'X-Rate-Limit-Remaining': { + schema: { + type: 'number', + }, + }, + 'X-Rate-Limit-Reset': { + schema: { + type: 'string', + format: 'date-time', + }, + }, + }, + content: { + 'text/plain': { + schema: { + type: 'string', + }, + }, + }, + }, + }, + }, + }, + }, + }), + ) + + const res = await withHandlers(handlers, () => { + return fetch('http://localhost/user') + }) + + expect(res.status).toEqual(200) + const headers = new Headers(res.headers) + + expect(headers.all()).toEqual({ + 'content-type': 'text/plain', + 'x-powered-by': 'msw', + // Header values are always strings. + 'x-rate-limit-remaining': expect.any(String), + 'x-rate-limit-reset': expect.stringMatching( + /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+?Z$/, + ), + }) +}) diff --git a/test/traffic/utils/index.ts b/test/traffic/utils/index.ts index 4d654fe..a239b6b 100644 --- a/test/traffic/utils/index.ts +++ b/test/traffic/utils/index.ts @@ -1,7 +1,7 @@ import * as fs from 'fs' import { Har, Header } from 'har-format' import { HeadersObject, headersToObject } from 'headers-utils' -import { MapEntryFn } from 'src/fromTraffic/fromTraffic' +import { MapEntryFn } from '../../../src/fromTraffic/fromTraffic' export function readArchive(archivePath: string): Har { return JSON.parse(fs.readFileSync(archivePath, 'utf8')) diff --git a/tsconfig.json b/tsconfig.json index 5a643a1..5596da9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,12 +10,7 @@ "noImplicitAny": true, "outDir": "lib", "declaration": true, - "declarationDir": "lib", - "baseUrl": "./", - "paths": { - "src/*": ["src/*"], - "test/*": ["test/*"] - } + "declarationDir": "lib" }, "include": ["src/**/*.ts"], "exclude": ["node_modules"]