@depup/mswjs__interceptors 0.41.3-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/ClientRequest/package.json +11 -0
- package/LICENSE.md +9 -0
- package/README.md +31 -0
- package/RemoteHttpInterceptor/package.json +11 -0
- package/WebSocket/package.json +12 -0
- package/XMLHttpRequest/package.json +12 -0
- package/changes.json +10 -0
- package/fetch/package.json +12 -0
- package/lib/browser/Interceptor-Deczogc8.d.cts +65 -0
- package/lib/browser/Interceptor-gqKgs-aF.d.mts +65 -0
- package/lib/browser/XMLHttpRequest-BACqefB-.cjs +761 -0
- package/lib/browser/XMLHttpRequest-BACqefB-.cjs.map +1 -0
- package/lib/browser/XMLHttpRequest-BvxZV0WU.mjs +756 -0
- package/lib/browser/XMLHttpRequest-BvxZV0WU.mjs.map +1 -0
- package/lib/browser/bufferUtils-BiiO6HZv.mjs +20 -0
- package/lib/browser/bufferUtils-BiiO6HZv.mjs.map +1 -0
- package/lib/browser/bufferUtils-Uc0eRItL.cjs +38 -0
- package/lib/browser/bufferUtils-Uc0eRItL.cjs.map +1 -0
- package/lib/browser/createRequestId-Cs4oXfa1.cjs +205 -0
- package/lib/browser/createRequestId-Cs4oXfa1.cjs.map +1 -0
- package/lib/browser/createRequestId-DQcIlohW.mjs +170 -0
- package/lib/browser/createRequestId-DQcIlohW.mjs.map +1 -0
- package/lib/browser/fetch-DdKEdDOR.mjs +248 -0
- package/lib/browser/fetch-DdKEdDOR.mjs.map +1 -0
- package/lib/browser/fetch-U3v3Y4ap.cjs +253 -0
- package/lib/browser/fetch-U3v3Y4ap.cjs.map +1 -0
- package/lib/browser/getRawRequest-BTaNLFr0.mjs +218 -0
- package/lib/browser/getRawRequest-BTaNLFr0.mjs.map +1 -0
- package/lib/browser/getRawRequest-zx8rUJL2.cjs +259 -0
- package/lib/browser/getRawRequest-zx8rUJL2.cjs.map +1 -0
- package/lib/browser/glossary-BdLS4k1H.d.cts +70 -0
- package/lib/browser/glossary-DYwOrogs.d.mts +70 -0
- package/lib/browser/handleRequest-CvX2G-Lz.cjs +189 -0
- package/lib/browser/handleRequest-CvX2G-Lz.cjs.map +1 -0
- package/lib/browser/handleRequest-D7kpTI5U.mjs +178 -0
- package/lib/browser/handleRequest-D7kpTI5U.mjs.map +1 -0
- package/lib/browser/hasConfigurableGlobal-BvCTG97d.cjs +45 -0
- package/lib/browser/hasConfigurableGlobal-BvCTG97d.cjs.map +1 -0
- package/lib/browser/hasConfigurableGlobal-npXitu1-.mjs +33 -0
- package/lib/browser/hasConfigurableGlobal-npXitu1-.mjs.map +1 -0
- package/lib/browser/index.cjs +70 -0
- package/lib/browser/index.cjs.map +1 -0
- package/lib/browser/index.d.cts +96 -0
- package/lib/browser/index.d.mts +96 -0
- package/lib/browser/index.mjs +56 -0
- package/lib/browser/index.mjs.map +1 -0
- package/lib/browser/interceptors/WebSocket/index.cjs +622 -0
- package/lib/browser/interceptors/WebSocket/index.cjs.map +1 -0
- package/lib/browser/interceptors/WebSocket/index.d.cts +277 -0
- package/lib/browser/interceptors/WebSocket/index.d.mts +277 -0
- package/lib/browser/interceptors/WebSocket/index.mjs +615 -0
- package/lib/browser/interceptors/WebSocket/index.mjs.map +1 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.cjs +7 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.d.cts +15 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.d.mts +15 -0
- package/lib/browser/interceptors/XMLHttpRequest/index.mjs +7 -0
- package/lib/browser/interceptors/fetch/index.cjs +6 -0
- package/lib/browser/interceptors/fetch/index.d.cts +13 -0
- package/lib/browser/interceptors/fetch/index.d.mts +13 -0
- package/lib/browser/interceptors/fetch/index.mjs +6 -0
- package/lib/browser/presets/browser.cjs +17 -0
- package/lib/browser/presets/browser.cjs.map +1 -0
- package/lib/browser/presets/browser.d.cts +12 -0
- package/lib/browser/presets/browser.d.mts +14 -0
- package/lib/browser/presets/browser.mjs +17 -0
- package/lib/browser/presets/browser.mjs.map +1 -0
- package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs +31 -0
- package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs.map +1 -0
- package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs +25 -0
- package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs.map +1 -0
- package/lib/node/BatchInterceptor-3LnAnLTx.cjs +49 -0
- package/lib/node/BatchInterceptor-3LnAnLTx.cjs.map +1 -0
- package/lib/node/BatchInterceptor-D7mXzHcQ.d.mts +26 -0
- package/lib/node/BatchInterceptor-DFaBPilf.mjs +44 -0
- package/lib/node/BatchInterceptor-DFaBPilf.mjs.map +1 -0
- package/lib/node/BatchInterceptor-D_YqR8qU.d.cts +26 -0
- package/lib/node/ClientRequest-2rDe54Ui.cjs +1043 -0
- package/lib/node/ClientRequest-2rDe54Ui.cjs.map +1 -0
- package/lib/node/ClientRequest-Ca8Qykuv.mjs +1034 -0
- package/lib/node/ClientRequest-Ca8Qykuv.mjs.map +1 -0
- package/lib/node/Interceptor-DEazpLJd.d.mts +133 -0
- package/lib/node/Interceptor-DJ2akVWI.d.cts +133 -0
- package/lib/node/RemoteHttpInterceptor.cjs +154 -0
- package/lib/node/RemoteHttpInterceptor.cjs.map +1 -0
- package/lib/node/RemoteHttpInterceptor.d.cts +39 -0
- package/lib/node/RemoteHttpInterceptor.d.mts +39 -0
- package/lib/node/RemoteHttpInterceptor.mjs +152 -0
- package/lib/node/RemoteHttpInterceptor.mjs.map +1 -0
- package/lib/node/XMLHttpRequest-B7kJdYYI.cjs +763 -0
- package/lib/node/XMLHttpRequest-B7kJdYYI.cjs.map +1 -0
- package/lib/node/XMLHttpRequest-C8dIZpds.mjs +757 -0
- package/lib/node/XMLHttpRequest-C8dIZpds.mjs.map +1 -0
- package/lib/node/bufferUtils-DiCTqG-7.cjs +38 -0
- package/lib/node/bufferUtils-DiCTqG-7.cjs.map +1 -0
- package/lib/node/bufferUtils-_8XfKIfX.mjs +20 -0
- package/lib/node/bufferUtils-_8XfKIfX.mjs.map +1 -0
- package/lib/node/chunk-CbDLau6x.cjs +34 -0
- package/lib/node/fetch-BmXpK10r.cjs +272 -0
- package/lib/node/fetch-BmXpK10r.cjs.map +1 -0
- package/lib/node/fetch-G1DVwDKG.mjs +265 -0
- package/lib/node/fetch-G1DVwDKG.mjs.map +1 -0
- package/lib/node/fetchUtils-BaY5iWXw.cjs +419 -0
- package/lib/node/fetchUtils-BaY5iWXw.cjs.map +1 -0
- package/lib/node/fetchUtils-CoU35g3M.mjs +359 -0
- package/lib/node/fetchUtils-CoU35g3M.mjs.map +1 -0
- package/lib/node/getRawRequest-BavnMWh_.cjs +36 -0
- package/lib/node/getRawRequest-BavnMWh_.cjs.map +1 -0
- package/lib/node/getRawRequest-DnwmXyOW.mjs +24 -0
- package/lib/node/getRawRequest-DnwmXyOW.mjs.map +1 -0
- package/lib/node/glossary-BLKRyLBd.cjs +12 -0
- package/lib/node/glossary-BLKRyLBd.cjs.map +1 -0
- package/lib/node/glossary-glQBRnVD.mjs +6 -0
- package/lib/node/glossary-glQBRnVD.mjs.map +1 -0
- package/lib/node/handleRequest-Bb7Y-XLw.cjs +220 -0
- package/lib/node/handleRequest-Bb7Y-XLw.cjs.map +1 -0
- package/lib/node/handleRequest-Y97UwBbF.mjs +190 -0
- package/lib/node/handleRequest-Y97UwBbF.mjs.map +1 -0
- package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs +26 -0
- package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs.map +1 -0
- package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs +20 -0
- package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs.map +1 -0
- package/lib/node/index-BMbJ8FXL.d.cts +113 -0
- package/lib/node/index-C0YAQ36w.d.mts +113 -0
- package/lib/node/index.cjs +54 -0
- package/lib/node/index.cjs.map +1 -0
- package/lib/node/index.d.cts +75 -0
- package/lib/node/index.d.mts +75 -0
- package/lib/node/index.mjs +40 -0
- package/lib/node/index.mjs.map +1 -0
- package/lib/node/interceptors/ClientRequest/index.cjs +6 -0
- package/lib/node/interceptors/ClientRequest/index.d.cts +2 -0
- package/lib/node/interceptors/ClientRequest/index.d.mts +3 -0
- package/lib/node/interceptors/ClientRequest/index.mjs +6 -0
- package/lib/node/interceptors/XMLHttpRequest/index.cjs +6 -0
- package/lib/node/interceptors/XMLHttpRequest/index.d.cts +14 -0
- package/lib/node/interceptors/XMLHttpRequest/index.d.mts +14 -0
- package/lib/node/interceptors/XMLHttpRequest/index.mjs +6 -0
- package/lib/node/interceptors/fetch/index.cjs +5 -0
- package/lib/node/interceptors/fetch/index.d.cts +12 -0
- package/lib/node/interceptors/fetch/index.d.mts +12 -0
- package/lib/node/interceptors/fetch/index.mjs +5 -0
- package/lib/node/node-DwCc6iuP.mjs +27 -0
- package/lib/node/node-DwCc6iuP.mjs.map +1 -0
- package/lib/node/node-dKdAf3tC.cjs +39 -0
- package/lib/node/node-dKdAf3tC.cjs.map +1 -0
- package/lib/node/presets/node.cjs +22 -0
- package/lib/node/presets/node.cjs.map +1 -0
- package/lib/node/presets/node.d.cts +13 -0
- package/lib/node/presets/node.d.mts +15 -0
- package/lib/node/presets/node.mjs +22 -0
- package/lib/node/presets/node.mjs.map +1 -0
- package/lib/node/utils/node/index.cjs +4 -0
- package/lib/node/utils/node/index.d.cts +16 -0
- package/lib/node/utils/node/index.d.mts +16 -0
- package/lib/node/utils/node/index.mjs +3 -0
- package/package.json +204 -0
- package/presets/browser/package.json +5 -0
- package/presets/node/package.json +11 -0
- package/src/BatchInterceptor.test.ts +255 -0
- package/src/BatchInterceptor.ts +95 -0
- package/src/Interceptor.test.ts +205 -0
- package/src/Interceptor.ts +249 -0
- package/src/InterceptorError.ts +7 -0
- package/src/RemoteHttpInterceptor.ts +251 -0
- package/src/RequestController.test.ts +104 -0
- package/src/RequestController.ts +109 -0
- package/src/createRequestId.test.ts +7 -0
- package/src/createRequestId.ts +9 -0
- package/src/getRawRequest.ts +21 -0
- package/src/glossary.ts +37 -0
- package/src/index.ts +15 -0
- package/src/interceptors/ClientRequest/MockHttpSocket.ts +724 -0
- package/src/interceptors/ClientRequest/agents.ts +110 -0
- package/src/interceptors/ClientRequest/index.test.ts +75 -0
- package/src/interceptors/ClientRequest/index.ts +193 -0
- package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +54 -0
- package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +45 -0
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +427 -0
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +268 -0
- package/src/interceptors/ClientRequest/utils/parserUtils.ts +48 -0
- package/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts +258 -0
- package/src/interceptors/ClientRequest/utils/recordRawHeaders.ts +262 -0
- package/src/interceptors/Socket/MockSocket.test.ts +264 -0
- package/src/interceptors/Socket/MockSocket.ts +58 -0
- package/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +26 -0
- package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts +52 -0
- package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +33 -0
- package/src/interceptors/WebSocket/WebSocketClassTransport.ts +116 -0
- package/src/interceptors/WebSocket/WebSocketClientConnection.ts +152 -0
- package/src/interceptors/WebSocket/WebSocketOverride.ts +252 -0
- package/src/interceptors/WebSocket/WebSocketServerConnection.ts +420 -0
- package/src/interceptors/WebSocket/WebSocketTransport.ts +39 -0
- package/src/interceptors/WebSocket/index.ts +191 -0
- package/src/interceptors/WebSocket/utils/bindEvent.test.ts +27 -0
- package/src/interceptors/WebSocket/utils/bindEvent.ts +21 -0
- package/src/interceptors/WebSocket/utils/events.test.ts +101 -0
- package/src/interceptors/WebSocket/utils/events.ts +94 -0
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +746 -0
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +121 -0
- package/src/interceptors/XMLHttpRequest/index.ts +61 -0
- package/src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts +51 -0
- package/src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts +17 -0
- package/src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts +12 -0
- package/src/interceptors/XMLHttpRequest/utils/concateArrayBuffer.test.ts +12 -0
- package/src/interceptors/XMLHttpRequest/utils/createEvent.test.ts +26 -0
- package/src/interceptors/XMLHttpRequest/utils/createEvent.ts +41 -0
- package/src/interceptors/XMLHttpRequest/utils/createResponse.ts +49 -0
- package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.test.ts +164 -0
- package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts +16 -0
- package/src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts +14 -0
- package/src/interceptors/fetch/index.ts +214 -0
- package/src/interceptors/fetch/utils/brotli-decompress.browser.ts +14 -0
- package/src/interceptors/fetch/utils/brotli-decompress.ts +31 -0
- package/src/interceptors/fetch/utils/createNetworkError.ts +5 -0
- package/src/interceptors/fetch/utils/decompression.ts +85 -0
- package/src/interceptors/fetch/utils/followRedirect.ts +114 -0
- package/src/presets/browser.ts +11 -0
- package/src/presets/node.ts +13 -0
- package/src/utils/bufferUtils.test.ts +21 -0
- package/src/utils/bufferUtils.ts +22 -0
- package/src/utils/canParseUrl.ts +13 -0
- package/src/utils/cloneObject.test.ts +94 -0
- package/src/utils/cloneObject.ts +36 -0
- package/src/utils/createProxy.test.ts +164 -0
- package/src/utils/createProxy.ts +104 -0
- package/src/utils/emitAsync.ts +25 -0
- package/src/utils/fetchUtils.ts +119 -0
- package/src/utils/findPropertySource.test.ts +27 -0
- package/src/utils/findPropertySource.ts +20 -0
- package/src/utils/getCleanUrl.test.ts +32 -0
- package/src/utils/getCleanUrl.ts +6 -0
- package/src/utils/getUrlByRequestOptions.test.ts +163 -0
- package/src/utils/getUrlByRequestOptions.ts +152 -0
- package/src/utils/getValueBySymbol.test.ts +14 -0
- package/src/utils/getValueBySymbol.ts +19 -0
- package/src/utils/handleRequest.ts +205 -0
- package/src/utils/hasConfigurableGlobal.test.ts +83 -0
- package/src/utils/hasConfigurableGlobal.ts +34 -0
- package/src/utils/isNodeLikeError.ts +13 -0
- package/src/utils/isObject.test.ts +21 -0
- package/src/utils/isObject.ts +8 -0
- package/src/utils/isPropertyAccessible.ts +19 -0
- package/src/utils/nextTick.ts +11 -0
- package/src/utils/node/index.ts +39 -0
- package/src/utils/parseJson.test.ts +10 -0
- package/src/utils/parseJson.ts +12 -0
- package/src/utils/resolveWebSocketUrl.ts +45 -0
- package/src/utils/responseUtils.ts +59 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { vi, it, expect } from 'vitest'
|
|
2
|
+
import { createProxy } from './createProxy'
|
|
3
|
+
|
|
4
|
+
it('does not interfere with default constructors', () => {
|
|
5
|
+
const ProxyClass = createProxy(
|
|
6
|
+
class {
|
|
7
|
+
constructor(public name: string) {}
|
|
8
|
+
},
|
|
9
|
+
{}
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
const instance = new ProxyClass('John')
|
|
13
|
+
expect(instance.name).toBe('John')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('does not interfere with default getters', () => {
|
|
17
|
+
const proxy = createProxy({ foo: 'initial' }, {})
|
|
18
|
+
expect(proxy.foo).toBe('initial')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('does not interfere with default setters', () => {
|
|
22
|
+
const proxy = createProxy({ foo: 'initial' }, {})
|
|
23
|
+
proxy.foo = 'next'
|
|
24
|
+
|
|
25
|
+
expect(proxy.foo).toBe('next')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('does not interfere with default methods', () => {
|
|
29
|
+
const proxy = createProxy({ getValue: () => 'initial' }, {})
|
|
30
|
+
expect(proxy.getValue()).toBe('initial')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('does not interfere with existing descriptors', () => {
|
|
34
|
+
const target = {} as { foo: string; bar: number }
|
|
35
|
+
let internalBar = 0
|
|
36
|
+
|
|
37
|
+
Object.defineProperties(target, {
|
|
38
|
+
foo: {
|
|
39
|
+
get: () => 'initial',
|
|
40
|
+
},
|
|
41
|
+
bar: {
|
|
42
|
+
set: (value) => {
|
|
43
|
+
internalBar = value + 10
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const proxy = createProxy(target, {
|
|
49
|
+
getProperty(data, next) {
|
|
50
|
+
return next()
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
expect(proxy.foo).toBe('initial')
|
|
54
|
+
|
|
55
|
+
proxy.bar = 5
|
|
56
|
+
expect(proxy.bar).toBeUndefined()
|
|
57
|
+
expect(internalBar).toBe(15)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('infer prototype descriptors', () => {
|
|
61
|
+
class Child {
|
|
62
|
+
ok: boolean
|
|
63
|
+
|
|
64
|
+
set status(nextStatus: number) {
|
|
65
|
+
this.ok = nextStatus >= 200 && nextStatus < 300
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
Object.defineProperties(Child.prototype, {
|
|
70
|
+
status: { enumerable: true },
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const scope = {} as { child: typeof Child }
|
|
74
|
+
|
|
75
|
+
Object.defineProperty(scope, 'child', {
|
|
76
|
+
enumerable: true,
|
|
77
|
+
value: Child,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const ProxyClass = createProxy(scope.child, {})
|
|
81
|
+
const instance = new ProxyClass()
|
|
82
|
+
|
|
83
|
+
instance.status = 201
|
|
84
|
+
expect(instance.ok).toBe(true)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('spies on the constructor', () => {
|
|
88
|
+
const OriginalClass = class {
|
|
89
|
+
constructor(public name: string, public age: number) {}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const constructorCall = vi.fn<
|
|
93
|
+
(
|
|
94
|
+
args: ConstructorParameters<typeof OriginalClass>,
|
|
95
|
+
next: () => typeof OriginalClass
|
|
96
|
+
) => typeof OriginalClass
|
|
97
|
+
>((args, next) => next())
|
|
98
|
+
|
|
99
|
+
const ProxyClass = createProxy(OriginalClass, {
|
|
100
|
+
constructorCall,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
new ProxyClass('John', 32)
|
|
104
|
+
|
|
105
|
+
expect(constructorCall).toHaveBeenCalledTimes(1)
|
|
106
|
+
expect(constructorCall).toHaveBeenCalledWith(
|
|
107
|
+
['John', 32],
|
|
108
|
+
expect.any(Function)
|
|
109
|
+
)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('spies on property getters', () => {
|
|
113
|
+
const getProperty = vi.fn((args, next) => next())
|
|
114
|
+
const proxy = createProxy({ foo: 'initial' }, { getProperty })
|
|
115
|
+
|
|
116
|
+
proxy.foo
|
|
117
|
+
|
|
118
|
+
expect(getProperty).toHaveBeenCalledTimes(1)
|
|
119
|
+
expect(getProperty).toHaveBeenCalledWith(['foo', proxy], expect.any(Function))
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('spies on property setters', () => {
|
|
123
|
+
const setProperty = vi.fn((args, next) => next())
|
|
124
|
+
const proxy = createProxy({ foo: 'initial' }, { setProperty })
|
|
125
|
+
|
|
126
|
+
proxy.foo = 'next'
|
|
127
|
+
|
|
128
|
+
expect(setProperty).toHaveBeenCalledTimes(1)
|
|
129
|
+
expect(setProperty).toHaveBeenCalledWith(
|
|
130
|
+
['foo', 'next'],
|
|
131
|
+
expect.any(Function)
|
|
132
|
+
)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('spies on method calls', () => {
|
|
136
|
+
const methodCall = vi.fn((args, next) => next())
|
|
137
|
+
const proxy = createProxy(
|
|
138
|
+
{
|
|
139
|
+
greet: (name: string) => `hello ${name}`,
|
|
140
|
+
},
|
|
141
|
+
{ methodCall }
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
proxy.greet('Clair')
|
|
145
|
+
|
|
146
|
+
expect(methodCall).toHaveBeenCalledTimes(1)
|
|
147
|
+
expect(methodCall).toHaveBeenCalledWith(
|
|
148
|
+
['greet', ['Clair']],
|
|
149
|
+
expect.any(Function)
|
|
150
|
+
)
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('proxies properties on the prototype level', () => {
|
|
154
|
+
const method = vi.fn()
|
|
155
|
+
const prototype = { method }
|
|
156
|
+
|
|
157
|
+
const proxy = createProxy(Object.create(prototype), {})
|
|
158
|
+
const proxyMethod = vi.fn()
|
|
159
|
+
proxy.method = proxyMethod
|
|
160
|
+
|
|
161
|
+
prototype.method()
|
|
162
|
+
expect(method).toHaveBeenCalledTimes(0)
|
|
163
|
+
expect(proxyMethod).toHaveBeenCalledTimes(1)
|
|
164
|
+
})
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { findPropertySource } from './findPropertySource'
|
|
2
|
+
|
|
3
|
+
export interface ProxyOptions<Target extends Record<string, any>> {
|
|
4
|
+
constructorCall?(args: Array<unknown>, next: NextFunction<Target>): Target
|
|
5
|
+
|
|
6
|
+
methodCall?<F extends keyof Target>(
|
|
7
|
+
this: Target,
|
|
8
|
+
data: [methodName: F, args: Array<unknown>],
|
|
9
|
+
next: NextFunction<void>
|
|
10
|
+
): void
|
|
11
|
+
|
|
12
|
+
setProperty?(
|
|
13
|
+
data: [propertyName: string | symbol, nextValue: unknown],
|
|
14
|
+
next: NextFunction<boolean>
|
|
15
|
+
): boolean
|
|
16
|
+
|
|
17
|
+
getProperty?(
|
|
18
|
+
data: [propertyName: string | symbol, receiver: Target],
|
|
19
|
+
next: NextFunction<void>
|
|
20
|
+
): void
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type NextFunction<ReturnType> = () => ReturnType
|
|
24
|
+
|
|
25
|
+
export function createProxy<Target extends object>(
|
|
26
|
+
target: Target,
|
|
27
|
+
options: ProxyOptions<Target>
|
|
28
|
+
): Target {
|
|
29
|
+
const proxy = new Proxy(target, optionsToProxyHandler(options))
|
|
30
|
+
|
|
31
|
+
return proxy
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function optionsToProxyHandler<T extends Record<string, any>>(
|
|
35
|
+
options: ProxyOptions<T>
|
|
36
|
+
): ProxyHandler<T> {
|
|
37
|
+
const { constructorCall, methodCall, getProperty, setProperty } = options
|
|
38
|
+
const handler: ProxyHandler<T> = {}
|
|
39
|
+
|
|
40
|
+
if (typeof constructorCall !== 'undefined') {
|
|
41
|
+
handler.construct = function (target, args, newTarget) {
|
|
42
|
+
const next = Reflect.construct.bind(null, target as any, args, newTarget)
|
|
43
|
+
return constructorCall.call(newTarget, args, next)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
handler.set = function (target, propertyName, nextValue) {
|
|
48
|
+
const next = () => {
|
|
49
|
+
const propertySource = findPropertySource(target, propertyName) || target
|
|
50
|
+
const ownDescriptors = Reflect.getOwnPropertyDescriptor(
|
|
51
|
+
propertySource,
|
|
52
|
+
propertyName
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
// Respect any custom setters present for this property.
|
|
56
|
+
if (typeof ownDescriptors?.set !== 'undefined') {
|
|
57
|
+
ownDescriptors.set.apply(target, [nextValue])
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Otherwise, set the property on the source.
|
|
62
|
+
return Reflect.defineProperty(propertySource, propertyName, {
|
|
63
|
+
writable: true,
|
|
64
|
+
enumerable: true,
|
|
65
|
+
configurable: true,
|
|
66
|
+
value: nextValue,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (typeof setProperty !== 'undefined') {
|
|
71
|
+
return setProperty.call(target, [propertyName, nextValue], next)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return next()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
handler.get = function (target, propertyName, receiver) {
|
|
78
|
+
/**
|
|
79
|
+
* @note Using `Reflect.get()` here causes "TypeError: Illegal invocation".
|
|
80
|
+
*/
|
|
81
|
+
const next = () => target[propertyName as any]
|
|
82
|
+
|
|
83
|
+
const value =
|
|
84
|
+
typeof getProperty !== 'undefined'
|
|
85
|
+
? getProperty.call(target, [propertyName, receiver], next)
|
|
86
|
+
: next()
|
|
87
|
+
|
|
88
|
+
if (typeof value === 'function') {
|
|
89
|
+
return (...args: Array<any>) => {
|
|
90
|
+
const next = value.bind(target, ...args)
|
|
91
|
+
|
|
92
|
+
if (typeof methodCall !== 'undefined') {
|
|
93
|
+
return methodCall.call(target, [propertyName as any, args], next)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return next()
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return value
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return handler
|
|
104
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Emitter, EventMap } from 'strict-event-emitter'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Emits an event on the given emitter but executes
|
|
5
|
+
* the listeners sequentially. This accounts for asynchronous
|
|
6
|
+
* listeners (e.g. those having "sleep" and handling the request).
|
|
7
|
+
*/
|
|
8
|
+
export async function emitAsync<
|
|
9
|
+
Events extends EventMap,
|
|
10
|
+
EventName extends keyof Events
|
|
11
|
+
>(
|
|
12
|
+
emitter: Emitter<Events>,
|
|
13
|
+
eventName: EventName,
|
|
14
|
+
...data: Events[EventName]
|
|
15
|
+
): Promise<void> {
|
|
16
|
+
const listeners = emitter.listeners(eventName)
|
|
17
|
+
|
|
18
|
+
if (listeners.length === 0) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for (const listener of listeners) {
|
|
23
|
+
await listener.apply(emitter, data)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { canParseUrl } from './canParseUrl'
|
|
2
|
+
import { getValueBySymbol } from './getValueBySymbol'
|
|
3
|
+
|
|
4
|
+
export interface FetchResponseInit extends ResponseInit {
|
|
5
|
+
url?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface UndiciFetchInternalState {
|
|
9
|
+
aborted: boolean
|
|
10
|
+
rangeRequested: boolean
|
|
11
|
+
timingAllowPassed: boolean
|
|
12
|
+
requestIncludesCredentials: boolean
|
|
13
|
+
type: ResponseType
|
|
14
|
+
status: number
|
|
15
|
+
statusText: string
|
|
16
|
+
timingInfo: unknown
|
|
17
|
+
cacheState: unknown
|
|
18
|
+
headersList: Record<symbol, Map<string, unknown>>
|
|
19
|
+
urlList: Array<URL>
|
|
20
|
+
body?: {
|
|
21
|
+
stream: ReadableStream
|
|
22
|
+
source: unknown
|
|
23
|
+
length: number
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class FetchResponse extends Response {
|
|
28
|
+
/**
|
|
29
|
+
* Response status codes for responses that cannot have body.
|
|
30
|
+
* @see https://fetch.spec.whatwg.org/#statuses
|
|
31
|
+
*/
|
|
32
|
+
static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]
|
|
33
|
+
|
|
34
|
+
static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]
|
|
35
|
+
|
|
36
|
+
static isConfigurableStatusCode(status: number): boolean {
|
|
37
|
+
return status >= 200 && status <= 599
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static isRedirectResponse(status: number): boolean {
|
|
41
|
+
return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns a boolean indicating whether the given response status
|
|
46
|
+
* code represents a response that can have a body.
|
|
47
|
+
*/
|
|
48
|
+
static isResponseWithBody(status: number): boolean {
|
|
49
|
+
return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static setUrl(url: string | undefined, response: Response): void {
|
|
53
|
+
if (!url || url === 'about:' || !canParseUrl(url)) {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const state = getValueBySymbol<UndiciFetchInternalState>('state', response)
|
|
58
|
+
|
|
59
|
+
if (state) {
|
|
60
|
+
// In Undici, push the URL to the internal list of URLs.
|
|
61
|
+
// This will respect the `response.url` getter logic correctly.
|
|
62
|
+
state.urlList.push(new URL(url))
|
|
63
|
+
} else {
|
|
64
|
+
// In other libraries, redefine the `url` property directly.
|
|
65
|
+
Object.defineProperty(response, 'url', {
|
|
66
|
+
value: url,
|
|
67
|
+
enumerable: true,
|
|
68
|
+
configurable: true,
|
|
69
|
+
writable: false,
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Parses the given raw HTTP headers into a Fetch API `Headers` instance.
|
|
76
|
+
*/
|
|
77
|
+
static parseRawHeaders(rawHeaders: Array<string>): Headers {
|
|
78
|
+
const headers = new Headers()
|
|
79
|
+
for (let line = 0; line < rawHeaders.length; line += 2) {
|
|
80
|
+
headers.append(rawHeaders[line], rawHeaders[line + 1])
|
|
81
|
+
}
|
|
82
|
+
return headers
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {
|
|
86
|
+
const status = init.status ?? 200
|
|
87
|
+
const safeStatus = FetchResponse.isConfigurableStatusCode(status)
|
|
88
|
+
? status
|
|
89
|
+
: 200
|
|
90
|
+
const finalBody = FetchResponse.isResponseWithBody(status) ? body : null
|
|
91
|
+
|
|
92
|
+
super(finalBody, {
|
|
93
|
+
status: safeStatus,
|
|
94
|
+
statusText: init.statusText,
|
|
95
|
+
headers: init.headers,
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
if (status !== safeStatus) {
|
|
99
|
+
/**
|
|
100
|
+
* @note Undici keeps an internal "Symbol(state)" that holds
|
|
101
|
+
* the actual value of response status. Update that in Node.js.
|
|
102
|
+
*/
|
|
103
|
+
const state = getValueBySymbol<UndiciFetchInternalState>('state', this)
|
|
104
|
+
|
|
105
|
+
if (state) {
|
|
106
|
+
state.status = status
|
|
107
|
+
} else {
|
|
108
|
+
Object.defineProperty(this, 'status', {
|
|
109
|
+
value: status,
|
|
110
|
+
enumerable: true,
|
|
111
|
+
configurable: true,
|
|
112
|
+
writable: false,
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
FetchResponse.setUrl(init.url, this)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
2
|
+
import { findPropertySource } from './findPropertySource'
|
|
3
|
+
|
|
4
|
+
it('returns the source for objects without prototypes', () => {
|
|
5
|
+
const obj = Object.create(null)
|
|
6
|
+
obj.test = undefined
|
|
7
|
+
const source = findPropertySource(obj, 'test')
|
|
8
|
+
expect(source).toBe(obj)
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('returns the source for objects with prototypes', () => {
|
|
12
|
+
const prototype = Object.create(null)
|
|
13
|
+
prototype.test = undefined
|
|
14
|
+
|
|
15
|
+
const obj = Object.create(prototype)
|
|
16
|
+
|
|
17
|
+
const source = findPropertySource(obj, 'test')
|
|
18
|
+
expect(source).toBe(prototype)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('returns null if the prototype chain does not contain the property', () => {
|
|
22
|
+
const prototype = Object.create(null)
|
|
23
|
+
const obj = Object.create(prototype)
|
|
24
|
+
|
|
25
|
+
const source = findPropertySource(obj, 'test')
|
|
26
|
+
expect(source).toBeNull()
|
|
27
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the source object of the given property on the target object
|
|
3
|
+
* (the target itself, any parent in its prototype, or null).
|
|
4
|
+
*/
|
|
5
|
+
export function findPropertySource(
|
|
6
|
+
target: object,
|
|
7
|
+
propertyName: string | symbol
|
|
8
|
+
): object | null {
|
|
9
|
+
if (!(propertyName in target)) {
|
|
10
|
+
return null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName)
|
|
14
|
+
if (hasProperty) {
|
|
15
|
+
return target
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const prototype = Reflect.getPrototypeOf(target)
|
|
19
|
+
return prototype ? findPropertySource(prototype, propertyName) : null
|
|
20
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { getCleanUrl } from './getCleanUrl'
|
|
3
|
+
|
|
4
|
+
describe('getCleanUrl', () => {
|
|
5
|
+
describe('given a URL without query parameters', () => {
|
|
6
|
+
it('should return url href as-is', () => {
|
|
7
|
+
const url = new URL('https://github.com')
|
|
8
|
+
expect(getCleanUrl(url)).toEqual('https://github.com/')
|
|
9
|
+
})
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
describe('given a URL with query parameters', () => {
|
|
13
|
+
it('should return url without parameters', () => {
|
|
14
|
+
const url = new URL('https://github.com/mswjs/?userId=abc-123')
|
|
15
|
+
expect(getCleanUrl(url)).toEqual('https://github.com/mswjs/')
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
describe('given a URL with a hash', () => {
|
|
20
|
+
it('should return a url without hash', () => {
|
|
21
|
+
const url = new URL('https://github.com/mswjs/#hello-world')
|
|
22
|
+
expect(getCleanUrl(url)).toEqual('https://github.com/mswjs/')
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
describe('given an absolute URL ', () => {
|
|
27
|
+
it('should return a clean relative URL', () => {
|
|
28
|
+
const url = new URL('/login?query=value', 'https://github.com')
|
|
29
|
+
expect(getCleanUrl(url, false)).toEqual('/login')
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
})
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { it, expect } from 'vitest'
|
|
2
|
+
import { Agent as HttpAgent } from 'http'
|
|
3
|
+
import { RequestOptions, Agent as HttpsAgent } from 'https'
|
|
4
|
+
import { getUrlByRequestOptions } from './getUrlByRequestOptions'
|
|
5
|
+
|
|
6
|
+
it('returns a URL based on the basic RequestOptions', () => {
|
|
7
|
+
expect(
|
|
8
|
+
getUrlByRequestOptions({
|
|
9
|
+
protocol: 'https:',
|
|
10
|
+
host: '127.0.0.1',
|
|
11
|
+
path: '/resource',
|
|
12
|
+
}).href
|
|
13
|
+
).toBe('https://127.0.0.1/resource')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('inherits protocol and port from http.Agent, if set', () => {
|
|
17
|
+
expect(
|
|
18
|
+
getUrlByRequestOptions({
|
|
19
|
+
host: '127.0.0.1',
|
|
20
|
+
path: '/',
|
|
21
|
+
agent: new HttpAgent(),
|
|
22
|
+
}).href
|
|
23
|
+
).toBe('http://127.0.0.1/')
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('inherits protocol and port from https.Agent, if set', () => {
|
|
27
|
+
expect(
|
|
28
|
+
getUrlByRequestOptions({
|
|
29
|
+
host: '127.0.0.1',
|
|
30
|
+
path: '/',
|
|
31
|
+
agent: new HttpsAgent({
|
|
32
|
+
port: 3080,
|
|
33
|
+
}),
|
|
34
|
+
}).href
|
|
35
|
+
).toBe('https://127.0.0.1:3080/')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('resolves protocol to "http" given no explicit protocol and no certificate', () => {
|
|
39
|
+
expect(
|
|
40
|
+
getUrlByRequestOptions({
|
|
41
|
+
host: '127.0.0.1',
|
|
42
|
+
path: '/',
|
|
43
|
+
}).href
|
|
44
|
+
).toBe('http://127.0.0.1/')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('resolves protocol to "https" given no explicit protocol, but certificate', () => {
|
|
48
|
+
expect(
|
|
49
|
+
getUrlByRequestOptions({
|
|
50
|
+
host: '127.0.0.1',
|
|
51
|
+
path: '/secure',
|
|
52
|
+
cert: '<!-- SSL certificate -->',
|
|
53
|
+
}).href
|
|
54
|
+
).toBe('https://127.0.0.1/secure')
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('resolves protocol to "https" given no explicit protocol, but port is 443', () => {
|
|
58
|
+
expect(
|
|
59
|
+
getUrlByRequestOptions({
|
|
60
|
+
host: '127.0.0.1',
|
|
61
|
+
port: 443,
|
|
62
|
+
path: '/resource',
|
|
63
|
+
}).href
|
|
64
|
+
).toBe('https://127.0.0.1/resource')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('resolves protocol to "https" given no explicit protocol, but agent port is 443', () => {
|
|
68
|
+
expect(
|
|
69
|
+
getUrlByRequestOptions({
|
|
70
|
+
host: '127.0.0.1',
|
|
71
|
+
agent: new HttpsAgent({
|
|
72
|
+
port: 443,
|
|
73
|
+
}),
|
|
74
|
+
path: '/resource',
|
|
75
|
+
}).href
|
|
76
|
+
).toBe('https://127.0.0.1/resource')
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('respects explicitly provided port', () => {
|
|
80
|
+
expect(
|
|
81
|
+
getUrlByRequestOptions({
|
|
82
|
+
protocol: 'http:',
|
|
83
|
+
host: '127.0.0.1',
|
|
84
|
+
port: 4002,
|
|
85
|
+
path: '/',
|
|
86
|
+
}).href
|
|
87
|
+
).toBe('http://127.0.0.1:4002/')
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('inherits "username" and "password"', () => {
|
|
91
|
+
const url = getUrlByRequestOptions({
|
|
92
|
+
protocol: 'https:',
|
|
93
|
+
host: '127.0.0.1',
|
|
94
|
+
path: '/user',
|
|
95
|
+
auth: 'admin:abc-123',
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
expect(url).toBeInstanceOf(URL)
|
|
99
|
+
expect(url).toHaveProperty('username', 'admin')
|
|
100
|
+
expect(url).toHaveProperty('password', 'abc-123')
|
|
101
|
+
expect(url).toHaveProperty('href', 'https://admin:abc-123@127.0.0.1/user')
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('resolves hostname to localhost if none provided', () => {
|
|
105
|
+
expect(getUrlByRequestOptions({}).hostname).toBe('localhost')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('resolves host to localhost if none provided', () => {
|
|
109
|
+
expect(getUrlByRequestOptions({}).host).toBe('localhost')
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('supports "hostname" and "port"', () => {
|
|
113
|
+
const options: RequestOptions = {
|
|
114
|
+
protocol: 'https:',
|
|
115
|
+
hostname: '127.0.0.1',
|
|
116
|
+
port: 1234,
|
|
117
|
+
path: '/resource',
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
expect(getUrlByRequestOptions(options).href).toBe(
|
|
121
|
+
'https://127.0.0.1:1234/resource'
|
|
122
|
+
)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('use "hostname" if both "hostname" and "host" are specified', () => {
|
|
126
|
+
const options: RequestOptions = {
|
|
127
|
+
protocol: 'https:',
|
|
128
|
+
host: 'host',
|
|
129
|
+
hostname: 'hostname',
|
|
130
|
+
path: '/resource',
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
expect(getUrlByRequestOptions(options).href).toBe(
|
|
134
|
+
'https://hostname/resource'
|
|
135
|
+
)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('parses "host" in IPv6', () => {
|
|
139
|
+
expect(
|
|
140
|
+
getUrlByRequestOptions({
|
|
141
|
+
host: '::1',
|
|
142
|
+
path: '/resource',
|
|
143
|
+
}).href
|
|
144
|
+
).toBe('http://[::1]/resource')
|
|
145
|
+
|
|
146
|
+
expect(
|
|
147
|
+
getUrlByRequestOptions({
|
|
148
|
+
host: '[::1]',
|
|
149
|
+
path: '/resource',
|
|
150
|
+
}).href
|
|
151
|
+
).toBe('http://[::1]/resource')
|
|
152
|
+
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it('parses "host" and "port" in IPv6', () => {
|
|
156
|
+
expect(
|
|
157
|
+
getUrlByRequestOptions({
|
|
158
|
+
host: '::1',
|
|
159
|
+
port: 3001,
|
|
160
|
+
path: '/resource',
|
|
161
|
+
}).href
|
|
162
|
+
).toBe('http://[::1]:3001/resource')
|
|
163
|
+
})
|