@mswjs/interceptors 0.21.1 → 0.22.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/lib/browser/interceptors/XMLHttpRequest/index.js +0 -4
- package/lib/browser/interceptors/XMLHttpRequest/index.mjs +0 -4
- package/lib/node/RemoteHttpInterceptor.js +11 -15
- package/lib/node/RemoteHttpInterceptor.mjs +5 -9
- package/lib/node/{chunk-ZSI7MX3V.mjs → chunk-37CATPNG.mjs} +0 -34
- package/lib/node/{chunk-ZWCZGO3W.mjs → chunk-CYWTKHFI.mjs} +2 -7
- package/lib/node/{chunk-CIN5URNI.mjs → chunk-G6ZTHYZQ.mjs} +1 -1
- package/lib/node/{chunk-HDUJCCWF.js → chunk-GGD5JOGB.js} +9 -14
- package/lib/node/{chunk-JISWS3Y3.mjs → chunk-KZEQH4YW.mjs} +1 -1
- package/lib/node/{chunk-UVNTVJHD.js → chunk-PRX3F52M.js} +17 -17
- package/lib/node/{chunk-KZJG2UW7.js → chunk-Q56TMOP5.js} +2 -2
- package/lib/node/{chunk-6GWWOJ23.js → chunk-SNNL2EXF.js} +3 -3
- package/lib/node/{chunk-Z5JAVEOB.mjs → chunk-SWJ33XIS.mjs} +10 -10
- package/lib/node/{chunk-QMIXLBOU.js → chunk-WWHITCCI.js} +2 -36
- package/lib/node/index.js +4 -4
- package/lib/node/index.mjs +3 -3
- package/lib/node/interceptors/ClientRequest/index.js +3 -4
- package/lib/node/interceptors/ClientRequest/index.mjs +2 -3
- package/lib/node/interceptors/XMLHttpRequest/index.js +4 -5
- package/lib/node/interceptors/XMLHttpRequest/index.mjs +3 -4
- package/lib/node/interceptors/fetch/index.js +2 -2
- package/lib/node/interceptors/fetch/index.mjs +1 -1
- package/package.json +11 -9
- package/src/BatchInterceptor.test.ts +8 -7
- package/src/Interceptor.test.ts +6 -5
- package/src/RemoteHttpInterceptor.ts +0 -1
- package/src/interceptors/ClientRequest/NodeClientRequest.test.ts +107 -85
- package/src/interceptors/ClientRequest/NodeClientRequest.ts +14 -6
- package/src/interceptors/ClientRequest/index.test.ts +20 -8
- package/src/interceptors/ClientRequest/utils/cloneIncomingMessage.test.ts +2 -1
- package/src/interceptors/ClientRequest/utils/createRequest.test.ts +1 -0
- package/src/interceptors/ClientRequest/utils/createRequest.ts +0 -1
- package/src/interceptors/ClientRequest/utils/createResponse.test.ts +1 -3
- package/src/interceptors/ClientRequest/utils/createResponse.ts +0 -1
- package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +5 -4
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +19 -18
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.test.ts +6 -5
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.test.ts +5 -4
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +0 -1
- package/src/interceptors/XMLHttpRequest/utils/concateArrayBuffer.test.ts +1 -3
- package/src/interceptors/XMLHttpRequest/utils/createEvent.test.ts +4 -5
- package/src/interceptors/XMLHttpRequest/utils/createResponse.ts +0 -1
- package/src/interceptors/fetch/index.ts +1 -2
- package/src/utils/AsyncEventEmitter.test.ts +8 -7
- package/src/utils/bufferUtils.test.ts +1 -0
- package/src/utils/cloneObject.test.ts +6 -5
- package/src/utils/getCleanUrl.test.ts +5 -4
- package/src/utils/getUrlByRequestOptions.test.ts +11 -10
- package/src/utils/getUrlByRequestOptions.ts +14 -1
- package/src/utils/isObject.test.ts +4 -3
- package/src/utils/parseJson.test.ts +3 -2
- package/lib/node/chunk-6V3JXLBF.js +0 -6093
- package/lib/node/chunk-NNVTJLQA.mjs +0 -6093
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
1
2
|
import { IncomingMessage } from 'http'
|
|
2
3
|
import { Socket } from 'net'
|
|
3
4
|
import * as zlib from 'zlib'
|
|
4
5
|
import { getIncomingMessageBody } from './getIncomingMessageBody'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
it('returns utf8 string given a utf8 response body', async () => {
|
|
7
8
|
const utfBuffer = Buffer.from('one')
|
|
8
9
|
const message = new IncomingMessage(new Socket())
|
|
9
10
|
|
|
@@ -14,7 +15,7 @@ test('returns utf8 string given a utf8 response body', async () => {
|
|
|
14
15
|
expect(await pendingResponseBody).toEqual('one')
|
|
15
16
|
})
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
it('returns utf8 string given a gzipped response body', async () => {
|
|
18
19
|
const utfBuffer = zlib.gzipSync(Buffer.from('two'))
|
|
19
20
|
const message = new IncomingMessage(new Socket())
|
|
20
21
|
message.headers = {
|
|
@@ -28,7 +29,7 @@ test('returns utf8 string given a gzipped response body', async () => {
|
|
|
28
29
|
expect(await pendingResponseBody).toEqual('two')
|
|
29
30
|
})
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
it('returns utf8 string given a gzipped response body with incorrect "content-lenght"', async () => {
|
|
32
33
|
const utfBuffer = zlib.gzipSync(Buffer.from('three'))
|
|
33
34
|
const message = new IncomingMessage(new Socket())
|
|
34
35
|
message.headers = {
|
|
@@ -43,7 +44,7 @@ test('returns utf8 string given a gzipped response body with incorrect "content-
|
|
|
43
44
|
expect(await pendingResponseBody).toEqual('three')
|
|
44
45
|
})
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
it('returns empty string given an empty body', async () => {
|
|
47
48
|
const message = new IncomingMessage(new Socket())
|
|
48
49
|
|
|
49
50
|
const pendingResponseBody = getIncomingMessageBody(message)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
1
2
|
import { parse } from 'url'
|
|
2
3
|
import { globalAgent as httpGlobalAgent, RequestOptions } from 'http'
|
|
3
4
|
import { Agent as HttpsAgent, globalAgent as httpsGlobalAgent } from 'https'
|
|
4
5
|
import { getUrlByRequestOptions } from '../../../utils/getUrlByRequestOptions'
|
|
5
6
|
import { normalizeClientRequestArgs } from './normalizeClientRequestArgs'
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
it('handles [string, callback] input', () => {
|
|
8
9
|
const [url, options, callback] = normalizeClientRequestArgs(
|
|
9
10
|
'https:',
|
|
10
11
|
'https://mswjs.io/resource',
|
|
@@ -24,7 +25,7 @@ test('handles [string, callback] input', () => {
|
|
|
24
25
|
expect(callback?.name).toEqual('cb')
|
|
25
26
|
})
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
it('handles [string, RequestOptions, callback] input', () => {
|
|
28
29
|
const initialOptions = {
|
|
29
30
|
headers: {
|
|
30
31
|
'Content-Type': 'text/plain',
|
|
@@ -47,7 +48,7 @@ test('handles [string, RequestOptions, callback] input', () => {
|
|
|
47
48
|
expect(callback?.name).toEqual('cb')
|
|
48
49
|
})
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
it('handles [URL, callback] input', () => {
|
|
51
52
|
const [url, options, callback] = normalizeClientRequestArgs(
|
|
52
53
|
'https:',
|
|
53
54
|
new URL('https://mswjs.io/resource'),
|
|
@@ -67,7 +68,7 @@ test('handles [URL, callback] input', () => {
|
|
|
67
68
|
expect(callback?.name).toEqual('cb')
|
|
68
69
|
})
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
it('handles [Absolute Legacy URL, callback] input', () => {
|
|
71
72
|
const [url, options, callback] = normalizeClientRequestArgs(
|
|
72
73
|
'https:',
|
|
73
74
|
parse('https://cherry:durian@mswjs.io:12345/resource?apple=banana'),
|
|
@@ -93,7 +94,7 @@ test('handles [Absolute Legacy URL, callback] input', () => {
|
|
|
93
94
|
expect(callback?.name).toEqual('cb')
|
|
94
95
|
})
|
|
95
96
|
|
|
96
|
-
|
|
97
|
+
it('handles [Relative Legacy URL, RequestOptions without path set, callback] input', () => {
|
|
97
98
|
const [url, options, callback] = normalizeClientRequestArgs(
|
|
98
99
|
'http:',
|
|
99
100
|
parse('/resource?apple=banana'),
|
|
@@ -115,7 +116,7 @@ test('handles [Relative Legacy URL, RequestOptions without path set, callback] i
|
|
|
115
116
|
expect(callback?.name).toEqual('cb')
|
|
116
117
|
})
|
|
117
118
|
|
|
118
|
-
|
|
119
|
+
it('handles [Relative Legacy URL, RequestOptions with path set, callback] input', () => {
|
|
119
120
|
const [url, options, callback] = normalizeClientRequestArgs(
|
|
120
121
|
'http:',
|
|
121
122
|
parse('/resource?apple=banana'),
|
|
@@ -137,7 +138,7 @@ test('handles [Relative Legacy URL, RequestOptions with path set, callback] inpu
|
|
|
137
138
|
expect(callback?.name).toEqual('cb')
|
|
138
139
|
})
|
|
139
140
|
|
|
140
|
-
|
|
141
|
+
it('handles [Relative Legacy URL, callback] input', () => {
|
|
141
142
|
const [url, options, callback] = normalizeClientRequestArgs(
|
|
142
143
|
'http:',
|
|
143
144
|
parse('/resource?apple=banana'),
|
|
@@ -157,7 +158,7 @@ test('handles [Relative Legacy URL, callback] input', () => {
|
|
|
157
158
|
expect(callback?.name).toEqual('cb')
|
|
158
159
|
})
|
|
159
160
|
|
|
160
|
-
|
|
161
|
+
it('handles [Relative Legacy URL] input', () => {
|
|
161
162
|
const [url, options, callback] = normalizeClientRequestArgs(
|
|
162
163
|
'http:',
|
|
163
164
|
parse('/resource?apple=banana')
|
|
@@ -176,7 +177,7 @@ test('handles [Relative Legacy URL] input', () => {
|
|
|
176
177
|
expect(callback).toBeUndefined()
|
|
177
178
|
})
|
|
178
179
|
|
|
179
|
-
|
|
180
|
+
it('handles [URL, RequestOptions, callback] input', () => {
|
|
180
181
|
const [url, options, callback] = normalizeClientRequestArgs(
|
|
181
182
|
'https:',
|
|
182
183
|
new URL('https://mswjs.io/resource'),
|
|
@@ -211,7 +212,7 @@ test('handles [URL, RequestOptions, callback] input', () => {
|
|
|
211
212
|
expect(callback?.name).toEqual('cb')
|
|
212
213
|
})
|
|
213
214
|
|
|
214
|
-
|
|
215
|
+
it('handles [RequestOptions, callback] input', () => {
|
|
215
216
|
const initialOptions = {
|
|
216
217
|
method: 'POST',
|
|
217
218
|
protocol: 'https:',
|
|
@@ -241,7 +242,7 @@ test('handles [RequestOptions, callback] input', () => {
|
|
|
241
242
|
expect(callback?.name).toEqual('cb')
|
|
242
243
|
})
|
|
243
244
|
|
|
244
|
-
|
|
245
|
+
it('handles [Empty RequestOptions, callback] input', () => {
|
|
245
246
|
const [_, options, callback] = normalizeClientRequestArgs(
|
|
246
247
|
'https:',
|
|
247
248
|
{},
|
|
@@ -257,7 +258,7 @@ test('handles [Empty RequestOptions, callback] input', () => {
|
|
|
257
258
|
/**
|
|
258
259
|
* @see https://github.com/mswjs/interceptors/issues/19
|
|
259
260
|
*/
|
|
260
|
-
|
|
261
|
+
it('handles [PartialRequestOptions, callback] input', () => {
|
|
261
262
|
const initialOptions = {
|
|
262
263
|
method: 'GET',
|
|
263
264
|
port: '50176',
|
|
@@ -291,7 +292,7 @@ test('handles [PartialRequestOptions, callback] input', () => {
|
|
|
291
292
|
expect(callback?.name).toEqual('cb')
|
|
292
293
|
})
|
|
293
294
|
|
|
294
|
-
|
|
295
|
+
it('sets fallback Agent based on the URL protocol', () => {
|
|
295
296
|
const [url, options] = normalizeClientRequestArgs(
|
|
296
297
|
'https:',
|
|
297
298
|
'https://github.com'
|
|
@@ -303,7 +304,7 @@ test('sets fallback Agent based on the URL protocol', () => {
|
|
|
303
304
|
expect(agent).toHaveProperty('protocol', url.protocol)
|
|
304
305
|
})
|
|
305
306
|
|
|
306
|
-
|
|
307
|
+
it('does not set any fallback Agent given "agent: false" option', () => {
|
|
307
308
|
const [, options] = normalizeClientRequestArgs(
|
|
308
309
|
'https:',
|
|
309
310
|
'https://github.com',
|
|
@@ -313,7 +314,7 @@ test('does not set any fallback Agent given "agent: false" option', () => {
|
|
|
313
314
|
expect(options.agent).toEqual(false)
|
|
314
315
|
})
|
|
315
316
|
|
|
316
|
-
|
|
317
|
+
it('sets the default Agent for HTTP request', () => {
|
|
317
318
|
const [, options] = normalizeClientRequestArgs(
|
|
318
319
|
'http:',
|
|
319
320
|
'http://github.com',
|
|
@@ -323,7 +324,7 @@ test('sets the default Agent for HTTP request', () => {
|
|
|
323
324
|
expect(options._defaultAgent).toEqual(httpGlobalAgent)
|
|
324
325
|
})
|
|
325
326
|
|
|
326
|
-
|
|
327
|
+
it('sets the default Agent for HTTPS request', () => {
|
|
327
328
|
const [, options] = normalizeClientRequestArgs(
|
|
328
329
|
'https:',
|
|
329
330
|
'https://github.com',
|
|
@@ -333,7 +334,7 @@ test('sets the default Agent for HTTPS request', () => {
|
|
|
333
334
|
expect(options._defaultAgent).toEqual(httpsGlobalAgent)
|
|
334
335
|
})
|
|
335
336
|
|
|
336
|
-
|
|
337
|
+
it('preserves a custom default Agent when set', () => {
|
|
337
338
|
const [, options] = normalizeClientRequestArgs(
|
|
338
339
|
'https:',
|
|
339
340
|
'https://github.com',
|
|
@@ -348,7 +349,7 @@ test('preserves a custom default Agent when set', () => {
|
|
|
348
349
|
expect(options._defaultAgent).toEqual(httpGlobalAgent)
|
|
349
350
|
})
|
|
350
351
|
|
|
351
|
-
|
|
352
|
+
it('merges URL-based RequestOptions with the custom RequestOptions', () => {
|
|
352
353
|
const [url, options] = normalizeClientRequestArgs(
|
|
353
354
|
'https:',
|
|
354
355
|
'https://github.com/graphql',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
1
2
|
import { normalizeClientRequestEndArgs } from './normalizeClientRequestEndArgs'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
it('returns [null, null, cb] given only the callback', () => {
|
|
4
5
|
const callback = () => {}
|
|
5
6
|
expect(normalizeClientRequestEndArgs(callback)).toEqual([
|
|
6
7
|
null,
|
|
@@ -9,11 +10,11 @@ test('returns [null, null, cb] given only the callback', () => {
|
|
|
9
10
|
])
|
|
10
11
|
})
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
it('returns [chunk, null, null] given only the chunk', () => {
|
|
13
14
|
expect(normalizeClientRequestEndArgs('chunk')).toEqual(['chunk', null, null])
|
|
14
15
|
})
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
it('returns [chunk, cb] given the chunk and the callback', () => {
|
|
17
18
|
const callback = () => {}
|
|
18
19
|
expect(normalizeClientRequestEndArgs('chunk', callback)).toEqual([
|
|
19
20
|
'chunk',
|
|
@@ -22,7 +23,7 @@ test('returns [chunk, cb] given the chunk and the callback', () => {
|
|
|
22
23
|
])
|
|
23
24
|
})
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
it('returns [chunk, encoding] given the chunk with the encoding', () => {
|
|
26
27
|
expect(normalizeClientRequestEndArgs('chunk', 'utf8')).toEqual([
|
|
27
28
|
'chunk',
|
|
28
29
|
'utf8',
|
|
@@ -30,7 +31,7 @@ test('returns [chunk, encoding] given the chunk with the encoding', () => {
|
|
|
30
31
|
])
|
|
31
32
|
})
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
it('returns [chunk, encoding, cb] given all three arguments', () => {
|
|
34
35
|
const callback = () => {}
|
|
35
36
|
expect(normalizeClientRequestEndArgs('chunk', 'utf8', callback)).toEqual([
|
|
36
37
|
'chunk',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
1
2
|
import { normalizeClientRequestWriteArgs } from './normalizeClientRequestWriteArgs'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
it('returns a triplet of null given no chunk, encoding, or callback', () => {
|
|
4
5
|
expect(
|
|
5
6
|
normalizeClientRequestWriteArgs([
|
|
6
7
|
// @ts-ignore
|
|
@@ -11,7 +12,7 @@ test('returns a triplet of null given no chunk, encoding, or callback', () => {
|
|
|
11
12
|
).toEqual([undefined, undefined, undefined])
|
|
12
13
|
})
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
it('returns [chunk, null, null] given only a chunk', () => {
|
|
15
16
|
expect(normalizeClientRequestWriteArgs(['chunk', undefined])).toEqual([
|
|
16
17
|
'chunk',
|
|
17
18
|
undefined,
|
|
@@ -19,7 +20,7 @@ test('returns [chunk, null, null] given only a chunk', () => {
|
|
|
19
20
|
])
|
|
20
21
|
})
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
it('returns [chunk, encoding] given only chunk and encoding', () => {
|
|
23
24
|
expect(normalizeClientRequestWriteArgs(['chunk', 'utf8'])).toEqual([
|
|
24
25
|
'chunk',
|
|
25
26
|
'utf8',
|
|
@@ -27,7 +28,7 @@ test('returns [chunk, encoding] given only chunk and encoding', () => {
|
|
|
27
28
|
])
|
|
28
29
|
})
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
it('returns [chunk, encoding, cb] given all three arguments', () => {
|
|
31
32
|
const callbackFn = () => {}
|
|
32
33
|
expect(
|
|
33
34
|
normalizeClientRequestWriteArgs(['chunk', 'utf8', callbackFn])
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*/
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { it, expect } from 'vitest'
|
|
4
3
|
import { createEvent } from './createEvent'
|
|
5
4
|
import { EventPolyfill } from '../polyfills/EventPolyfill'
|
|
6
5
|
|
|
7
6
|
const request = new XMLHttpRequest()
|
|
8
7
|
request.open('POST', '/user')
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
it('returns an EventPolyfill instance with the given target set', () => {
|
|
11
10
|
const event = createEvent(request, 'my-event')
|
|
12
11
|
const target = event.target as XMLHttpRequest
|
|
13
12
|
|
|
@@ -15,7 +14,7 @@ test('returns an EventPolyfill instance with the given target set', () => {
|
|
|
15
14
|
expect(target).toBeInstanceOf(XMLHttpRequest)
|
|
16
15
|
})
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
it('returns the ProgressEvent instance', () => {
|
|
19
18
|
const event = createEvent(request, 'load', {
|
|
20
19
|
loaded: 100,
|
|
21
20
|
total: 500,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { invariant } from 'outvariant'
|
|
2
|
-
import type { Response as ResponsePolyfill } from '@remix-run/web-fetch'
|
|
3
2
|
import { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'
|
|
4
3
|
import { Interceptor } from '../../Interceptor'
|
|
5
4
|
import { uuidv4 } from '../../utils/uuid'
|
|
@@ -81,7 +80,7 @@ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
|
|
|
81
80
|
this.log('no mocked response received!')
|
|
82
81
|
|
|
83
82
|
return pureFetch(request).then((response) => {
|
|
84
|
-
const responseClone = response.clone()
|
|
83
|
+
const responseClone = response.clone()
|
|
85
84
|
this.log('original fetch performed', responseClone)
|
|
86
85
|
|
|
87
86
|
this.emitter.emit(
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { vi, it, expect, afterEach } from 'vitest'
|
|
1
2
|
import { AsyncEventEmitter } from './AsyncEventEmitter'
|
|
2
3
|
import { sleep } from '../../test/helpers'
|
|
3
4
|
|
|
4
5
|
afterEach(() => {
|
|
5
|
-
|
|
6
|
+
vi.useRealTimers()
|
|
6
7
|
})
|
|
7
8
|
|
|
8
9
|
it('emits and listens to events', () => {
|
|
9
10
|
const emitter = new AsyncEventEmitter<{ hello: [string] }>()
|
|
10
|
-
const listener =
|
|
11
|
+
const listener = vi.fn()
|
|
11
12
|
emitter.on('hello', listener)
|
|
12
13
|
emitter.emit('hello', 'John')
|
|
13
14
|
|
|
@@ -19,10 +20,10 @@ it('resolves "untilIdle" when all the event listeners are done', async () => {
|
|
|
19
20
|
const emitter = new AsyncEventEmitter<{ speak: [string] }>()
|
|
20
21
|
|
|
21
22
|
const results: string[] = []
|
|
22
|
-
const firstListener =
|
|
23
|
+
const firstListener = vi.fn(() => results.push('first'))
|
|
23
24
|
emitter.on('speak', firstListener)
|
|
24
25
|
|
|
25
|
-
const secondListener =
|
|
26
|
+
const secondListener = vi.fn(async () => {
|
|
26
27
|
await sleep(150)
|
|
27
28
|
results.push('second')
|
|
28
29
|
})
|
|
@@ -43,7 +44,7 @@ it('resolves "untilIdle" only for the relevant listeners', async () => {
|
|
|
43
44
|
const emitter = new AsyncEventEmitter<{ signal: [number] }>()
|
|
44
45
|
|
|
45
46
|
const results: number[] = []
|
|
46
|
-
const listener =
|
|
47
|
+
const listener = vi.fn(async (code: number) => {
|
|
47
48
|
if (code !== 1) {
|
|
48
49
|
// Delay listener based on the signal code.
|
|
49
50
|
await sleep(150)
|
|
@@ -79,7 +80,7 @@ it('propagates listener exceptions to "untilIdle" promise', async () => {
|
|
|
79
80
|
const emitter = new AsyncEventEmitter<{ ping: never }>()
|
|
80
81
|
|
|
81
82
|
const error = new Error('oops')
|
|
82
|
-
const listener =
|
|
83
|
+
const listener = vi.fn(() => {
|
|
83
84
|
throw error
|
|
84
85
|
})
|
|
85
86
|
emitter.on('ping', listener)
|
|
@@ -91,7 +92,7 @@ it('propagates listener exceptions to "untilIdle" promise', async () => {
|
|
|
91
92
|
it('does not emit events once the emitter was deactivated', () => {
|
|
92
93
|
const emitter = new AsyncEventEmitter<{ ping: never }>()
|
|
93
94
|
|
|
94
|
-
const listener =
|
|
95
|
+
const listener = vi.fn()
|
|
95
96
|
emitter.on('ping', listener)
|
|
96
97
|
emitter.deactivate()
|
|
97
98
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
1
2
|
import { cloneObject } from './cloneObject'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
it('clones a shallow object', () => {
|
|
4
5
|
const original = { a: 1, b: 2, c: [1, 2, 3] }
|
|
5
6
|
const clone = cloneObject(original)
|
|
6
7
|
|
|
@@ -18,7 +19,7 @@ test('clones a shallow object', () => {
|
|
|
18
19
|
expect(original).toHaveProperty('c', [1, 2, 3])
|
|
19
20
|
})
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
it('clones a nested object', () => {
|
|
22
23
|
const original = { a: { b: 1 }, c: { d: { e: 2 } } }
|
|
23
24
|
const clone = cloneObject(original)
|
|
24
25
|
|
|
@@ -33,7 +34,7 @@ test('clones a nested object', () => {
|
|
|
33
34
|
expect(original).toHaveProperty(['c', 'd', 'e'], 2)
|
|
34
35
|
})
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
it('clones a class instance', () => {
|
|
37
38
|
class Car {
|
|
38
39
|
public manufacturer: string
|
|
39
40
|
constructor() {
|
|
@@ -53,7 +54,7 @@ test('clones a class instance', () => {
|
|
|
53
54
|
expect(clone.getManufacturer()).toEqual('Audi')
|
|
54
55
|
})
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
it('ignores nested class instances', () => {
|
|
57
58
|
class Car {
|
|
58
59
|
name: string
|
|
59
60
|
constructor(name: string) {
|
|
@@ -81,7 +82,7 @@ test('ignores nested class instances', () => {
|
|
|
81
82
|
expect(original.car.getName()).toEqual('Audi')
|
|
82
83
|
})
|
|
83
84
|
|
|
84
|
-
|
|
85
|
+
it('clones an object with null prototype', () => {
|
|
85
86
|
const original = {
|
|
86
87
|
key: Object.create(null),
|
|
87
88
|
}
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
1
2
|
import { getCleanUrl } from './getCleanUrl'
|
|
2
3
|
|
|
3
4
|
describe('getCleanUrl', () => {
|
|
4
5
|
describe('given a URL without query parameters', () => {
|
|
5
|
-
|
|
6
|
+
it('should return url href as-is', () => {
|
|
6
7
|
const url = new URL('https://github.com')
|
|
7
8
|
expect(getCleanUrl(url)).toEqual('https://github.com/')
|
|
8
9
|
})
|
|
9
10
|
})
|
|
10
11
|
|
|
11
12
|
describe('given a URL with query parameters', () => {
|
|
12
|
-
|
|
13
|
+
it('should return url without parameters', () => {
|
|
13
14
|
const url = new URL('https://github.com/mswjs/?userId=abc-123')
|
|
14
15
|
expect(getCleanUrl(url)).toEqual('https://github.com/mswjs/')
|
|
15
16
|
})
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
describe('given a URL with a hash', () => {
|
|
19
|
-
|
|
20
|
+
it('should return a url without hash', () => {
|
|
20
21
|
const url = new URL('https://github.com/mswjs/#hello-world')
|
|
21
22
|
expect(getCleanUrl(url)).toEqual('https://github.com/mswjs/')
|
|
22
23
|
})
|
|
23
24
|
})
|
|
24
25
|
|
|
25
26
|
describe('given an absolute URL ', () => {
|
|
26
|
-
|
|
27
|
+
it('should return a clean relative URL', () => {
|
|
27
28
|
const url = new URL('/login?query=value', 'https://github.com')
|
|
28
29
|
expect(getCleanUrl(url, false)).toEqual('/login')
|
|
29
30
|
})
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
1
2
|
import { Agent as HttpAgent } from 'http'
|
|
2
3
|
import { RequestOptions, Agent as HttpsAgent } from 'https'
|
|
3
4
|
import { getUrlByRequestOptions } from './getUrlByRequestOptions'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
it('returns a URL based on the basic RequestOptions', () => {
|
|
6
7
|
const options: RequestOptions = {
|
|
7
8
|
protocol: 'https:',
|
|
8
9
|
host: '127.0.0.1',
|
|
@@ -15,7 +16,7 @@ test('returns a URL based on the basic RequestOptions', () => {
|
|
|
15
16
|
expect(url).toHaveProperty('href', 'https://127.0.0.1/resource')
|
|
16
17
|
})
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
it('inherits protocol and port from http.Agent, if set', () => {
|
|
19
20
|
const options: RequestOptions = {
|
|
20
21
|
host: '127.0.0.1',
|
|
21
22
|
path: '/',
|
|
@@ -29,7 +30,7 @@ test('inherits protocol and port from http.Agent, if set', () => {
|
|
|
29
30
|
expect(url).toHaveProperty('href', 'http://127.0.0.1/')
|
|
30
31
|
})
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
it('inherits protocol and port from https.Agent, if set', () => {
|
|
33
34
|
const options: RequestOptions = {
|
|
34
35
|
host: '127.0.0.1',
|
|
35
36
|
path: '/',
|
|
@@ -45,7 +46,7 @@ test('inherits protocol and port from https.Agent, if set', () => {
|
|
|
45
46
|
expect(url).toHaveProperty('href', 'https://127.0.0.1:3080/')
|
|
46
47
|
})
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
it('resolves protocol to "http" given no explicit protocol and no certificate', () => {
|
|
49
50
|
const options: RequestOptions = {
|
|
50
51
|
host: '127.0.0.1',
|
|
51
52
|
path: '/',
|
|
@@ -58,7 +59,7 @@ test('resolves protocol to "http" given no explicit protocol and no certificate'
|
|
|
58
59
|
expect(url).toHaveProperty('href', 'http://127.0.0.1/')
|
|
59
60
|
})
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
it('resolves protocol to "https" given no explicit protocol, but certificate', () => {
|
|
62
63
|
const options: RequestOptions = {
|
|
63
64
|
host: '127.0.0.1',
|
|
64
65
|
path: '/secure',
|
|
@@ -72,7 +73,7 @@ test('resolves protocol to "https" given no explicit protocol, but certificate',
|
|
|
72
73
|
expect(url).toHaveProperty('href', 'https://127.0.0.1/secure')
|
|
73
74
|
})
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
it('resolves protocol to "https" given no explicit protocol, but port is 443', () => {
|
|
76
77
|
const options: RequestOptions = {
|
|
77
78
|
host: '127.0.0.1',
|
|
78
79
|
port: 443,
|
|
@@ -85,7 +86,7 @@ test('resolves protocol to "https" given no explicit protocol, but port is 443',
|
|
|
85
86
|
expect(url).toHaveProperty('href', 'https://127.0.0.1/resource')
|
|
86
87
|
})
|
|
87
88
|
|
|
88
|
-
|
|
89
|
+
it('resolves protocol to "https" given no explicit protocol, but agent port is 443', () => {
|
|
89
90
|
const options: RequestOptions = {
|
|
90
91
|
host: '127.0.0.1',
|
|
91
92
|
agent: new HttpsAgent({
|
|
@@ -100,7 +101,7 @@ test('resolves protocol to "https" given no explicit protocol, but agent port is
|
|
|
100
101
|
expect(url).toHaveProperty('href', 'https://127.0.0.1/resource')
|
|
101
102
|
})
|
|
102
103
|
|
|
103
|
-
|
|
104
|
+
it('inherits "port" if given', () => {
|
|
104
105
|
const options = {
|
|
105
106
|
protocol: 'http:',
|
|
106
107
|
host: '127.0.0.1',
|
|
@@ -115,7 +116,7 @@ test('inherits "port" if given', () => {
|
|
|
115
116
|
expect(url).toHaveProperty('href', 'http://127.0.0.1:4002/')
|
|
116
117
|
})
|
|
117
118
|
|
|
118
|
-
|
|
119
|
+
it('inherits "username" and "password"', () => {
|
|
119
120
|
const options: RequestOptions = {
|
|
120
121
|
protocol: 'https:',
|
|
121
122
|
host: '127.0.0.1',
|
|
@@ -131,7 +132,7 @@ test('inherits "username" and "password"', () => {
|
|
|
131
132
|
expect(url).toHaveProperty('href', 'https://admin:abc-123@127.0.0.1/user')
|
|
132
133
|
})
|
|
133
134
|
|
|
134
|
-
|
|
135
|
+
it('resolves hostname to localhost if none provided', () => {
|
|
135
136
|
const url = getUrlByRequestOptions({})
|
|
136
137
|
|
|
137
138
|
expect(url).toBeInstanceOf(URL)
|
|
@@ -68,6 +68,15 @@ function getAuthByRequestOptions(options: ResolvedRequestOptions) {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Returns true if host looks like an IPv6 address without surrounding brackets
|
|
73
|
+
* It assumes any host containing `:` is definitely not IPv4 and probably IPv6,
|
|
74
|
+
* but note that this could include invalid IPv6 addresses as well.
|
|
75
|
+
*/
|
|
76
|
+
function isRawIPv6Address(host: string): boolean {
|
|
77
|
+
return host.includes(':') && !host.startsWith('[') && !host.endsWith(']')
|
|
78
|
+
}
|
|
79
|
+
|
|
71
80
|
/**
|
|
72
81
|
* Creates a `URL` instance from a given `RequestOptions` object.
|
|
73
82
|
*/
|
|
@@ -85,7 +94,11 @@ export function getUrlByRequestOptions(options: ResolvedRequestOptions): URL {
|
|
|
85
94
|
debug('port', port)
|
|
86
95
|
debug('path', path)
|
|
87
96
|
|
|
88
|
-
|
|
97
|
+
/**
|
|
98
|
+
* @note As of Node >= 17, hosts (including "localhost") can resolve to IPv6
|
|
99
|
+
* addresses, so construct valid URL by surrounding the IPv6 host with brackets.
|
|
100
|
+
*/
|
|
101
|
+
const baseUrl = `${protocol}//${isRawIPv6Address(host) ? `[${host}]` : host}`
|
|
89
102
|
debug('base URL:', baseUrl)
|
|
90
103
|
|
|
91
104
|
const url = options.uri ? new URL(options.uri.href) : new URL(path, baseUrl)
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
1
2
|
import { isObject } from './isObject'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
it('resolves given an object', () => {
|
|
4
5
|
expect(isObject({})).toBe(true)
|
|
5
6
|
expect(isObject({ a: 1 })).toBe(true)
|
|
6
7
|
})
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
it('rejects given an object-like instance', () => {
|
|
9
10
|
expect(isObject([1])).toBe(false)
|
|
10
11
|
expect(isObject(function () {})).toBe(false)
|
|
11
12
|
})
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
it('rejects given a non-object instance', () => {
|
|
14
15
|
expect(isObject(null)).toBe(false)
|
|
15
16
|
expect(isObject(undefined)).toBe(false)
|
|
16
17
|
expect(isObject(false)).toBe(false)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
1
2
|
import { parseJson } from './parseJson'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
it('parses a given string into JSON', () => {
|
|
4
5
|
expect(parseJson('{"id":1}')).toEqual({ id: 1 })
|
|
5
6
|
})
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
it('returns null given invalid JSON string', () => {
|
|
8
9
|
expect(parseJson('{"o:2\'')).toBeNull()
|
|
9
10
|
})
|