msw 2.10.5 → 2.11.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 (108) hide show
  1. package/lib/browser/index.js.map +1 -1
  2. package/lib/browser/index.mjs.map +1 -1
  3. package/lib/core/{HttpResponse-CC5tPhLa.d.mts → HttpResponse-B4YmE-GJ.d.mts} +22 -8
  4. package/lib/core/{HttpResponse-CKZrrwKE.d.ts → HttpResponse-BbwAqLE_.d.ts} +22 -8
  5. package/lib/core/HttpResponse.d.mts +1 -1
  6. package/lib/core/HttpResponse.d.ts +1 -1
  7. package/lib/core/HttpResponse.js.map +1 -1
  8. package/lib/core/HttpResponse.mjs.map +1 -1
  9. package/lib/core/SetupApi.d.mts +1 -1
  10. package/lib/core/SetupApi.d.ts +1 -1
  11. package/lib/core/getResponse.d.mts +1 -1
  12. package/lib/core/getResponse.d.ts +1 -1
  13. package/lib/core/graphql.d.mts +2 -2
  14. package/lib/core/graphql.d.ts +2 -2
  15. package/lib/core/graphql.js +2 -8
  16. package/lib/core/graphql.js.map +1 -1
  17. package/lib/core/graphql.mjs +2 -8
  18. package/lib/core/graphql.mjs.map +1 -1
  19. package/lib/core/handlers/GraphQLHandler.d.mts +1 -1
  20. package/lib/core/handlers/GraphQLHandler.d.ts +1 -1
  21. package/lib/core/handlers/GraphQLHandler.js +36 -9
  22. package/lib/core/handlers/GraphQLHandler.js.map +1 -1
  23. package/lib/core/handlers/GraphQLHandler.mjs +36 -9
  24. package/lib/core/handlers/GraphQLHandler.mjs.map +1 -1
  25. package/lib/core/handlers/HttpHandler.d.mts +15 -5
  26. package/lib/core/handlers/HttpHandler.d.ts +15 -5
  27. package/lib/core/handlers/HttpHandler.js +21 -10
  28. package/lib/core/handlers/HttpHandler.js.map +1 -1
  29. package/lib/core/handlers/HttpHandler.mjs +21 -10
  30. package/lib/core/handlers/HttpHandler.mjs.map +1 -1
  31. package/lib/core/handlers/RequestHandler.d.mts +1 -1
  32. package/lib/core/handlers/RequestHandler.d.ts +1 -1
  33. package/lib/core/handlers/RequestHandler.js +1 -1
  34. package/lib/core/handlers/RequestHandler.js.map +1 -1
  35. package/lib/core/handlers/RequestHandler.mjs +1 -1
  36. package/lib/core/handlers/RequestHandler.mjs.map +1 -1
  37. package/lib/core/http.d.mts +4 -4
  38. package/lib/core/http.d.ts +4 -4
  39. package/lib/core/http.js +2 -2
  40. package/lib/core/http.js.map +1 -1
  41. package/lib/core/http.mjs +2 -2
  42. package/lib/core/http.mjs.map +1 -1
  43. package/lib/core/index.d.mts +2 -2
  44. package/lib/core/index.d.ts +2 -2
  45. package/lib/core/index.js.map +1 -1
  46. package/lib/core/index.mjs.map +1 -1
  47. package/lib/core/passthrough.d.mts +1 -1
  48. package/lib/core/passthrough.d.ts +1 -1
  49. package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
  50. package/lib/core/utils/HttpResponse/decorators.d.ts +1 -1
  51. package/lib/core/utils/cookieStore.d.mts +10 -2
  52. package/lib/core/utils/cookieStore.d.ts +10 -2
  53. package/lib/core/utils/cookieStore.js +49 -146
  54. package/lib/core/utils/cookieStore.js.map +1 -1
  55. package/lib/core/utils/cookieStore.mjs +53 -136
  56. package/lib/core/utils/cookieStore.mjs.map +1 -1
  57. package/lib/core/utils/executeHandlers.d.mts +1 -1
  58. package/lib/core/utils/executeHandlers.d.ts +1 -1
  59. package/lib/core/utils/handleRequest.d.mts +1 -1
  60. package/lib/core/utils/handleRequest.d.ts +1 -1
  61. package/lib/core/utils/handleRequest.js +1 -1
  62. package/lib/core/utils/handleRequest.js.map +1 -1
  63. package/lib/core/utils/handleRequest.mjs +1 -1
  64. package/lib/core/utils/handleRequest.mjs.map +1 -1
  65. package/lib/core/utils/internal/isHandlerKind.d.mts +1 -1
  66. package/lib/core/utils/internal/isHandlerKind.d.ts +1 -1
  67. package/lib/core/utils/internal/parseGraphQLRequest.d.mts +1 -1
  68. package/lib/core/utils/internal/parseGraphQLRequest.d.ts +1 -1
  69. package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
  70. package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
  71. package/lib/core/utils/internal/requestHandlerUtils.d.mts +1 -1
  72. package/lib/core/utils/internal/requestHandlerUtils.d.ts +1 -1
  73. package/lib/core/utils/request/getRequestCookies.js +1 -1
  74. package/lib/core/utils/request/getRequestCookies.js.map +1 -1
  75. package/lib/core/utils/request/getRequestCookies.mjs +1 -1
  76. package/lib/core/utils/request/getRequestCookies.mjs.map +1 -1
  77. package/lib/core/utils/request/storeResponseCookies.d.mts +1 -1
  78. package/lib/core/utils/request/storeResponseCookies.d.ts +1 -1
  79. package/lib/core/utils/request/storeResponseCookies.js +2 -2
  80. package/lib/core/utils/request/storeResponseCookies.js.map +1 -1
  81. package/lib/core/utils/request/storeResponseCookies.mjs +2 -2
  82. package/lib/core/utils/request/storeResponseCookies.mjs.map +1 -1
  83. package/lib/core/ws/handleWebSocketEvent.d.mts +1 -1
  84. package/lib/core/ws/handleWebSocketEvent.d.ts +1 -1
  85. package/lib/iife/index.js +2661 -12110
  86. package/lib/iife/index.js.map +1 -1
  87. package/lib/mockServiceWorker.js +1 -1
  88. package/lib/node/index.js.map +1 -1
  89. package/lib/node/index.mjs.map +1 -1
  90. package/package.json +4 -4
  91. package/src/browser/setupWorker/setupWorker.ts +1 -1
  92. package/src/core/HttpResponse.ts +3 -3
  93. package/src/core/graphql.ts +8 -12
  94. package/src/core/handlers/GraphQLHandler.test.ts +86 -51
  95. package/src/core/handlers/GraphQLHandler.ts +81 -17
  96. package/src/core/handlers/HttpHandler.test.ts +60 -30
  97. package/src/core/handlers/HttpHandler.ts +61 -12
  98. package/src/core/handlers/RequestHandler.ts +2 -2
  99. package/src/core/http.ts +5 -5
  100. package/src/core/index.ts +3 -0
  101. package/src/core/utils/cookieStore.ts +56 -198
  102. package/src/core/utils/handleRequest.test.ts +84 -0
  103. package/src/core/utils/handleRequest.ts +1 -1
  104. package/src/core/utils/request/getRequestCookies.ts +1 -1
  105. package/src/core/utils/request/storeResponseCookies.ts +3 -3
  106. package/src/core/utils/request/toPublicUrl.test.ts +1 -1
  107. package/src/core/ws/WebSocketClientManager.test.ts +1 -1
  108. package/src/node/SetupServerApi.ts +1 -1
