From a2153c93edd752d7c5686573f684721b19f0a115 Mon Sep 17 00:00:00 2001 From: bitttttten Date: Wed, 28 Aug 2024 18:19:47 +0200 Subject: [PATCH] feat: print request body in `onUnhandledRequest` message (#2227) Co-authored-by: Artem Zakharchenko --- .../utils/request/onUnhandledRequest.test.ts | 28 +++++++++++++++++++ src/core/utils/request/onUnhandledRequest.ts | 7 ++++- .../graphql-api/anonymous-operation.test.ts | 12 ++++---- .../many-request-handlers-jsdom.test.ts | 11 ++++---- .../regressions/many-request-handlers.test.ts | 11 ++++---- 5 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/core/utils/request/onUnhandledRequest.test.ts b/src/core/utils/request/onUnhandledRequest.test.ts index 7cb9826fc..a65497ea1 100644 --- a/src/core/utils/request/onUnhandledRequest.test.ts +++ b/src/core/utils/request/onUnhandledRequest.test.ts @@ -12,6 +12,15 @@ const fixtures = { • GET ${url} +If you still wish to intercept this unhandled request, please create a request handler for it. +Read more: https://mswjs.io/docs/getting-started/mocks`, + warningWithResponseBody: (url = `/api`) => `\ +[MSW] Warning: intercepted a request without a matching request handler: + + • POST ${url} + + • Request body: {\"variables\":{\"id\":\"abc-123\"},\"query\":\"query UserName($id: String!) { user(id: $id) { name } }\"} + If you still wish to intercept this unhandled request, please create a request handler for it. Read more: https://mswjs.io/docs/getting-started/mocks`, @@ -51,6 +60,25 @@ test('supports the "warn" request strategy', async () => { ) }) +test('supports the "warn" request strategy with request body', async () => { + await onUnhandledRequest( + new Request(new URL('http://localhost/api'), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + variables: { + id: 'abc-123', + }, + query: 'query UserName($id: String!) { user(id: $id) { name } }', + }), + }), + ) + + expect(console.warn).toHaveBeenCalledWith(fixtures.warningWithResponseBody()) +}) + test('supports the "error" request strategy', async () => { await expect( onUnhandledRequest(new Request(new URL('http://localhost/api')), 'error'), diff --git a/src/core/utils/request/onUnhandledRequest.ts b/src/core/utils/request/onUnhandledRequest.ts index 02708b139..4f7360507 100644 --- a/src/core/utils/request/onUnhandledRequest.ts +++ b/src/core/utils/request/onUnhandledRequest.ts @@ -24,7 +24,12 @@ export async function onUnhandledRequest( const url = new URL(request.url) const publicUrl = toPublicUrl(url) + url.search - const unhandledRequestMessage = `intercepted a request without a matching request handler:\n\n \u2022 ${request.method} ${publicUrl}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/getting-started/mocks` + const requestBody = + request.method === 'HEAD' || request.method === 'GET' + ? null + : await request.clone().text() + const messageDetails = `\n\n \u2022 ${request.method} ${publicUrl}\n\n${requestBody ? ` \u2022 Request body: ${requestBody}\n\n` : ''}` + const unhandledRequestMessage = `intercepted a request without a matching request handler:${messageDetails}If you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/getting-started/mocks` function applyStrategy(strategy: UnhandledRequestStrategy) { switch (strategy) { diff --git a/test/browser/graphql-api/anonymous-operation.test.ts b/test/browser/graphql-api/anonymous-operation.test.ts index 6cef3e90a..87979279f 100644 --- a/test/browser/graphql-api/anonymous-operation.test.ts +++ b/test/browser/graphql-api/anonymous-operation.test.ts @@ -41,8 +41,8 @@ test('does not warn on anonymous GraphQL operation when no GraphQL handlers are const endpointUrl = httpServer.http.url('/graphql') const response = await query(endpointUrl, { + // Intentionally anonymous query. query: gql` - # Intentionally anonymous query. query { user { id @@ -71,6 +71,8 @@ test('does not warn on anonymous GraphQL operation when no GraphQL handlers are • POST ${endpointUrl} + • Request body: {\"query\":\"\\n query {\\n user {\\n id\\n }\\n }\\n \"} + If you still wish to intercept this unhandled request, please create a request handler for it. Read more: https://mswjs.io/docs/getting-started/mocks`, ]) @@ -105,9 +107,9 @@ test('warns on handled anonymous GraphQL operation', async ({ const endpointUrl = httpServer.http.url('/graphql') const response = await query(endpointUrl, { + // Intentionally anonymous query. + // It will be handled in the "graphql.operation()" handler above. query: gql` - # Intentionally anonymous query. - # It will be handled in the "graphql.operation()" handler above. query { user { id @@ -170,9 +172,9 @@ test('does not print a warning on anonymous GraphQL operation handled by "graphq const endpointUrl = httpServer.http.url('/graphql') const response = await query(endpointUrl, { + // Intentionally anonymous query. + // It will be handled in the "graphql.operation()" handler above. query: gql` - # Intentionally anonymous query. - # It will be handled in the "graphql.operation()" handler above. query { user { id diff --git a/test/node/regressions/many-request-handlers-jsdom.test.ts b/test/node/regressions/many-request-handlers-jsdom.test.ts index 5324fd705..58e8153bc 100644 --- a/test/node/regressions/many-request-handlers-jsdom.test.ts +++ b/test/node/regressions/many-request-handlers-jsdom.test.ts @@ -1,6 +1,4 @@ -/** - * @vitest-environment jsdom - */ +// @vitest-environment jsdom import { HttpServer } from '@open-draft/test-server/http' import { graphql, http, HttpResponse } from 'msw' import { setupServer } from 'msw/node' @@ -74,8 +72,9 @@ describe('http handlers', () => { body: 'request-body-', }, ) - // Each clone is a new AbortSignal listener which needs to be registered - expect(requestCloneSpy).toHaveBeenCalledTimes(1) + // Each clone is a new AbortSignal listener which needs to be registered. + // One clone is `onUnhandledRequest` reading the request body to print. + expect(requestCloneSpy).toHaveBeenCalledTimes(2) expect(httpResponse.status).toBe(500) expect(processErrorSpy).not.toHaveBeenCalled() }) @@ -122,7 +121,7 @@ describe('graphql handlers', () => { }) expect(unhandledResponse.status).toEqual(500) - expect(requestCloneSpy).toHaveBeenCalledTimes(2) + expect(requestCloneSpy).toHaveBeenCalledTimes(3) // Must not print any memory leak warnings. expect(processErrorSpy).not.toHaveBeenCalled() }) diff --git a/test/node/regressions/many-request-handlers.test.ts b/test/node/regressions/many-request-handlers.test.ts index 3079ebc9c..44dba797a 100644 --- a/test/node/regressions/many-request-handlers.test.ts +++ b/test/node/regressions/many-request-handlers.test.ts @@ -1,6 +1,4 @@ -/** - * @vitest-environment node - */ +// @vitest-environment node import { HttpServer } from '@open-draft/test-server/http' import { graphql, http, HttpResponse } from 'msw' import { setupServer } from 'msw/node' @@ -75,8 +73,9 @@ describe('http handlers', () => { body: 'request-body-', }, ) - // Each clone is a new AbortSignal listener which needs to be registered - expect(requestCloneSpy).toHaveBeenCalledTimes(1) + // Each clone is a new AbortSignal listener which needs to be registered. + // One clone is `onUnhandledRequest` reading the request body to print. + expect(requestCloneSpy).toHaveBeenCalledTimes(2) expect(httpResponse.status).toBe(500) expect(stdErrSpy).not.toHaveBeenCalled() }) @@ -124,7 +123,7 @@ describe('graphql handlers', () => { }) expect(unhandledResponse.status).toEqual(500) - expect(requestCloneSpy).toHaveBeenCalledTimes(2) + expect(requestCloneSpy).toHaveBeenCalledTimes(3) // Must not print any memory leak warnings. expect(stdErrSpy).not.toHaveBeenCalled() })