msw 2.3.5 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/lib/browser/index.js +1 -1
  2. package/lib/browser/index.js.map +1 -1
  3. package/lib/browser/index.mjs +1 -1
  4. package/lib/browser/index.mjs.map +1 -1
  5. package/lib/core/{GraphQLHandler-L3AUWt2v.d.mts → GraphQLHandler-5pZBHLn9.d.mts} +1 -1
  6. package/lib/core/{GraphQLHandler-UgnlXhlx.d.ts → GraphQLHandler-Cu4Xvg4S.d.ts} +1 -1
  7. package/lib/core/{HttpResponse-B58aIqZM.d.ts → HttpResponse-DE19n76Q.d.ts} +7 -0
  8. package/lib/core/{HttpResponse-fnOXxh4-.d.mts → HttpResponse-Gtw1lt3H.d.mts} +7 -0
  9. package/lib/core/HttpResponse.d.mts +1 -1
  10. package/lib/core/HttpResponse.d.ts +1 -1
  11. package/lib/core/HttpResponse.js +13 -0
  12. package/lib/core/HttpResponse.js.map +1 -1
  13. package/lib/core/HttpResponse.mjs +13 -0
  14. package/lib/core/HttpResponse.mjs.map +1 -1
  15. package/lib/core/SetupApi.d.mts +1 -1
  16. package/lib/core/SetupApi.d.ts +1 -1
  17. package/lib/core/getResponse.d.mts +1 -1
  18. package/lib/core/getResponse.d.ts +1 -1
  19. package/lib/core/graphql.d.mts +2 -2
  20. package/lib/core/graphql.d.ts +2 -2
  21. package/lib/core/handlers/GraphQLHandler.d.mts +2 -2
  22. package/lib/core/handlers/GraphQLHandler.d.ts +2 -2
  23. package/lib/core/handlers/GraphQLHandler.js.map +1 -1
  24. package/lib/core/handlers/GraphQLHandler.mjs.map +1 -1
  25. package/lib/core/handlers/HttpHandler.d.mts +1 -1
  26. package/lib/core/handlers/HttpHandler.d.ts +1 -1
  27. package/lib/core/handlers/HttpHandler.js.map +1 -1
  28. package/lib/core/handlers/HttpHandler.mjs.map +1 -1
  29. package/lib/core/handlers/RequestHandler.d.mts +1 -1
  30. package/lib/core/handlers/RequestHandler.d.ts +1 -1
  31. package/lib/core/http.d.mts +1 -1
  32. package/lib/core/http.d.ts +1 -1
  33. package/lib/core/index.d.mts +2 -2
  34. package/lib/core/index.d.ts +2 -2
  35. package/lib/core/passthrough.d.mts +1 -1
  36. package/lib/core/passthrough.d.ts +1 -1
  37. package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
  38. package/lib/core/utils/HttpResponse/decorators.d.ts +1 -1
  39. package/lib/core/utils/executeHandlers.d.mts +1 -1
  40. package/lib/core/utils/executeHandlers.d.ts +1 -1
  41. package/lib/core/utils/handleRequest.d.mts +1 -1
  42. package/lib/core/utils/handleRequest.d.ts +1 -1
  43. package/lib/core/utils/internal/devUtils.js.map +1 -1
  44. package/lib/core/utils/internal/devUtils.mjs.map +1 -1
  45. package/lib/core/utils/internal/jsonParse.js +1 -1
  46. package/lib/core/utils/internal/jsonParse.js.map +1 -1
  47. package/lib/core/utils/internal/jsonParse.mjs +1 -1
  48. package/lib/core/utils/internal/jsonParse.mjs.map +1 -1
  49. package/lib/core/utils/internal/parseGraphQLRequest.d.mts +2 -2
  50. package/lib/core/utils/internal/parseGraphQLRequest.d.ts +2 -2
  51. package/lib/core/utils/internal/parseGraphQLRequest.js +19 -4
  52. package/lib/core/utils/internal/parseGraphQLRequest.js.map +1 -1
  53. package/lib/core/utils/internal/parseGraphQLRequest.mjs +8 -3
  54. package/lib/core/utils/internal/parseGraphQLRequest.mjs.map +1 -1
  55. package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
  56. package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
  57. package/lib/core/utils/internal/parseMultipartData.js +1 -1
  58. package/lib/core/utils/internal/parseMultipartData.js.map +1 -1
  59. package/lib/core/utils/internal/parseMultipartData.mjs +1 -1
  60. package/lib/core/utils/internal/parseMultipartData.mjs.map +1 -1
  61. package/lib/core/utils/internal/requestHandlerUtils.d.mts +1 -1
  62. package/lib/core/utils/internal/requestHandlerUtils.d.ts +1 -1
  63. package/lib/core/utils/request/onUnhandledRequest.js +6 -2
  64. package/lib/core/utils/request/onUnhandledRequest.js.map +1 -1
  65. package/lib/core/utils/request/onUnhandledRequest.mjs +6 -2
  66. package/lib/core/utils/request/onUnhandledRequest.mjs.map +1 -1
  67. package/lib/iife/index.js +26649 -16038
  68. package/lib/iife/index.js.map +1 -1
  69. package/lib/mockServiceWorker.js +1 -1
  70. package/package.json +9 -5
  71. package/src/browser/setupWorker/start/createStartHandler.ts +1 -0
  72. package/src/browser/setupWorker/start/utils/printStartMessage.ts +6 -0
  73. package/src/browser/setupWorker/stop/utils/printStopMessage.ts +1 -0
  74. package/src/browser/utils/supportsReadableStreamTransfer.ts +1 -1
  75. package/src/core/HttpResponse.test.ts +30 -0
  76. package/src/core/HttpResponse.ts +19 -0
  77. package/src/core/handlers/GraphQLHandler.ts +6 -0
  78. package/src/core/handlers/HttpHandler.ts +5 -0
  79. package/src/core/utils/internal/devUtils.ts +2 -0
  80. package/src/core/utils/internal/jsonParse.ts +1 -1
  81. package/src/core/utils/internal/parseGraphQLRequest.ts +9 -3
  82. package/src/core/utils/internal/parseMultipartData.ts +1 -1
  83. package/src/core/utils/request/onUnhandledRequest.test.ts +28 -0
  84. package/src/core/utils/request/onUnhandledRequest.ts +6 -1