@@ -1,230 +1,88 @@
1
- import { invariant } from 'outvariant'
2
1
  import { isNodeProcess } from 'is-node-process'
3
- import toughCookie, {
4
- type Cookie as CookieInstance,
5
- } from '@bundled-es-modules/tough-cookie'
6
-
7
- const { Cookie, CookieJar, Store, MemoryCookieStore, domainMatch, pathMatch } =
8
- toughCookie
9
-
10
- /**
11
- * Custom cookie store that uses the Web Storage API.
12
- * @see https://github.com/expo/tough-cookie-web-storage-store
13
- */
14
- class WebStorageCookieStore extends Store {
15
- private storage: Storage
16
- private storageKey: string
2
+ import { invariant } from 'outvariant'
3
+ import {
4
+ Cookie,
5
+ CookieJar,
6
+ MemoryCookieStore,
7
+ type MemoryCookieStoreIndex,
8
+ } from 'tough-cookie'
9
+ import { jsonParse } from './internal/jsonParse'
10
+
11
+ class CookieStore {
12
+ #storageKey = '__msw-cookie-store__'
13
+ #jar: CookieJar
14
+ #memoryStore: MemoryCookieStore
17
15
 
18
16
  constructor() {
19
- super()
20
-
21
- invariant(
22
- typeof localStorage !== 'undefined',
23
- 'Failed to create a WebStorageCookieStore: `localStorage` is not available in this environment. This is likely an issue with MSW. Please report it on GitHub: https://github.com/mswjs/msw/issues',
24
- )
25
-
26
- this.synchronous = true
27
- this.storage = localStorage
28
- this.storageKey = '__msw-cookie-store__'
29
- }
30
-
31
- findCookie(
32
- domain: string,
33
- path: string,
34
- key: string,
35
- callback: (error: Error | null, cookie: CookieInstance | null) => void,
36
- ): void {
37
- try {
38
- const store = this.getStore()
39
- const cookies = this.filterCookiesFromList(store, { domain, path, key })
40
- callback(null, cookies[0] || null)
41
- } catch (error) {
42
- if (error instanceof Error) {
43
- callback(error, null)
44
- }
45
- }
46
- }
47
-
48
- findCookies(
49
- domain: string,
50
- path: string,
51
- allowSpecialUseDomain: boolean,
52
- callback: (error: Error | null, cookie: Array<CookieInstance>) => void,
53
- ): void {
54
- if (!domain) {
55
- callback(null, [])
56
- return
17
+ if (!isNodeProcess()) {
18
+ invariant(
19
+ typeof localStorage !== 'undefined',
20
+ 'Failed to create a CookieStore: `localStorage` is not available in this environment. This is likely an issue with your environment, which has been detected as browser (or browser-like) environment and must implement global browser APIs correctly.',
21
+ )
57
22
  }
58
23
 
59
- try {
60
- const store = this.getStore()
61
- const results = this.filterCookiesFromList(store, {
62
- domain,
63
- path,
64
- })
65
- callback(null, results)
66
- } catch (error) {
67
- if (error instanceof Error) {
68
- callback(error, [])
69
- }
70
- }
24
+ this.#memoryStore = new MemoryCookieStore()
25
+ this.#memoryStore.idx = this.getCookieStoreIndex()
26
+ this.#jar = new CookieJar(this.#memoryStore)
71
27
  }
72
28
 
73
- putCookie(
74
- cookie: CookieInstance,
75
- callback: (error: Error | null) => void,
76
- ): void {
77
- try {
78
- // Never set cookies with `maxAge` of `0`.
79
- if (cookie.maxAge === 0) {
80
- return
81
- }
82
-
83
- const store = this.getStore()
84
- store.push(cookie)
85
- this.updateStore(store)
86
- } catch (error) {
87
- if (error instanceof Error) {
88
- callback(error)
89
- }
90
- }
29
+ public getCookies(url: string): Array<Cookie> {
30
+ return this.#jar.getCookiesSync(url)
91
31
  }
92
32
 
93
- updateCookie(
94
- oldCookie: CookieInstance,
95
- newCookie: CookieInstance,
96
- callback: (error: Error | null) => void,
97
- ): void {
98
- /**
99
- * If updating a cookie with `maxAge` of `0`, remove it from the store.
100
- * Otherwise, two cookie entries will be created.
101
- * @see https://github.com/mswjs/msw/issues/2272
102
- */
103
- if (newCookie.maxAge === 0) {
104
- this.removeCookie(
105
- newCookie.domain || '',
106
- newCookie.path || '',
107
- newCookie.key,
108
- callback,
109
- )
110
- return
111
- }
112
-
113
- this.putCookie(newCookie, callback)
33
+ public async setCookie(cookieName: string, url: string): Promise<void> {
34
+ await this.#jar.setCookie(cookieName, url)
35
+ this.persist()
114
36
  }
115
37
 
116
- removeCookie(
117
- domain: string,
118
- path: string,
119
- key: string,
120
- callback: (error: Error | null) => void,
121
- ): void {
122
- try {
123
- const store = this.getStore()
124
- const nextStore = this.deleteCookiesFromList(store, { domain, path, key })
125
- this.updateStore(nextStore)
126
- callback(null)
127
- } catch (error) {
128
- if (error instanceof Error) {
129
- callback(error)
130
- }
38
+ private getCookieStoreIndex(): MemoryCookieStoreIndex {
39
+ if (typeof localStorage === 'undefined') {
40
+ return {}
131
41
  }
132
- }
133
42
 
134
- removeCookies(
135
- domain: string,
136
- path: string,
137
- callback: (error: Error | null) => void,
138
- ): void {
139
- try {
140
- const store = this.getStore()
141
- const nextStore = this.deleteCookiesFromList(store, { domain, path })
142
- this.updateStore(nextStore)
143
- callback(null)
144
- } catch (error) {
145
- if (error instanceof Error) {
146
- callback(error)
147
- }
43
+ const cookiesString = localStorage.getItem(this.#storageKey)
44
+ if (cookiesString == null) {
45
+ return {}
148
46
  }
149
- }
150
47
 
151
- getAllCookies(
152
- callback: (error: Error | null, cookie: Array<CookieInstance>) => void,
153
- ): void {
154
- try {
155
- callback(null, this.getStore())
156
- } catch (error) {
157
- if (error instanceof Error) {
158
- callback(error, [])
159
- }
48
+ const rawCookies = jsonParse<Array<Record<string, unknown>>>(cookiesString)
49
+ if (rawCookies == null) {
50
+ return {}
160
51
  }
161
- }
162
52
 
163
- private getStore(): Array<CookieInstance> {
164
- try {
165
- const json = this.storage.getItem(this.storageKey)
53
+ const cookies: MemoryCookieStoreIndex = {}
166
54
 
167
- if (json == null) {
168
- return []
169
- }
55
+ for (const rawCookie of rawCookies) {
56
+ const cookie = Cookie.fromJSON(rawCookie)
170
57
 
171
- const rawCookies = JSON.parse(json) as Array<Record<string, any>>
172
- const cookies: Array<CookieInstance> = []
173
- for (const rawCookie of rawCookies) {
174
- const cookie = Cookie.fromJSON(rawCookie)
175
- if (cookie != null) {
176
- cookies.push(cookie)
177
- }
58
+ if (cookie != null && cookie.domain != null && cookie.path != null) {
59
+ cookies[cookie.domain] ||= {}
60
+ cookies[cookie.domain][cookie.path] ||= {}
61
+ cookies[cookie.domain][cookie.path][cookie.key] = cookie
178
62
  }
179
- return cookies
180
- } catch {
181
- return []
182
63
  }
183
- }
184
64
 
185
- private updateStore(nextStore: Array<CookieInstance>) {
186
- this.storage.setItem(
187
- this.storageKey,
188
- JSON.stringify(nextStore.map((cookie) => cookie.toJSON())),
189
- )
65
+ return cookies
190
66
  }
191
67
 
192
- private filterCookiesFromList(
193
- cookies: Array<CookieInstance>,
194
- matches: { domain?: string; path?: string; key?: string },
195
- ): Array<CookieInstance> {
196
- const result: Array<CookieInstance> = []
197
-
198
- for (const cookie of cookies) {
199
- if (matches.domain && !domainMatch(matches.domain, cookie.domain || '')) {
200
- continue
201
- }
68
+ private persist(): void {
69
+ if (typeof localStorage === 'undefined') {
70
+ return
71
+ }
202
72
 
203
- if (matches.path && !pathMatch(matches.path, cookie.path || '')) {
204
- continue
205
- }
73
+ const data = []
74
+ const { idx } = this.#memoryStore
206
75
 
207
- if (matches.key && cookie.key !== matches.key) {
208
- continue
76
+ for (const domain in idx) {
77
+ for (const path in idx[domain]) {
78
+ for (const key in idx[domain][path]) {
79
+ data.push(idx[domain][path][key].toJSON())
80
+ }
209
81
  }
210
-
211
- result.push(cookie)
212
82
  }
213
83
 
214
- return result
215
- }
216
-
217
- private deleteCookiesFromList(
218
- cookies: Array<CookieInstance>,
219
- matches: { domain?: string; path?: string; key?: string },
220
- ) {
221
- const matchingCookies = this.filterCookiesFromList(cookies, matches)
222
- return cookies.filter((cookie) => !matchingCookies.includes(cookie))
84
+ localStorage.setItem(this.#storageKey, JSON.stringify(data))
223
85
  }
224
86
  }
225
87
 
226
- const store = isNodeProcess()
227
- ? new MemoryCookieStore()
228
- : new WebStorageCookieStore()
229
-
230
- export const cookieStore = new CookieJar(store)
88
+ export const cookieStore = new CookieStore()
@@ -487,3 +487,87 @@ describe('[Private] - resolutionContext - used for extensions', () => {
487
487
  })
488
488
  })
489
489
  })
490
+
491
+ describe('handler with custom predicate', () => {
492
+ test('matches if custom predicate returns true', async () => {
493
+ const { emitter, events } = setup()
494
+
495
+ const requestId = createRequestId()
496
+ const request = new Request(new URL('http://localhost/login'), {
497
+ method: 'POST',
498
+ body: JSON.stringify({ username: 'test', password: 'password' }),
499
+ headers: { 'Content-Type': 'application/json' },
500
+ })
501
+ const handlers: Array<RequestHandler> = [
502
+ http.post(
503
+ async ({ request }) => {
504
+ const body = await request.clone().json()
505
+ return body.username === 'test' && body.password === 'password'
506
+ },
507
+ () =>
508
+ HttpResponse.json({
509
+ success: true,
510
+ }),
511
+ ),
512
+ ]
513
+
514
+ const result = await handleRequest(
515
+ request,
516
+ requestId,
517
+ handlers,
518
+ options,
519
+ emitter,
520
+ handleRequestOptions,
521
+ )
522
+
523
+ expect(result).toBeDefined()
524
+ expect(await result?.json()).toStrictEqual({ success: true })
525
+ expect(events).toEqual([
526
+ ['request:start', { request, requestId }],
527
+ ['request:match', { request, requestId }],
528
+ ['request:end', { request, requestId }],
529
+ ])
530
+ expect(handleRequestOptions.onMockedResponse).toHaveBeenCalledTimes(1)
531
+ })
532
+
533
+ test('does not match if custom predicate returns false', async () => {
534
+ const { emitter, events } = setup()
535
+
536
+ const requestId = createRequestId()
537
+ const request = new Request(new URL('http://localhost/login'), {
538
+ method: 'POST',
539
+ body: JSON.stringify({ username: 'test', password: 'passwordd' }),
540
+ headers: { 'Content-Type': 'application/json' },
541
+ })
542
+ const handlers: Array<RequestHandler> = [
543
+ http.post(
544
+ async ({ request }) => {
545
+ const body = await request.clone().json()
546
+ return body.username === 'test' && body.password === 'password'
547
+ },
548
+ () =>
549
+ HttpResponse.json({
550
+ success: true,
551
+ }),
552
+ ),
553
+ ]
554
+
555
+ const result = await handleRequest(
556
+ request,
557
+ requestId,
558
+ handlers,
559
+ options,
560
+ emitter,
561
+ handleRequestOptions,
562
+ )
563
+
564
+ expect(result).toBeUndefined()
565
+ expect(events).toEqual([
566
+ ['request:start', { request, requestId }],
567
+ ['request:unhandled', { request, requestId }],
568
+ ['request:end', { request, requestId }],
569
+ ])
570
+ expect(options.onUnhandledRequest).toHaveBeenCalledTimes(1)
571
+ expect(handleRequestOptions.onPassthroughResponse).toHaveBeenCalledTimes(1)
572
+ })
573
+ })
@@ -105,7 +105,7 @@ export async function handleRequest(
105
105
  }
106
106
 
107
107
  // Store all the received response cookies in the cookie jar.
108
- storeResponseCookies(request, response)
108
+ await storeResponseCookies(request, response)
109
109
 
110
110
  emitter.emit('request:match', { request, requestId })
111
111
 
@@ -66,7 +66,7 @@ export function getAllRequestCookies(request: Request): Record<string, string> {
66
66
  )
67
67
  }
68
68
 
69
- const cookiesFromStore = cookieStore.getCookiesSync(request.url)
69
+ const cookiesFromStore = cookieStore.getCookies(request.url)
70
70
  const storedCookiesObject = Object.fromEntries(
71
71
  cookiesFromStore.map((cookie) => [cookie.key, cookie.value]),
72
72
  )
@@ -1,10 +1,10 @@
1
1
  import { cookieStore } from '../cookieStore'
2
2
  import { kSetCookie } from '../HttpResponse/decorators'
3
3
 
4
- export function storeResponseCookies(
4
+ export async function storeResponseCookies(
5
5
  request: Request,
6
6
  response: Response,
7
- ): void {
7
+ ): Promise<void> {
8
8
  // Grab the raw "Set-Cookie" response header provided
9
9
  // in the HeadersInit for this mocked response.
10
10
  const responseCookies = Reflect.get(response, kSetCookie) as
@@ -12,6 +12,6 @@ export function storeResponseCookies(
12
12
  | undefined
13
13
 
14
14
  if (responseCookies) {
15
- cookieStore.setCookie(responseCookies, request.url)
15
+ await cookieStore.setCookie(responseCookies, request.url)
16
16
  }
17
17
  }
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { toPublicUrl } from './toPublicUrl'
5
5
 
6
- test('returns an absolute request URL withouth search params', () => {
6
+ test('returns an absolute request URL without search params', () => {
7
7
  expect(toPublicUrl(new URL('https://test.mswjs.io/path'))).toBe(
8
8
  'https://test.mswjs.io/path',
9
9
  )
@@ -62,7 +62,7 @@ it('adds multiple clients from this runtime to the list of clients', async () =>
62
62
  )
63
63
  await manager.addConnection(connectionTwo)
64
64
 
65
- // Must add the new cilent to the list as well.
65
+ // Must add the new client to the list as well.
66
66
  expect(Array.from(manager.clients.values())).toEqual([
67
67
  connectionOne,
68
68
  connectionTwo,
@@ -19,7 +19,7 @@ type RequestHandlersContext = {
19
19
  /**
20
20
  * A handlers controller that utilizes `AsyncLocalStorage` in Node.js
21
21
  * to prevent the request handlers list from being a shared state
22
- * across mutliple tests.
22
+ * across multiple tests.
23
23
  */
24
24
  class AsyncHandlersController implements HandlersController {
25
25
  private rootContext: RequestHandlersContext