@mswjs/interceptors 0.31.1 → 0.32.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 (69) hide show
  1. package/README.md +56 -39
  2. package/lib/node/RemoteHttpInterceptor.d.ts +1 -2
  3. package/lib/node/RemoteHttpInterceptor.js +11 -11
  4. package/lib/node/RemoteHttpInterceptor.mjs +5 -5
  5. package/lib/node/{chunk-LTEXDYJ6.js → chunk-2COJKQQB.js} +3 -3
  6. package/lib/node/chunk-3OJLYEWA.mjs +963 -0
  7. package/lib/node/chunk-3OJLYEWA.mjs.map +1 -0
  8. package/lib/node/chunk-5JMJ55U7.js +963 -0
  9. package/lib/node/chunk-5JMJ55U7.js.map +1 -0
  10. package/lib/node/{chunk-E4AC7YAC.js → chunk-BFLYGQ6D.js} +4 -2
  11. package/lib/node/{chunk-KSHIDGUL.mjs → chunk-DV4PBH4D.mjs} +3 -3
  12. package/lib/node/{chunk-OUWBQF3Z.mjs → chunk-KWV3JXSI.mjs} +14 -14
  13. package/lib/node/chunk-KWV3JXSI.mjs.map +1 -0
  14. package/lib/node/{chunk-6FRASLM3.mjs → chunk-PNWPIDEL.mjs} +2 -2
  15. package/lib/node/{chunk-APT7KA3B.js → chunk-PYD4E2EJ.js} +13 -13
  16. package/lib/node/{chunk-Q7POAM5N.mjs → chunk-TGTPXCLF.mjs} +3 -1
  17. package/lib/node/{chunk-MQJ3JOOK.js → chunk-UXCYRE4F.js} +14 -14
  18. package/lib/node/chunk-UXCYRE4F.js.map +1 -0
  19. package/lib/node/index.js +3 -3
  20. package/lib/node/index.mjs +2 -2
  21. package/lib/node/interceptors/ClientRequest/index.d.ts +83 -14
  22. package/lib/node/interceptors/ClientRequest/index.js +4 -4
  23. package/lib/node/interceptors/ClientRequest/index.mjs +3 -3
  24. package/lib/node/interceptors/XMLHttpRequest/index.js +4 -4
  25. package/lib/node/interceptors/XMLHttpRequest/index.mjs +3 -3
  26. package/lib/node/interceptors/fetch/index.js +10 -10
  27. package/lib/node/interceptors/fetch/index.mjs +2 -2
  28. package/lib/node/presets/node.d.ts +2 -3
  29. package/lib/node/presets/node.js +6 -6
  30. package/lib/node/presets/node.mjs +4 -4
  31. package/package.json +2 -2
  32. package/src/interceptors/ClientRequest/MockHttpSocket.ts +595 -0
  33. package/src/interceptors/ClientRequest/agents.ts +78 -0
  34. package/src/interceptors/ClientRequest/index.test.ts +14 -12
  35. package/src/interceptors/ClientRequest/index.ts +200 -41
  36. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +78 -98
  37. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +40 -22
  38. package/src/interceptors/Socket/MockSocket.test.ts +264 -0
  39. package/src/interceptors/Socket/MockSocket.ts +59 -0
  40. package/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +26 -0
  41. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts +52 -0
  42. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +33 -0
  43. package/src/interceptors/Socket/utils/parseRawHeaders.ts +10 -0
  44. package/lib/node/chunk-IS3CIGXU.js +0 -909
  45. package/lib/node/chunk-IS3CIGXU.js.map +0 -1
  46. package/lib/node/chunk-MQJ3JOOK.js.map +0 -1
  47. package/lib/node/chunk-OMOWHUE6.mjs +0 -909
  48. package/lib/node/chunk-OMOWHUE6.mjs.map +0 -1
  49. package/lib/node/chunk-OUWBQF3Z.mjs.map +0 -1
  50. package/src/interceptors/ClientRequest/NodeClientRequest.test.ts +0 -206
  51. package/src/interceptors/ClientRequest/NodeClientRequest.ts +0 -680
  52. package/src/interceptors/ClientRequest/http.get.ts +0 -30
  53. package/src/interceptors/ClientRequest/http.request.ts +0 -27
  54. package/src/interceptors/ClientRequest/utils/cloneIncomingMessage.test.ts +0 -26
  55. package/src/interceptors/ClientRequest/utils/cloneIncomingMessage.ts +0 -74
  56. package/src/interceptors/ClientRequest/utils/createRequest.test.ts +0 -144
  57. package/src/interceptors/ClientRequest/utils/createRequest.ts +0 -51
  58. package/src/interceptors/ClientRequest/utils/createResponse.test.ts +0 -53
  59. package/src/interceptors/ClientRequest/utils/createResponse.ts +0 -55
  60. package/src/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.test.ts +0 -41
  61. package/src/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.ts +0 -53
  62. package/src/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.test.ts +0 -36
  63. package/src/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.ts +0 -39
  64. /package/lib/node/{chunk-LTEXDYJ6.js.map → chunk-2COJKQQB.js.map} +0 -0
  65. /package/lib/node/{chunk-E4AC7YAC.js.map → chunk-BFLYGQ6D.js.map} +0 -0
  66. /package/lib/node/{chunk-KSHIDGUL.mjs.map → chunk-DV4PBH4D.mjs.map} +0 -0
  67. /package/lib/node/{chunk-6FRASLM3.mjs.map → chunk-PNWPIDEL.mjs.map} +0 -0
  68. /package/lib/node/{chunk-APT7KA3B.js.map → chunk-PYD4E2EJ.js.map} +0 -0
  69. /package/lib/node/{chunk-Q7POAM5N.mjs.map → chunk-TGTPXCLF.mjs.map} +0 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * @vitest-environment node
