From 5816f2dcd01b85f9e8d713f91bc9d619992340cc Mon Sep 17 00:00:00 2001 From: Patrick McLaughlin Date: Wed, 30 Mar 2022 09:07:05 -0400 Subject: [PATCH] feat: use HTTP status codes in superagent-codec-adapter Ticket: BG-45933 --- packages/io-ts-express/test/test-server.ts | 8 ++++---- packages/io-ts-http/src/httpResponse.ts | 3 +++ .../superagent-codec-adapter/src/request.ts | 17 +++++++++-------- .../test/request.test.ts | 8 ++++---- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/packages/io-ts-express/test/test-server.ts b/packages/io-ts-express/test/test-server.ts index fd425112..42c8370d 100644 --- a/packages/io-ts-express/test/test-server.ts +++ b/packages/io-ts-express/test/test-server.ts @@ -106,7 +106,7 @@ test('should offer a delightful developer experience', async (t) => { // application layer :thonking: const response = await apiClient['hello.world'] .put({ secretCode: 1000 }) - .decodeExpecting('ok') + .decodeExpecting(200) .then((res) => res.body); t.like(response, { message: "Who's there?" }); @@ -130,7 +130,7 @@ test('should invoke app-level middleware', async (t) => { const response = await apiClient['hello.world'] .put({ secretCode: 1000 }) - .decodeExpecting('ok') + .decodeExpecting(200) .then((res) => res.body); t.like(response, { message: "Who's there?", appMiddlewareRan: true }); @@ -153,7 +153,7 @@ test('should invoke route-level middleware', async (t) => { const response = await apiClient['hello.world'] .put({ secretCode: 1000 }) - .decodeExpecting('ok') + .decodeExpecting(200) .then((res) => res.body); t.like(response, { message: "Who's there?", routeMiddlewareRan: true }); @@ -176,7 +176,7 @@ test('should infer status code from response type', async (t) => { const response = await apiClient['hello.world'] .put({ secretCode: 0 }) - .decodeExpecting('invalidRequest') + .decodeExpecting(400) .then((res) => res.body); t.like(response, { errors: 'Please do not tell me zero! I will now explode' }); diff --git a/packages/io-ts-http/src/httpResponse.ts b/packages/io-ts-http/src/httpResponse.ts index fda31c35..c09669a5 100644 --- a/packages/io-ts-http/src/httpResponse.ts +++ b/packages/io-ts-http/src/httpResponse.ts @@ -18,3 +18,6 @@ export const HttpResponseCodes: { [K in Status]: number } = { internalError: 500, serviceUnavailable: 503, }; + +export type KnownHttpStatusCodes = + typeof HttpResponseCodes[KnownResponses]; diff --git a/packages/superagent-codec-adapter/src/request.ts b/packages/superagent-codec-adapter/src/request.ts index 6c2d5ae7..dd95ebcf 100644 --- a/packages/superagent-codec-adapter/src/request.ts +++ b/packages/superagent-codec-adapter/src/request.ts @@ -5,16 +5,15 @@ import type { Response, SuperAgent, SuperAgentRequest } from 'superagent'; import type { SuperTest } from 'supertest'; import { URL } from 'url'; import { pipe } from 'fp-ts/function'; -import { HttpResponseCodes } from '@bitgo/io-ts-http'; type SuccessfulResponses = { - [Status in h.KnownResponses]: { + [Status in h.KnownHttpStatusCodes]: { status: Status; error?: undefined; body: t.TypeOf; original: Response; }; -}[h.KnownResponses]; +}[h.KnownHttpStatusCodes]; type DecodedResponse = | SuccessfulResponses @@ -29,7 +28,7 @@ const decodedResponse = (res: DecodedResponse) type ExpectedDecodedResponse< Route extends h.HttpRoute, - Status extends h.KnownResponses, + Status extends h.KnownHttpStatusCodes, > = { body: t.TypeOf; original: Response; @@ -37,7 +36,7 @@ type ExpectedDecodedResponse< type PatchedRequest = Req & { decode: () => Promise>; - decodeExpecting: >( + decodeExpecting: >( status: Status, ) => Promise>; }; @@ -97,7 +96,7 @@ const patchRequest = ( let status: string | undefined; // DISCUSS: Should we have this as a preprocessed const in io-ts-http? - for (const [name, code] of Object.entries(HttpResponseCodes)) { + for (const [name, code] of Object.entries(h.HttpResponseCodes)) { if (statusCode === code) { status = name; break; @@ -125,7 +124,7 @@ const patchRequest = ( route.response[status].decode(res.body), E.map((body) => decodedResponse({ - status: status as h.KnownResponses, + status: statusCode, body, original: res, }), @@ -142,7 +141,9 @@ const patchRequest = ( ); }); - patchedReq.decodeExpecting = >( + patchedReq.decodeExpecting = < + Status extends h.KnownHttpStatusCodes, + >( status: Status, ) => patchedReq.decode().then((res) => { diff --git a/packages/superagent-codec-adapter/test/request.test.ts b/packages/superagent-codec-adapter/test/request.test.ts index 25eeac74..949a3227 100644 --- a/packages/superagent-codec-adapter/test/request.test.ts +++ b/packages/superagent-codec-adapter/test/request.test.ts @@ -105,7 +105,7 @@ describe('request', () => { .post({ id: 1337, foo: 'test', bar: 42 }) .decode(); - assert.equal(response.status, 'ok'); + assert.equal(response.status, 200); assert.deepEqual(response.body, { id: 1337, foo: 'test', @@ -152,7 +152,7 @@ describe('request', () => { it('narrows expected response types', async () => { const response = await apiClient['api.v1.test'] .post({ id: 1337, foo: 'test', bar: 42 }) - .decodeExpecting('ok'); + .decodeExpecting(200); assert.deepEqual(response.body, { id: 1337, @@ -166,7 +166,7 @@ describe('request', () => { const result = await apiClient['api.v1.test'] .post({ id: 1337, foo: 'test', bar: 42 }) .set('x-send-unexpected-status-code', 'true') - .decodeExpecting('ok') + .decodeExpecting(200) .then(() => false) .catch(() => true); @@ -177,7 +177,7 @@ describe('request', () => { const result = await apiClient['api.v1.test'] .post({ id: 1337, foo: 'test', bar: 42 }) .set('x-send-invalid-response-body', 'true') - .decodeExpecting('ok') + .decodeExpecting(200) .then(() => false) .catch(() => true);