@@ -8,7 +8,7 @@
8
8
  * - Please do NOT serve this file on production.
9
9
  */
10
10
 
11
- const PACKAGE_VERSION = '2.3.5'
11
+ const PACKAGE_VERSION = '2.4.1'
12
12
  const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'
13
13
  const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
14
14
  const activeClientIds = new Set()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "msw",
3
- "version": "2.3.5",
3
+ "version": "2.4.1",
4
4
  "description": "Seamless REST/GraphQL API mocking library for browser and Node.js.",
5
5
  "main": "./lib/core/index.js",
6
6
  "module": "./lib/core/index.mjs",
@@ -122,7 +122,6 @@
122
122
  "@types/cookie": "^0.6.0",
123
123
  "@types/statuses": "^2.0.4",
124
124
  "chalk": "^4.1.2",
125
- "graphql": "^16.8.1",
126
125
  "headers-polyfill": "^4.0.2",
127
126
  "is-node-process": "^1.2.0",
128
127
  "outvariant": "^1.4.2",
@@ -143,8 +142,8 @@
143
142
  "@types/glob": "^8.1.0",
144
143
  "@types/json-bigint": "^1.0.4",
145
144
  "@types/node": "18.x",
146
- "@typescript-eslint/eslint-plugin": "^7.2.0",
147
- "@typescript-eslint/parser": "^7.2.0",
145
+ "@typescript-eslint/eslint-plugin": "^8.3.0",
146
+ "@typescript-eslint/parser": "^8.3.0",
148
147
  "@web/dev-server": "^0.1.38",
149
148
  "axios": "^1.6.5",
150
149
  "babel-minify": "^0.5.1",
@@ -161,6 +160,7 @@
161
160
  "fs-extra": "^11.2.0",
162
161
  "fs-teardown": "^0.3.0",
163
162
  "glob": "^10.3.10",
163
+ "graphql": "^16.8.1",
164
164
  "jsdom": "^23.2.0",
165
165
  "json-bigint": "^1.0.0",
166
166
  "lint-staged": "^15.2.0",
@@ -180,9 +180,13 @@
180
180
  "webpack-http-server": "^0.5.0"
181
181
  },
182
182
  "peerDependencies": {
183
+ "graphql": ">= 16.8.x",
183
184
  "typescript": ">= 4.7.x"
184
185
  },
