@depup/msw 3.0.0-depup.0 → 3.0.1-depup.0
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.
- package/README.md +2 -2
- package/changes.json +1 -1
- package/lib/_chunks/attach-sibling-handlers.js +1 -1
- package/lib/_chunks/cookie-store.js +9 -1
- package/lib/_chunks/cookie-store.js.map +1 -1
- package/lib/_chunks/http-handler.js +14 -9
- package/lib/_chunks/http-handler.js.map +1 -1
- package/lib/_chunks/http-response.js +1 -1
- package/lib/_chunks/interceptor-source.js +15 -1
- package/lib/_chunks/interceptor-source.js.map +1 -1
- package/lib/_chunks/request-handler.js +1 -1
- package/lib/_chunks/sse.js +1 -1
- package/lib/browser/index.js +1 -1
- package/lib/graphql/index.js +1 -1
- package/lib/iife/index.js +37 -10
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +1 -1
- package/lib/node/index.js +1 -1
- package/package.json +6 -6
- package/src/core/experimental/frames/http-frame.test.ts +49 -0
- package/src/core/experimental/frames/http-frame.ts +19 -0
- package/src/http/http-handler.test.ts +19 -1
- package/src/http/http-handler.ts +13 -0
- package/src/vite/plugin.test.ts +24 -6
package/lib/mockServiceWorker.js
CHANGED
package/lib/node/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { h as devUtils } from "../_chunks/cookie-store.js";
|
|
2
2
|
import { c as HandlersController, s as defineNetwork, t as InterceptorSource } from "../_chunks/interceptor-source.js";
|
|
3
3
|
import { invariant } from "outvariant";
|
|
4
4
|
import { WebSocketInterceptor } from "@mswjs/interceptors/WebSocket";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@depup/msw",
|
|
3
|
-
"version": "3.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.0.1-depup.0",
|
|
4
|
+
"description": "The industry standard for API mocking in JavaScript. (with updated dependencies)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/core/index.js",
|
|
7
7
|
"types": "./lib/core/index.d.ts",
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
"dependencies": {
|
|
126
126
|
"@inquirer/confirm": "^6.3.2",
|
|
127
127
|
"@msw/url": "^0.1.2",
|
|
128
|
-
"@mswjs/interceptors": "^0.45.
|
|
128
|
+
"@mswjs/interceptors": "^0.45.6",
|
|
129
129
|
"cookie": "^2.0.1",
|
|
130
130
|
"headers-polyfill": "^5.0.1",
|
|
131
131
|
"is-node-process": "^1.2.0",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"json-bigint": "^1.0.0",
|
|
168
168
|
"knip": "^6.34.0",
|
|
169
169
|
"lint-staged": "^17.1.1",
|
|
170
|
-
"msw": "^3.0.
|
|
170
|
+
"msw": "^3.0.1",
|
|
171
171
|
"oxlint": "^1.75.0",
|
|
172
172
|
"page-with": "^0.6.1",
|
|
173
173
|
"prettier": "^3.9.6",
|
|
@@ -238,8 +238,8 @@
|
|
|
238
238
|
},
|
|
239
239
|
"depsUpdated": 2,
|
|
240
240
|
"originalPackage": "msw",
|
|
241
|
-
"originalVersion": "3.0.
|
|
242
|
-
"processedAt": "2026-09-
|
|
241
|
+
"originalVersion": "3.0.1",
|
|
242
|
+
"processedAt": "2026-09-30T16:13:04.601Z",
|
|
243
243
|
"smokeTest": "passed"
|
|
244
244
|
}
|
|
245
245
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FetchRequest } from '@mswjs/interceptors'
|
|
1
2
|
import { http } from '#http/http'
|
|
2
3
|
import { graphql } from '../../../graphql'
|
|
3
4
|
import { ws } from '../../../ws'
|
|
@@ -169,6 +170,54 @@ test('resolves a non-matching request', async () => {
|
|
|
169
170
|
])
|
|
170
171
|
})
|
|
171
172
|
|
|
173
|
+
/**
|
|
174
|
+
* @todo Revisit the `http.all()` handler below once `http.connect()`
|
|
175
|
+
* is supported: a matching CONNECT handler must take precedence.
|
|
176
|
+
*/
|
|
177
|
+
test('passes through an unhandled CONNECT request without applying the unhandled frame strategy', async () => {
|
|
178
|
+
class HttpFrame extends HttpNetworkFrame {
|
|
179
|
+
respondWith = vi.fn()
|
|
180
|
+
passthrough = vi.fn()
|
|
181
|
+
errorWith = vi.fn()
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const frame = new HttpFrame({
|
|
185
|
+
request: new FetchRequest('http://localhost/127.0.0.1:443', {
|
|
186
|
+
method: 'CONNECT',
|
|
187
|
+
}),
|
|
188
|
+
})
|
|
189
|
+
const { events } = spyOnNetworkFrame(frame)
|
|
190
|
+
const unhandledFrameCallback = vi.fn()
|
|
191
|
+
|
|
192
|
+
const matches = await frame.resolve(
|
|
193
|
+
[
|
|
194
|
+
http.all('*', () => {
|
|
195
|
+
return new Response(null, { status: 204 })
|
|
196
|
+
}),
|
|
197
|
+
],
|
|
198
|
+
unhandledFrameCallback,
|
|
199
|
+
{ quiet: true },
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
expect.soft(matches).toBe(null)
|
|
203
|
+
expect.soft(frame.passthrough).toHaveBeenCalledOnce()
|
|
204
|
+
expect.soft(frame.respondWith).not.toHaveBeenCalled()
|
|
205
|
+
expect.soft(frame.errorWith).not.toHaveBeenCalled()
|
|
206
|
+
expect.soft(unhandledFrameCallback).not.toHaveBeenCalled()
|
|
207
|
+
expect.soft(events).toEqual([
|
|
208
|
+
expect.objectContaining({
|
|
209
|
+
type: 'request:start',
|
|
210
|
+
requestId: frame.data.id,
|
|
211
|
+
request: frame.data.request,
|
|
212
|
+
}),
|
|
213
|
+
expect.objectContaining({
|
|
214
|
+
type: 'request:end',
|
|
215
|
+
requestId: frame.data.id,
|
|
216
|
+
request: frame.data.request,
|
|
217
|
+
}),
|
|
218
|
+
])
|
|
219
|
+
})
|
|
220
|
+
|
|
172
221
|
test('resolves a matched passthrough', async () => {
|
|
173
222
|
class HttpFrame extends HttpNetworkFrame {
|
|
174
223
|
respondWith = vi.fn()
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type NetworkFrameResolutionContext,
|
|
7
7
|
} from './network-frame'
|
|
8
8
|
import { toPublicUrl } from '../../utils/request/to-public-url'
|
|
9
|
+
import { isStringEqual } from '../../utils/internal/is-string-equal'
|
|
9
10
|
import { executeHandlers } from '../../utils/execute-handlers'
|
|
10
11
|
import { storeResponseCookies } from '../../utils/request/store-response-cookies'
|
|
11
12
|
import { shouldBypassRequest } from '../request-utils'
|
|
@@ -191,6 +192,24 @@ export abstract class HttpNetworkFrame extends NetworkFrame<
|
|
|
191
192
|
|
|
192
193
|
// No matching handlers.
|
|
193
194
|
if (lookupResult == null) {
|
|
195
|
+
/**
|
|
196
|
+
* @note Unhandled CONNECT requests establish a tunnel through a proxy.
|
|
197
|
+
* They are transport, not the request the developer cares about, so
|
|
198
|
+
* they pass through silently regardless of the unhandled frame strategy.
|
|
199
|
+
* The request sent through the tunnel gets its own resolution.
|
|
200
|
+
*/
|
|
201
|
+
if (isStringEqual(request.method, 'CONNECT')) {
|
|
202
|
+
this.events.emit(
|
|
203
|
+
new RequestEvent('request:end', {
|
|
204
|
+
requestId,
|
|
205
|
+
request,
|
|
206
|
+
}),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
this.passthrough()
|
|
210
|
+
return null
|
|
211
|
+
}
|
|
212
|
+
|
|
194
213
|
this.events.emit(
|
|
195
214
|
new RequestEvent('request:unhandled', {
|
|
196
215
|
requestId,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
|
-
import { createRequestId } from '@mswjs/interceptors'
|
|
2
|
+
import { createRequestId, FetchRequest } from '@mswjs/interceptors'
|
|
3
3
|
import type { HttpRequestResolverExtras } from './http-handler'
|
|
4
4
|
import { HttpHandler } from './http-handler'
|
|
5
5
|
import { HttpResponse } from './index'
|
|
@@ -70,6 +70,24 @@ describe('parse', () => {
|
|
|
70
70
|
})
|
|
71
71
|
|
|
72
72
|
describe('predicate', () => {
|
|
73
|
+
/**
|
|
74
|
+
* @todo Decide whether `http.all()` matches CONNECT requests
|
|
75
|
+
* once `http.connect()` is supported.
|
|
76
|
+
*/
|
|
77
|
+
test('returns false given a CONNECT request', async () => {
|
|
78
|
+
const handler = new HttpHandler(/.+/, '*', resolver)
|
|
79
|
+
const request = new FetchRequest('http://localhost/127.0.0.1:443', {
|
|
80
|
+
method: 'CONNECT',
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
await expect(
|
|
84
|
+
handler.predicate({
|
|
85
|
+
request,
|
|
86
|
+
parsedResult: await handler.parse({ request }),
|
|
87
|
+
}),
|
|
88
|
+
).resolves.toBe(false)
|
|
89
|
+
})
|
|
90
|
+
|
|
73
91
|
test('returns true given a matching request', async () => {
|
|
74
92
|
const handler = new HttpHandler('POST', '/login', resolver)
|
|
75
93
|
const request = new Request(new URL('/login', location.href), {
|
package/src/http/http-handler.ts
CHANGED
|
@@ -122,6 +122,19 @@ export class HttpHandler extends RequestHandler<
|
|
|
122
122
|
request: Request
|
|
123
123
|
resolutionContext?: ResponseResolutionContext
|
|
124
124
|
}) {
|
|
125
|
+
/**
|
|
126
|
+
* @note CONNECT requests target an authority ("host:port"), not a URL.
|
|
127
|
+
* HTTP handlers never match them.
|
|
128
|
+
* @todo Match the authority against the handler path once
|
|
129
|
+
* `http.connect()` is supported instead of bailing out.
|
|
130
|
+
*/
|
|
131
|
+
if (isStringEqual(args.request.method, 'CONNECT')) {
|
|
132
|
+
return {
|
|
133
|
+
match: { matches: false, params: {} },
|
|
134
|
+
cookies: {},
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
125
138
|
const url = new URL(args.request.url)
|
|
126
139
|
const cookies = getAllRequestCookies(args.request)
|
|
127
140
|
|
package/src/vite/plugin.test.ts
CHANGED
|
@@ -454,6 +454,9 @@ document.querySelector('output').textContent = String(network.readyState)
|
|
|
454
454
|
let completedUpdates = 0
|
|
455
455
|
|
|
456
456
|
if (import.meta.hot) {
|
|
457
|
+
import.meta.hot.on('vite:beforeUpdate', () => {
|
|
458
|
+
document.body.dataset.disabledBeforeUpdate = String(network.readyState === 0)
|
|
459
|
+
})
|
|
457
460
|
import.meta.hot.on('vite:afterUpdate', () => {
|
|
458
461
|
document.body.dataset.completedUpdates = String(++completedUpdates)
|
|
459
462
|
})
|
|
@@ -519,18 +522,33 @@ document.querySelector('button').onclick = async () => {
|
|
|
519
522
|
await page.getByRole('button', { name: 'Enable' }).click()
|
|
520
523
|
|
|
521
524
|
await expect.poll(() => page.locator('output').textContent()).toBe('mocked')
|
|
525
|
+
await page.evaluate(() => {
|
|
526
|
+
delete document.body.dataset.disabledBeforeUpdate
|
|
527
|
+
})
|
|
522
528
|
server.environments.client.hot.send({ type: 'update', updates: [] })
|
|
523
529
|
|
|
524
530
|
await expect
|
|
525
531
|
.poll(() => page.locator('body').getAttribute('data-completed-updates'))
|
|
526
532
|
.toBe('2')
|
|
527
533
|
await expect(
|
|
528
|
-
page.
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
+
page.locator('body').getAttribute('data-disabled-before-update'),
|
|
535
|
+
).resolves.toBe('true')
|
|
536
|
+
/**
|
|
537
|
+
* @note The runtime re-enables the network after the update asynchronously:
|
|
538
|
+
* the worker has to be re-activated before it can respond with mocks.
|
|
539
|
+
* Until then, requests reach the dev server. Poll for the mocked response.
|
|
540
|
+
*/
|
|
541
|
+
await expect
|
|
542
|
+
.poll(
|
|
543
|
+
() =>
|
|
544
|
+
page.evaluate(async () => {
|
|
545
|
+
const response = await fetch('/resource')
|
|
546
|
+
|
|
547
|
+
return response.text()
|
|
548
|
+
}),
|
|
549
|
+
{ timeout: 10_000 },
|
|
550
|
+
)
|
|
551
|
+
.toBe('mocked')
|
|
534
552
|
await expect(
|
|
535
553
|
page.evaluate(async () => {
|
|
536
554
|
const registrations = await navigator.serviceWorker.getRegistrations()
|