3
+ */
4
+ import { Socket } from 'node:net'
5
+ import { vi, it, expect } from 'vitest'
6
+ import { MockSocket } from './MockSocket'
7
+
8
+ it(`keeps the socket connecting until it's destroyed`, () => {
9
+ const socket = new MockSocket({
10
+ write: vi.fn(),
11
+ read: vi.fn(),
12
+ })
13
+
14
+ expect(socket.connecting).toBe(true)
15
+
16
+ socket.destroy()
17
+ expect(socket.connecting).toBe(false)
18
+ })
19
+
20
+ it('calls the "write" on "socket.write()"', () => {
21
+ const writeCallback = vi.fn()
22
+ const socket = new MockSocket({
23
+ write: writeCallback,
24
+ read: vi.fn(),
25
+ })
26
+
27
+ socket.write()
28
+ expect(writeCallback).toHaveBeenCalledWith(undefined, undefined, undefined)
29
+ })
30
+
31
+ it('calls the "write" on "socket.write(chunk)"', () => {
32
+ const writeCallback = vi.fn()
33
+ const socket = new MockSocket({
34
+ write: writeCallback,
35
+ read: vi.fn(),
36
+ })
37
+
38
+ socket.write('hello')
39
+ expect(writeCallback).toHaveBeenCalledWith('hello', undefined, undefined)
40
+ })
41
+
42
+ it('calls the "write" on "socket.write(chunk, encoding)"', () => {
43
+ const writeCallback = vi.fn()
44
+ const socket = new MockSocket({
45
+ write: writeCallback,
46
+ read: vi.fn(),
47
+ })
48
+
49
+ socket.write('hello', 'utf8')
50
+ expect(writeCallback).toHaveBeenCalledWith('hello', 'utf8', undefined)
51
+ })
52
+
53
+ it('calls the "write" on "socket.write(chunk, encoding, callback)"', () => {
54
+ const writeCallback = vi.fn()
55
+ const socket = new MockSocket({
56
+ write: writeCallback,
57
+ read: vi.fn(),
58
+ })
59
+
60
+ const callback = vi.fn()
61
+ socket.write('hello', 'utf8', callback)
62
+ expect(writeCallback).toHaveBeenCalledWith('hello', 'utf8', callback)
63
+ })
64
+
65
+ it('calls the "write" on "socket.end()"', () => {
66
+ const writeCallback = vi.fn()
67
+ const socket = new MockSocket({
68
+ write: writeCallback,
69
+ read: vi.fn(),
70
+ })
71
+
72
+ socket.end()
73
+ expect(writeCallback).toHaveBeenCalledWith(undefined, undefined, undefined)
74
+ })
75
+
76
+ it('calls the "write" on "socket.end(chunk)"', () => {
77
+ const writeCallback = vi.fn()
78
+ const socket = new MockSocket({
79
+ write: writeCallback,
80
+ read: vi.fn(),
81
+ })
82
+
83
+ socket.end('final')
84
+ expect(writeCallback).toHaveBeenCalledWith('final', undefined, undefined)
85
+ })
86
+
87
+ it('calls the "write" on "socket.end(chunk, encoding)"', () => {
88
+ const writeCallback = vi.fn()
89
+ const socket = new MockSocket({
90
+ write: writeCallback,
91
+ read: vi.fn(),
92
+ })
93
+
94
+ socket.end('final', 'utf8')
95
+ expect(writeCallback).toHaveBeenCalledWith('final', 'utf8', undefined)
96
+ })
97
+
98
+ it('calls the "write" on "socket.end(chunk, encoding, callback)"', () => {
99
+ const writeCallback = vi.fn()
100
+ const socket = new MockSocket({
101
+ write: writeCallback,
102
+ read: vi.fn(),
103
+ })
104
+
105
+ const callback = vi.fn()
106
+ socket.end('final', 'utf8', callback)
107
+ expect(writeCallback).toHaveBeenCalledWith('final', 'utf8', callback)
108
+ })
109
+
110
+ it('calls the "write" on "socket.end()" without any arguments', () => {
111
+ const writeCallback = vi.fn()
112
+ const socket = new MockSocket({
113
+ write: writeCallback,
114
+ read: vi.fn(),
115
+ })
116
+
117
+ socket.end()
118
+ expect(writeCallback).toHaveBeenCalledWith(undefined, undefined, undefined)
119
+ })
120
+
121
+ it('emits "finished" on .end() without any arguments', async () => {
122
+ const finishListener = vi.fn()
123
+ const socket = new MockSocket({
124
+ write: vi.fn(),
125
+ read: vi.fn(),
126
+ })
127
+ socket.on('finish', finishListener)
128
+ socket.end()
129
+
130
+ await vi.waitFor(() => {
131
+ expect(finishListener).toHaveBeenCalledTimes(1)
132
+ })
133
+ })
134
+
135
+ it('calls the "read" on "socket.read(chunk)"', () => {
136
+ const readCallback = vi.fn()
137
+ const socket = new MockSocket({
138
+ write: vi.fn(),
139
+ read: readCallback,
140
+ })
141
+
142
+ socket.push('hello')
143
+ expect(readCallback).toHaveBeenCalledWith('hello', undefined)
144
+ })
145
+
146
+ it('calls the "read" on "socket.read(chunk, encoding)"', () => {
147
+ const readCallback = vi.fn()
148
+ const socket = new MockSocket({
149
+ write: vi.fn(),
150
+ read: readCallback,
151
+ })
152
+
153
+ socket.push('world', 'utf8')
154
+ expect(readCallback).toHaveBeenCalledWith('world', 'utf8')
155
+ })
156
+
157
+ it('calls the "read" on "socket.read(null)"', () => {
158
+ const readCallback = vi.fn()
159
+ const socket = new MockSocket({
160
+ write: vi.fn(),
161
+ read: readCallback,
162
+ })
163
+
164
+ socket.push(null)
165
+ expect(readCallback).toHaveBeenCalledWith(null, undefined)
166
+ })
167
+
168
+ it('updates the writable state on "socket.end()"', async () => {
169
+ const finishListener = vi.fn()
170
+ const endListener = vi.fn()
171
+ const socket = new MockSocket({
172
+ write: vi.fn(),
173
+ read: vi.fn(),
174
+ })
175
+ socket.on('finish', finishListener)
176
+ socket.on('end', endListener)
177
+
178
+ expect(socket.writable).toBe(true)
179
+ expect(socket.writableEnded).toBe(false)
180
+ expect(socket.writableFinished).toBe(false)
181
+
182
+ socket.write('hello')
183
+ // Finish the writable stream.
184
+ socket.end()
185
+
186
+ expect(socket.writable).toBe(false)
187
+ expect(socket.writableEnded).toBe(true)
188
+
189
+ // The "finish" event is emitted when writable is done.
190
+ // I.e. "socket.end()" is called.
191
+ await vi.waitFor(() => {
192
+ expect(finishListener).toHaveBeenCalledTimes(1)
193
+ })
194
+ expect(socket.writableFinished).toBe(true)
195
+ })
196
+
197
+ it('updates the readable state on "socket.push(null)"', async () => {
198
+ const endListener = vi.fn()
199
+ const socket = new MockSocket({
200
+ write: vi.fn(),
201
+ read: vi.fn(),
202
+ })
203
+ socket.on('end', endListener)
204
+
205
+ expect(socket.readable).toBe(true)
206
+ expect(socket.readableEnded).toBe(false)
207
+
208
+ socket.push('hello')
209
+ socket.push(null)
210
+
211
+ expect(socket.readable).toBe(true)
212
+ expect(socket.readableEnded).toBe(false)
213
+
214
+ // Read the data to free the buffer and
215
+ // make Socket emit "end".
216
+ socket.read()
217
+
218
+ await vi.waitFor(() => {
219
+ expect(endListener).toHaveBeenCalledTimes(1)
220
+ })
221
+ expect(socket.readable).toBe(false)
222
+ expect(socket.readableEnded).toBe(true)
223
+ })
224
+
225
+ it('updates the readable/writable state on "socket.destroy()"', async () => {
226
+ const finishListener = vi.fn()
227
+ const endListener = vi.fn()
228
+ const closeListener = vi.fn()
229
+ const socket = new MockSocket({
230
+ write: vi.fn(),
231
+ read: vi.fn(),
232
+ })
233
+ socket.on('finish', finishListener)
234
+ socket.on('end', endListener)
235
+ socket.on('close', closeListener)
236
+
237
+ expect(socket.writable).toBe(true)
238
+ expect(socket.writableEnded).toBe(false)
239
+ expect(socket.writableFinished).toBe(false)
240
+ expect(socket.readable).toBe(true)
241
+
242
+ socket.destroy()
243
+
244
+ expect(socket.writable).toBe(false)
245
+ // The ".end()" wasn't called.
246
+ expect(socket.writableEnded).toBe(false)
247
+ expect(socket.writableFinished).toBe(false)
248
+ expect(socket.readable).toBe(false)
249
+
250
+ await vi.waitFor(() => {
251
+ expect(closeListener).toHaveBeenCalledTimes(1)
252
+ })
253
+
254
+ // Neither "finish" nor "end" events are emitted
255
+ // when you destroy the stream. If you want those,
256
+ // call ".end()", then destroy the stream.
257
+ expect(finishListener).not.toHaveBeenCalled()
258
+ expect(endListener).not.toHaveBeenCalled()
259
+ expect(socket.writableFinished).toBe(false)
260
+
261
+ // The "end" event was never emitted so "readableEnded"
262
+ // remains false.
263
+ expect(socket.readableEnded).toBe(false)
264
+ })
@@ -0,0 +1,59 @@
1
+ import net from 'node:net'
2
+ import {
3
+ normalizeSocketWriteArgs,
4
+ type WriteArgs,
5
+ type WriteCallback,
6
+ } from './utils/normalizeSocketWriteArgs'
7
+
8
+ export interface MockSocketOptions {
9
+ write: (
10
+ chunk: Buffer | string,
11
+ encoding: BufferEncoding | undefined,
12
+ callback?: WriteCallback
13
+ ) => void
14
+
15
+ read: (chunk: Buffer, encoding: BufferEncoding | undefined) => void
16
+ }
17
+
18
+ export class MockSocket extends net.Socket {
19
+ public connecting: boolean
20
+
21
+ constructor(protected readonly options: MockSocketOptions) {
22
+ super()
23
+ this.connecting = false
24
+ this.connect()
25
+
26
+ this._final = (callback) => {
27
+ callback(null)
28
+ }
29
+ }
30
+
31
+ public connect() {
32
+ // The connection will remain pending until
33
+ // the consumer decides to handle it.
34
+ this.connecting = true
35
+ return this
36
+ }
37
+
38
+ public write(...args: Array<unknown>): boolean {
39
+ const [chunk, encoding, callback] = normalizeSocketWriteArgs(
40
+ args as WriteArgs
41
+ )
42
+ this.options.write(chunk, encoding, callback)
43
+ return true
44
+ }
45
+
46
+ public end(...args: Array<unknown>) {
47
+ const [chunk, encoding, callback] = normalizeSocketWriteArgs(
48
+ args as WriteArgs
49
+ )
50
+ this.options.write(chunk, encoding, callback)
51
+
52
+ return super.end.apply(this, args as any)
53
+ }
54
+
55
+ public push(chunk: any, encoding?: BufferEncoding): boolean {
56
+ this.options.read(chunk, encoding)
57
+ return super.push(chunk, encoding)
58
+ }
59
+ }
@@ -0,0 +1,26 @@
1
+ export function baseUrlFromConnectionOptions(options: any): URL {
2
+ if ('href' in options) {
3
+ return new URL(options.href)
4
+ }
5
+
6
+ const protocol = options.port === 443 ? 'https:' : 'http:'
7
+ const host = options.host
8
+
9
+ const url = new URL(`${protocol}//${host}`)
10
+
11
+ if (options.port) {
12
+ url.port = options.port.toString()
13
+ }
14
+
15
+ if (options.path) {
16
+ url.pathname = options.path
17
+ }
18
+
19
+ if (options.auth) {
20
+ const [username, password] = options.auth.split(':')
21
+ url.username = username
22
+ url.password = password
23
+ }
24
+
25
+ return url
26
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @vitest-environment node
3
+ */
4
+ import { it, expect } from 'vitest'
5
+ import { normalizeSocketWriteArgs } from './normalizeSocketWriteArgs'
6
+
7
+ it('normalizes .write()', () => {
8
+ expect(normalizeSocketWriteArgs([undefined])).toEqual([
9
+ undefined,
10
+ undefined,
11
+ undefined,
12
+ ])
13
+ expect(normalizeSocketWriteArgs([null])).toEqual([null, undefined, undefined])
14
+ })
15
+
16
+ it('normalizes .write(chunk)', () => {
17
+ expect(normalizeSocketWriteArgs([Buffer.from('hello')])).toEqual([
18
+ Buffer.from('hello'),
19
+ undefined,
20
+ undefined,
21
+ ])
22
+ expect(normalizeSocketWriteArgs(['hello'])).toEqual([
23
+ 'hello',
24
+ undefined,
25
+ undefined,
26
+ ])
27
+ expect(normalizeSocketWriteArgs([null])).toEqual([null, undefined, undefined])
28
+ })
29
+
30
+ it('normalizes .write(chunk, encoding)', () => {
31
+ expect(normalizeSocketWriteArgs([Buffer.from('hello'), 'utf8'])).toEqual([
32
+ Buffer.from('hello'),
33
+ 'utf8',
34
+ undefined,
35
+ ])
36
+ })
37
+
38
+ it('normalizes .write(chunk, callback)', () => {
39
+ const callback = () => {}
40
+ expect(normalizeSocketWriteArgs([Buffer.from('hello'), callback])).toEqual([
41
+ Buffer.from('hello'),
42
+ undefined,
43
+ callback,
44
+ ])
45
+ })
46
+
47
+ it('normalizes .write(chunk, encoding, callback)', () => {
48
+ const callback = () => {}
49
+ expect(
50
+ normalizeSocketWriteArgs([Buffer.from('hello'), 'utf8', callback])
51
+ ).toEqual([Buffer.from('hello'), 'utf8', callback])
52
+ })
@@ -0,0 +1,33 @@
1
+ export type WriteCallback = (error?: Error | null) => void
2
+
3
+ export type WriteArgs =
4
+ | [chunk: unknown, callback?: WriteCallback]
5
+ | [chunk: unknown, encoding: BufferEncoding, callback?: WriteCallback]
6
+
7
+ export type NormalizedSocketWriteArgs = [
8
+ chunk: any,
9
+ encoding?: BufferEncoding,
10
+ callback?: WriteCallback,
11
+ ]
12
+
13
+ /**
14
+ * Normalizes the arguments provided to the `Writable.prototype.write()`
15
+ * and `Writable.prototype.end()`.
16
+ */
17
+ export function normalizeSocketWriteArgs(
18
+ args: WriteArgs
19
+ ): NormalizedSocketWriteArgs {
20
+ const normalized: NormalizedSocketWriteArgs = [args[0], undefined, undefined]
21
+
22
+ if (typeof args[1] === 'string') {
23
+ normalized[1] = args[1]
24
+ } else if (typeof args[1] === 'function') {
25
+ normalized[2] = args[1]
26
+ }
27
+
28
+ if (typeof args[2] === 'function') {
29
+ normalized[2] = args[2]
30
+ }
31
+
32
+ return normalized
33
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Create a Fetch API `Headers` instance from the given raw headers list.
3
+ */
4
+ export function parseRawHeaders(rawHeaders: Array<string>): Headers {
5
+ const headers = new Headers()
6
+ for (let line = 0; line < rawHeaders.length; line += 2) {
7
+ headers.append(rawHeaders[line], rawHeaders[line + 1])
8
+ }
9
+ return headers
10
+ }