185
186
  "peerDependenciesMeta": {
187
+ "graphql": {
188
+ "optional": true
189
+ },
186
190
  "typescript": {
187
191
  "optional": true
188
192
  }
@@ -200,7 +204,7 @@
200
204
  "scripts": {
201
205
  "start": "tsup --watch",
202
206
  "clean": "rimraf ./lib",
203
- "lint": "eslint \"{cli,config,src,test}/**/*.ts\"",
207
+ "lint": "eslint \"{cli,src}/**/*.ts\"",
204
208
  "build": "pnpm clean && cross-env NODE_ENV=production tsup && pnpm patch:dts",
205
209
  "patch:dts": "node \"./config/scripts/patch-ts.js\"",
206
210
  "check:exports": "node \"./config/scripts/validate-esm.js\"",
@@ -79,6 +79,7 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
79
79
  devUtils.error(
80
80
  'Error while checking the worker script integrity. Please report this on GitHub (https://github.com/mswjs/msw/issues), including the original error below.',
81
81
  )
82
+ // eslint-disable-next-line no-console
82
83
  console.error(error)
83
84
  })
84
85
 
@@ -17,24 +17,30 @@ export function printStartMessage(args: PrintStartMessageArgs = {}) {
17
17
 
18
18
  const message = args.message || 'Mocking enabled.'
19
19
 
20
+ // eslint-disable-next-line no-console
20
21
  console.groupCollapsed(
21
22
  `%c${devUtils.formatMessage(message)}`,
22
23
  'color:orangered;font-weight:bold;',
23
24
  )
25
+ // eslint-disable-next-line no-console
24
26
  console.log(
25
27
  '%cDocumentation: %chttps://mswjs.io/docs',
26
28
  'font-weight:bold',
27
29
  'font-weight:normal',
28
30
  )
31
+ // eslint-disable-next-line no-console
29
32
  console.log('Found an issue? https://github.com/mswjs/msw/issues')
30
33
 
31
34
  if (args.workerUrl) {
35
+ // eslint-disable-next-line no-console
32
36
  console.log('Worker script URL:', args.workerUrl)
33
37
  }
34
38
 
35
39
  if (args.workerScope) {
40
+ // eslint-disable-next-line no-console
36
41
  console.log('Worker scope:', args.workerScope)
37
42
  }
38
43
 
44
+ // eslint-disable-next-line no-console
39
45
  console.groupEnd()
40
46
  }
@@ -5,6 +5,7 @@ export function printStopMessage(args: { quiet?: boolean } = {}): void {
5
5
  return
6
6
  }
7
7
 
8
+ // eslint-disable-next-line no-console
8
9
  console.log(
9
10
  `%c${devUtils.formatMessage('Mocking disabled.')}`,
10
11
  'color:orangered;font-weight:bold;',
@@ -11,7 +11,7 @@ export function supportsReadableStreamTransfer() {
11
11
  const message = new MessageChannel()
12
12
  message.port1.postMessage(stream, [stream])
13
13
  return true
14
- } catch (error) {
14
+ } catch {
15
15
  return false
16
16
  }
17
17
  }
@@ -223,6 +223,36 @@ describe('HttpResponse.xml()', () => {
223
223
  })
224
224
  })
225
225
 
226
+ describe('HttpResponse.html()', () => {
227
+ it('creates an html response', async () => {
228
+ const response = HttpResponse.html('<p class="author">Jane Doe</p>')
229
+
230
+ expect(response.status).toBe(200)
231
+ expect(response.statusText).toBe('OK')
232
+ expect(response.body).toBeInstanceOf(ReadableStream)
233
+ expect(await response.text()).toBe('<p class="author">Jane Doe</p>')
234
+ expect(Object.fromEntries(response.headers.entries())).toEqual({
235
+ 'content-type': 'text/html',
236
+ })
237
+ })
238
+
239
+ it('allows overriding the "Content-Type" response header', async () => {
240
+ const response = HttpResponse.html('<p class="author">Jane Doe</p>', {
241
+ headers: {
242
+ 'Content-Type': 'text/html; charset=utf-8',
243
+ },
244
+ })
245
+
246
+ expect(response.status).toBe(200)
247
+ expect(response.statusText).toBe('OK')
248
+ expect(response.body).toBeInstanceOf(ReadableStream)
249
+ expect(await response.text()).toBe('<p class="author">Jane Doe</p>')
250
+ expect(Object.fromEntries(response.headers.entries())).toEqual({
251
+ 'content-type': 'text/html; charset=utf-8',
252
+ })
253
+ })
254
+ })
255
+
226
256
  it('creates an array buffer response', async () => {
227
257
  const buffer = new TextEncoder().encode('hello world')
228
258
  const response = HttpResponse.arrayBuffer(buffer)
@@ -125,6 +125,25 @@ export class HttpResponse extends Response {
125
125
  return new HttpResponse(body, responseInit)
126
126
  }
127
127
 
128
+ /**
129
+ * Create a `Response` with a `Content-Type: "text/html"` body.
130
+ * @example
131
+ * HttpResponse.html(`<p class="author">Jane Doe</p>`)
132
+ * HttpResponse.html(`<main id="abc-123">Main text</main>`, { status: 201 })
133
+ */
134
+ static html<BodyType extends string>(
135
+ body?: BodyType | null,
136
+ init?: HttpResponseInit,
137
+ ): Response {
138
+ const responseInit = normalizeResponseInit(init)
139
+
140
+ if (!responseInit.headers.has('Content-Type')) {
141
+ responseInit.headers.set('Content-Type', 'text/html')
142
+ }
143
+
144
+ return new HttpResponse(body, responseInit)
145
+ }
146
+
128
147
  /**
129
148
  * Create a `Response` with an `ArrayBuffer` body.
130
149
  * @example
@@ -155,6 +155,7 @@ export class GraphQLHandler extends RequestHandler<
155
155
  GraphQLHandler.parsedRequestCache.set(
156
156
  request,
157
157
  await parseGraphQLRequest(request).catch((error) => {
158
+ // eslint-disable-next-line no-console
158
159
  console.error(error)
159
160
  return undefined
160
161
  }),
@@ -252,6 +253,7 @@ Consider naming this operation or using "graphql.operation()" request handler to
252
253
  ? `${args.parsedResult.operationType} ${args.parsedResult.operationName}`
253
254
  : `anonymous ${args.parsedResult.operationType}`
254
255
 
256
+ // eslint-disable-next-line no-console
255
257
  console.groupCollapsed(
256
258
  devUtils.formatMessage(
257
259
  `${getTimestamp()} ${requestInfo} (%c${loggedResponse.status} ${
@@ -261,9 +263,13 @@ Consider naming this operation or using "graphql.operation()" request handler to
261
263
  `color:${statusColor}`,
262
264
  'color:inherit',
263
265
  )
266
+ // eslint-disable-next-line no-console
264
267
  console.log('Request:', loggedRequest)
268
+ // eslint-disable-next-line no-console
265
269
  console.log('Handler:', this)
270
+ // eslint-disable-next-line no-console
266
271
  console.log('Response:', loggedResponse)
272
+ // eslint-disable-next-line no-console
267
273
  console.groupEnd()
268
274
  }
269
275
  }
@@ -152,6 +152,7 @@ export class HttpHandler extends RequestHandler<
152
152
  const loggedResponse = await serializeResponse(args.response)
153
153
  const statusColor = getStatusCodeColor(loggedResponse.status)
154
154
 
155
+ // eslint-disable-next-line no-console
155
156
  console.groupCollapsed(
156
157
  devUtils.formatMessage(
157
158
  `${getTimestamp()} ${args.request.method} ${publicUrl} (%c${
@@ -161,9 +162,13 @@ export class HttpHandler extends RequestHandler<
161
162
  `color:${statusColor}`,
162
163
  'color:inherit',
163
164
  )
165
+ // eslint-disable-next-line no-console
164
166
  console.log('Request', loggedRequest)
167
+ // eslint-disable-next-line no-console
165
168
  console.log('Handler:', this)
169
+ // eslint-disable-next-line no-console
166
170
  console.log('Response', loggedResponse)
171
+ // eslint-disable-next-line no-console
167
172
  console.groupEnd()
168
173
  }
169
174
  }
@@ -14,6 +14,7 @@ function formatMessage(message: string, ...positionals: any[]): string {
14
14
  * Prints a library-specific warning.
15
15
  */
16
16
  function warn(message: string, ...positionals: any[]): void {
17
+ // eslint-disable-next-line no-console
17
18
  console.warn(formatMessage(message, ...positionals))
18
19
  }
19
20
 
@@ -21,6 +22,7 @@ function warn(message: string, ...positionals: any[]): void {
21
22
  * Prints a library-specific error.
22
23
  */
23
24
  function error(message: string, ...positionals: any[]): void {
25
+ // eslint-disable-next-line no-console
24
26
  console.error(formatMessage(message, ...positionals))
25
27
  }
26
28
 
@@ -7,7 +7,7 @@ export function jsonParse<ValueType extends Record<string, any>>(
7
7
  ): ValueType | undefined {
8
8
  try {
9
9
  return JSON.parse(value)
10
- } catch (error) {
10
+ } catch {
11
11
  return undefined
12
12
  }
13
13
  }
@@ -3,7 +3,6 @@ import type {
3
3
  OperationDefinitionNode,
4
4
  OperationTypeNode,
5
5
  } from 'graphql'
6
- import { parse } from 'graphql'
7
6
  import type { GraphQLVariables } from '../../handlers/GraphQLHandler'
8
7
  import { toPublicUrl } from '../request/toPublicUrl'
9
8
  import { devUtils } from './devUtils'
@@ -40,7 +39,14 @@ export function parseDocumentNode(node: DocumentNode): ParsedGraphQLQuery {
40
39
  }
41
40
  }
42
41
 
43
- function parseQuery(query: string): ParsedGraphQLQuery | Error {
42
+ async function parseQuery(query: string): Promise<ParsedGraphQLQuery | Error> {
43
+ const { parse } = await import('graphql').catch((error) => {
44
+ devUtils.error(
45
+ 'Failed to parse a GraphQL query: cannot import the "graphql" module. Please make sure you install it if you wish to intercept GraphQL requests. See the original import error below.',
46
+ )
47
+ throw error
48
+ })
49
+
44
50
  try {
45
51
  const ast = parse(query)
46
52
  return parseDocumentNode(ast)
@@ -181,7 +187,7 @@ export async function parseGraphQLRequest(
181
187
  }
182
188
 
183
189
  const { query, variables } = input
184
- const parsedResult = parseQuery(query)
190
+ const parsedResult = await parseQuery(query)
185
191
 
186
192
  if (parsedResult instanceof Error) {
187
193
  const requestPublicUrl = toPublicUrl(request.url)
@@ -98,7 +98,7 @@ export function parseMultipartData<T extends DefaultRequestMultipartBody>(
98
98
  }
99
99
 
100
100
  return parsedBody as T
101
- } catch (error) {
101
+ } catch {
102
102
  return undefined
103
103
  }
104
104
  }
@@ -12,6 +12,15 @@ const fixtures = {
12
12
 
13
13
  • GET ${url}
14
14
 
15
+ If you still wish to intercept this unhandled request, please create a request handler for it.
16
+ Read more: https://mswjs.io/docs/getting-started/mocks`,
17
+ warningWithResponseBody: (url = `/api`) => `\
18
+ [MSW] Warning: intercepted a request without a matching request handler:
19
+
20
+ • POST ${url}
21
+
22
+ • Request body: {\"variables\":{\"id\":\"abc-123\"},\"query\":\"query UserName($id: String!) { user(id: $id) { name } }\"}
23
+
15
24
  If you still wish to intercept this unhandled request, please create a request handler for it.
16
25
  Read more: https://mswjs.io/docs/getting-started/mocks`,
17
26
 
@@ -51,6 +60,25 @@ test('supports the "warn" request strategy', async () => {
51
60
  )
52
61
  })
53
62
 
63
+ test('supports the "warn" request strategy with request body', async () => {
64
+ await onUnhandledRequest(
65
+ new Request(new URL('http://localhost/api'), {
66
+ method: 'POST',
67
+ headers: {
68
+ 'Content-Type': 'application/json',
69
+ },
70
+ body: JSON.stringify({
71
+ variables: {
72
+ id: 'abc-123',
73
+ },
74
+ query: 'query UserName($id: String!) { user(id: $id) { name } }',
75
+ }),
76
+ }),
77
+ )
78
+
79
+ expect(console.warn).toHaveBeenCalledWith(fixtures.warningWithResponseBody())
80
+ })
81
+
54
82
  test('supports the "error" request strategy', async () => {
55
83
  await expect(
56
84
  onUnhandledRequest(new Request(new URL('http://localhost/api')), 'error'),
@@ -24,7 +24,12 @@ export async function onUnhandledRequest(
24
24
  const url = new URL(request.url)
25
25
  const publicUrl = toPublicUrl(url) + url.search
26
26
 
27
- 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`
27
+ const requestBody =
28
+ request.method === 'HEAD' || request.method === 'GET'
29
+ ? null
30
+ : await request.clone().text()
31
+ const messageDetails = `\n\n \u2022 ${request.method} ${publicUrl}\n\n${requestBody ? ` \u2022 Request body: ${requestBody}\n\n` : ''}`
32
+ 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`
28
33
 
29
34
  function applyStrategy(strategy: UnhandledRequestStrategy) {
30
35
  switch (strategy) {