@mswjs/interceptors 0.41.9 → 0.42.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.
Files changed (335) hide show
  1. package/README.md +274 -228
  2. package/lib/browser/{bufferUtils-BiiO6HZv.mjs → buffer-utils-DJj7YzLG.js} +3 -3
  3. package/lib/browser/buffer-utils-DJj7YzLG.js.map +1 -0
  4. package/lib/browser/create-request-id-DlEd4GOA.js +184 -0
  5. package/lib/browser/create-request-id-DlEd4GOA.js.map +1 -0
  6. package/lib/browser/{getRawRequest-B1BqgWG6.mjs → fetch-utils-zxA_SD66.js} +123 -52
  7. package/lib/browser/fetch-utils-zxA_SD66.js.map +1 -0
  8. package/lib/browser/handle-request-CIOa9O-N.js +167 -0
  9. package/lib/browser/handle-request-CIOa9O-N.js.map +1 -0
  10. package/lib/{node/hasConfigurableGlobal-BiTmog1u.mjs → browser/has-configurable-global-Cew-dYqk.js} +5 -7
  11. package/lib/browser/has-configurable-global-Cew-dYqk.js.map +1 -0
  12. package/lib/browser/http-CB9rQ7i_.d.ts +105 -0
  13. package/lib/browser/{index.d.cts → index.d.ts} +33 -38
  14. package/lib/browser/index.js +130 -0
  15. package/lib/browser/index.js.map +1 -0
  16. package/lib/browser/interceptor-dtJZ_9QT.d.ts +50 -0
  17. package/lib/browser/interceptors/WebSocket/index.d.ts +2 -0
  18. package/lib/browser/interceptors/WebSocket/{index.mjs → index.js} +39 -30
  19. package/lib/browser/interceptors/WebSocket/index.js.map +1 -0
  20. package/lib/browser/interceptors/XMLHttpRequest/web.d.ts +11 -0
  21. package/lib/browser/interceptors/XMLHttpRequest/web.js +2 -0
  22. package/lib/browser/interceptors/fetch/web.d.ts +14 -0
  23. package/lib/browser/interceptors/fetch/web.js +2 -0
  24. package/lib/browser/presets/browser.d.ts +11 -0
  25. package/lib/browser/presets/browser.js +12 -0
  26. package/lib/browser/presets/browser.js.map +1 -0
  27. package/lib/browser/{resolveWebSocketUrl-C83-x9iE.mjs → resolve-web-socket-url-CSvNPLGi.js} +3 -3
  28. package/lib/browser/resolve-web-socket-url-CSvNPLGi.js.map +1 -0
  29. package/lib/browser/web-BjVDkiX0.js +248 -0
  30. package/lib/browser/web-BjVDkiX0.js.map +1 -0
  31. package/lib/browser/{XMLHttpRequest-DrZAf3w6.mjs → web-C2oKsT3Q.js} +327 -255
  32. package/lib/browser/web-C2oKsT3Q.js.map +1 -0
  33. package/lib/browser/{interceptors/WebSocket/index.d.cts → websocket-CC0nB0md.d.ts} +41 -33
  34. package/lib/node/batch-interceptor-ByEZVih3.js +119 -0
  35. package/lib/node/batch-interceptor-ByEZVih3.js.map +1 -0
  36. package/lib/node/batch-interceptor-CPjFK2td.d.ts +28 -0
  37. package/lib/node/buffer-utils-BvPY1Tc-.js +187 -0
  38. package/lib/node/buffer-utils-BvPY1Tc-.js.map +1 -0
  39. package/lib/node/fetch-utils-Dw1PsmtX.js +568 -0
  40. package/lib/node/fetch-utils-Dw1PsmtX.js.map +1 -0
  41. package/lib/node/has-configurable-global-CJCh_g1I.js +22 -0
  42. package/lib/node/has-configurable-global-CJCh_g1I.js.map +1 -0
  43. package/lib/node/http-CB9rQ7i_.d.ts +105 -0
  44. package/lib/{browser/interceptors/WebSocket/index.d.mts → node/index.d.ts} +120 -60
  45. package/lib/node/{index.mjs → index.js} +8 -11
  46. package/lib/node/index.js.map +1 -0
  47. package/lib/node/interceptor-dtJZ_9QT.d.ts +50 -0
  48. package/lib/node/interceptors/ClientRequest/index.d.ts +14 -0
  49. package/lib/node/interceptors/ClientRequest/index.js +67 -0
  50. package/lib/node/interceptors/ClientRequest/index.js.map +1 -0
  51. package/lib/node/interceptors/XMLHttpRequest/node.d.ts +12 -0
  52. package/lib/node/interceptors/XMLHttpRequest/node.js +74 -0
  53. package/lib/node/interceptors/XMLHttpRequest/node.js.map +1 -0
  54. package/lib/node/interceptors/fetch/node.d.ts +18 -0
  55. package/lib/node/interceptors/fetch/node.js +83 -0
  56. package/lib/node/interceptors/fetch/node.js.map +1 -0
  57. package/lib/node/interceptors/http/index.d.ts +14 -0
  58. package/lib/node/interceptors/http/index.js +32 -0
  59. package/lib/node/interceptors/http/index.js.map +1 -0
  60. package/lib/node/interceptors/net/index.d.ts +203 -0
  61. package/lib/node/interceptors/net/index.js +2 -0
  62. package/lib/node/llhttp/constants.cjs +485 -0
  63. package/lib/node/llhttp/constants.d.cts +957 -0
  64. package/lib/node/llhttp/llhttp.wasm +0 -0
  65. package/lib/node/net-DtMnyEeg.js +1388 -0
  66. package/lib/node/net-DtMnyEeg.js.map +1 -0
  67. package/lib/node/presets/node.d.ts +12 -0
  68. package/lib/node/presets/node.js +17 -0
  69. package/lib/node/presets/node.js.map +1 -0
  70. package/lib/node/{RemoteHttpInterceptor.d.cts → remote-http-interceptor.d.ts} +12 -11
  71. package/lib/node/{RemoteHttpInterceptor.mjs → remote-http-interceptor.js} +38 -33
  72. package/lib/node/remote-http-interceptor.js.map +1 -0
  73. package/lib/node/source-lP0yyEtA.js +1990 -0
  74. package/lib/node/source-lP0yyEtA.js.map +1 -0
  75. package/package.json +79 -118
  76. package/src/batch-interceptor.test.ts +475 -0
  77. package/src/batch-interceptor.ts +244 -0
  78. package/src/{createRequestId.test.ts → create-request-id.test.ts} +1 -2
  79. package/src/disposable.ts +13 -0
  80. package/src/events/http.ts +92 -0
  81. package/src/events/websocket.ts +47 -0
  82. package/src/glossary.ts +1 -27
  83. package/src/index.ts +18 -10
  84. package/src/interceptor.test.ts +279 -0
  85. package/src/interceptor.ts +139 -0
  86. package/src/interceptors/ClientRequest/index.test.ts +21 -39
  87. package/src/interceptors/ClientRequest/index.ts +64 -179
  88. package/src/interceptors/ClientRequest/utils/{recordRawHeaders.test.ts → record-raw-headers.test.ts} +1 -2
  89. package/src/interceptors/ClientRequest/utils/{recordRawHeaders.ts → record-raw-headers.ts} +29 -2
  90. package/src/interceptors/WebSocket/index.ts +33 -50
  91. package/src/interceptors/WebSocket/utils/{bindEvent.test.ts → bind-event.test.ts} +1 -2
  92. package/src/interceptors/WebSocket/utils/events.test.ts +0 -1
  93. package/src/interceptors/WebSocket/{WebSocketClassTransport.ts → web-socket-class-transport.ts} +3 -3
  94. package/src/interceptors/WebSocket/{WebSocketClientConnection.ts → web-socket-client-connection.ts} +4 -4
  95. package/src/interceptors/WebSocket/{WebSocketOverride.ts → web-socket-override.ts} +6 -7
  96. package/src/interceptors/WebSocket/{WebSocketServerConnection.ts → web-socket-server-connection.ts} +4 -4
  97. package/src/interceptors/WebSocket/{WebSocketTransport.ts → web-socket-transport.ts} +1 -1
  98. package/src/interceptors/XMLHttpRequest/node.ts +104 -0
  99. package/src/interceptors/XMLHttpRequest/polyfills/{ProgressEventPolyfill.ts → progress-event-polyfill.ts} +1 -1
  100. package/src/interceptors/XMLHttpRequest/utils/{concateArrayBuffer.test.ts → concat-array-buffer.test.ts} +1 -2
  101. package/src/interceptors/XMLHttpRequest/utils/{concatArrayBuffer.ts → concat-array-buffer.ts} +1 -1
  102. package/src/interceptors/XMLHttpRequest/utils/{createEvent.test.ts → create-event.test.ts} +3 -4
  103. package/src/interceptors/XMLHttpRequest/utils/{createEvent.ts → create-event.ts} +2 -2
  104. package/src/interceptors/XMLHttpRequest/utils/{createResponse.ts → create-response.ts} +1 -1
  105. package/src/interceptors/XMLHttpRequest/utils/{getBodyByteLength.test.ts → get-body-byte-length.test.ts} +1 -2
  106. package/src/interceptors/XMLHttpRequest/web.ts +34 -0
  107. package/src/interceptors/XMLHttpRequest/{XMLHttpRequestController.ts → xml-http-request-controller.ts} +363 -204
  108. package/src/interceptors/XMLHttpRequest/{XMLHttpRequestProxy.ts → xml-http-request-proxy.ts} +28 -25
  109. package/src/interceptors/fetch/node.ts +103 -0
  110. package/src/interceptors/fetch/utils/{followRedirect.ts → follow-redirect.ts} +1 -1
  111. package/src/interceptors/fetch/web.ts +217 -0
  112. package/src/interceptors/http/forward-events.test.ts +86 -0
  113. package/src/interceptors/http/forward-events.ts +139 -0
  114. package/src/interceptors/http/http-parser/index.ts +310 -0
  115. package/src/interceptors/http/http-parser/llhttp/constants.cjs +485 -0
  116. package/src/interceptors/http/http-parser/llhttp/constants.d.cts +957 -0
  117. package/src/interceptors/http/http-parser/llhttp/llhttp.wasm +0 -0
  118. package/src/interceptors/http/http-parser.ts +138 -0
  119. package/src/interceptors/http/index.ts +34 -0
  120. package/src/interceptors/http/source.ts +688 -0
  121. package/src/interceptors/net/index.ts +368 -0
  122. package/src/interceptors/net/socket-controller.ts +1476 -0
  123. package/src/interceptors/net/utils/address-info.ts +54 -0
  124. package/src/interceptors/net/utils/connection-options-to-url.ts +56 -0
  125. package/src/interceptors/net/utils/flush-writes.ts +57 -0
  126. package/src/interceptors/net/utils/get-tls-connect-options.ts +23 -0
  127. package/src/interceptors/net/utils/normalize-net-connect-args.test.ts +233 -0
  128. package/src/interceptors/net/utils/normalize-net-connect-args.ts +121 -0
  129. package/src/interceptors/net/utils/normalize-tls-connect-args.ts +50 -0
  130. package/src/presets/browser.ts +4 -4
  131. package/src/presets/node.ts +4 -4
  132. package/src/{RemoteHttpInterceptor.ts → remote-http-interceptor.ts} +55 -42
  133. package/src/request-context.ts +40 -0
  134. package/src/{RequestController.test.ts → request-controller.test.ts} +37 -3
  135. package/src/{RequestController.ts → request-controller.ts} +33 -11
  136. package/src/utils/{bufferUtils.test.ts → buffer-utils.test.ts} +1 -2
  137. package/src/utils/buffer-utils.ts +37 -0
  138. package/src/utils/{cloneObject.test.ts → clone-object.test.ts} +1 -2
  139. package/src/utils/{cloneObject.ts → clone-object.ts} +8 -8
  140. package/src/utils/{createProxy.test.ts → create-proxy.test.ts} +6 -4
  141. package/src/utils/{createProxy.ts → create-proxy.ts} +1 -1
  142. package/src/utils/{fetchUtils.test.ts → fetch-utils.test.ts} +1 -1
  143. package/src/utils/{fetchUtils.ts → fetch-utils.ts} +28 -3
  144. package/src/utils/{findPropertySource.test.ts → find-property-source.test.ts} +1 -2
  145. package/src/utils/{getCleanUrl.test.ts → get-clean-url.test.ts} +1 -2
  146. package/src/utils/{getUrlByRequestOptions.test.ts → get-url-by-request-options.test.ts} +4 -8
  147. package/src/utils/{getUrlByRequestOptions.ts → get-url-by-request-options.ts} +16 -16
  148. package/src/utils/{getValueBySymbol.test.ts → get-value-by-symbol.test.ts} +1 -2
  149. package/src/utils/{handleRequest.ts → handle-request.ts} +61 -41
  150. package/src/utils/{hasConfigurableGlobal.test.ts → has-configurable-global.test.ts} +1 -2
  151. package/src/utils/{hasConfigurableGlobal.ts → has-configurable-global.ts} +2 -4
  152. package/src/utils/{isObject.test.ts → is-object.test.ts} +1 -2
  153. package/src/utils/logger.test.ts +154 -0
  154. package/src/utils/logger.ts +154 -0
  155. package/src/utils/{parseJson.test.ts → parse-json.test.ts} +1 -2
  156. package/src/utils/{patchesRegistry.test.ts → patches-registry.test.ts} +1 -1
  157. package/src/utils/{patchesRegistry.ts → patches-registry.ts} +1 -1
  158. package/src/utils/{responseUtils.ts → response-utils.ts} +25 -2
  159. package/ClientRequest/package.json +0 -11
  160. package/RemoteHttpInterceptor/package.json +0 -11
  161. package/WebSocket/package.json +0 -12
  162. package/XMLHttpRequest/package.json +0 -12
  163. package/fetch/package.json +0 -12
  164. package/lib/browser/Interceptor-Deczogc8.d.cts +0 -65
  165. package/lib/browser/Interceptor-gqKgs-aF.d.mts +0 -65
  166. package/lib/browser/XMLHttpRequest-DrZAf3w6.mjs.map +0 -1
  167. package/lib/browser/XMLHttpRequest-gXuzzX1g.cjs +0 -751
  168. package/lib/browser/XMLHttpRequest-gXuzzX1g.cjs.map +0 -1
  169. package/lib/browser/bufferUtils-BiiO6HZv.mjs.map +0 -1
  170. package/lib/browser/bufferUtils-Uc0eRItL.cjs +0 -38
  171. package/lib/browser/bufferUtils-Uc0eRItL.cjs.map +0 -1
  172. package/lib/browser/createRequestId-DOf8Ktjs.cjs +0 -205
  173. package/lib/browser/createRequestId-DOf8Ktjs.cjs.map +0 -1
  174. package/lib/browser/createRequestId-DYCsFHOi.mjs +0 -170
  175. package/lib/browser/createRequestId-DYCsFHOi.mjs.map +0 -1
  176. package/lib/browser/fetch-5IMPqr9e.mjs +0 -236
  177. package/lib/browser/fetch-5IMPqr9e.mjs.map +0 -1
  178. package/lib/browser/fetch-Bt9rMY9c.cjs +0 -241
  179. package/lib/browser/fetch-Bt9rMY9c.cjs.map +0 -1
  180. package/lib/browser/getRawRequest-B1BqgWG6.mjs.map +0 -1
  181. package/lib/browser/getRawRequest-DdfaiPVH.cjs +0 -376
  182. package/lib/browser/getRawRequest-DdfaiPVH.cjs.map +0 -1
  183. package/lib/browser/glossary-1lhZx6Aw.d.cts +0 -69
  184. package/lib/browser/glossary-nkHWcwvY.d.mts +0 -69
  185. package/lib/browser/handleRequest-CJim54xG.cjs +0 -191
  186. package/lib/browser/handleRequest-CJim54xG.cjs.map +0 -1
  187. package/lib/browser/handleRequest-CPPgsG7s.mjs +0 -180
  188. package/lib/browser/handleRequest-CPPgsG7s.mjs.map +0 -1
  189. package/lib/browser/hasConfigurableGlobal-C8zq1MCg.mjs +0 -109
  190. package/lib/browser/hasConfigurableGlobal-C8zq1MCg.mjs.map +0 -1
  191. package/lib/browser/hasConfigurableGlobal-CS7adEvV.cjs +0 -126
  192. package/lib/browser/hasConfigurableGlobal-CS7adEvV.cjs.map +0 -1
  193. package/lib/browser/index.cjs +0 -70
  194. package/lib/browser/index.cjs.map +0 -1
  195. package/lib/browser/index.d.mts +0 -125
  196. package/lib/browser/index.mjs +0 -56
  197. package/lib/browser/index.mjs.map +0 -1
  198. package/lib/browser/interceptors/WebSocket/index.cjs +0 -618
  199. package/lib/browser/interceptors/WebSocket/index.cjs.map +0 -1
  200. package/lib/browser/interceptors/WebSocket/index.mjs.map +0 -1
  201. package/lib/browser/interceptors/XMLHttpRequest/index.cjs +0 -8
  202. package/lib/browser/interceptors/XMLHttpRequest/index.d.cts +0 -15
  203. package/lib/browser/interceptors/XMLHttpRequest/index.d.mts +0 -15
  204. package/lib/browser/interceptors/XMLHttpRequest/index.mjs +0 -8
  205. package/lib/browser/interceptors/fetch/index.cjs +0 -7
  206. package/lib/browser/interceptors/fetch/index.d.cts +0 -13
  207. package/lib/browser/interceptors/fetch/index.d.mts +0 -13
  208. package/lib/browser/interceptors/fetch/index.mjs +0 -7
  209. package/lib/browser/presets/browser.cjs +0 -18
  210. package/lib/browser/presets/browser.cjs.map +0 -1
  211. package/lib/browser/presets/browser.d.cts +0 -12
  212. package/lib/browser/presets/browser.d.mts +0 -14
  213. package/lib/browser/presets/browser.mjs +0 -18
  214. package/lib/browser/presets/browser.mjs.map +0 -1
  215. package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs +0 -31
  216. package/lib/browser/resolveWebSocketUrl-6K6EgqsA.cjs.map +0 -1
  217. package/lib/browser/resolveWebSocketUrl-C83-x9iE.mjs.map +0 -1
  218. package/lib/node/BatchInterceptor-BGhH8z1z.cjs +0 -49
  219. package/lib/node/BatchInterceptor-BGhH8z1z.cjs.map +0 -1
  220. package/lib/node/BatchInterceptor-C4-RX5rg.mjs +0 -44
  221. package/lib/node/BatchInterceptor-C4-RX5rg.mjs.map +0 -1
  222. package/lib/node/BatchInterceptor-KKF8Q47I.d.cts +0 -26
  223. package/lib/node/BatchInterceptor-rSr-NH_H.d.mts +0 -26
  224. package/lib/node/ClientRequest-2loAH7xM.cjs +0 -1058
  225. package/lib/node/ClientRequest-2loAH7xM.cjs.map +0 -1
  226. package/lib/node/ClientRequest-DGhBX21V.mjs +0 -1049
  227. package/lib/node/ClientRequest-DGhBX21V.mjs.map +0 -1
  228. package/lib/node/Interceptor-BsZ21ue0.d.cts +0 -132
  229. package/lib/node/Interceptor-soD-WpQO.d.mts +0 -132
  230. package/lib/node/RemoteHttpInterceptor.cjs +0 -155
  231. package/lib/node/RemoteHttpInterceptor.cjs.map +0 -1
  232. package/lib/node/RemoteHttpInterceptor.d.mts +0 -39
  233. package/lib/node/RemoteHttpInterceptor.mjs.map +0 -1
  234. package/lib/node/XMLHttpRequest-BtDNZipW.cjs +0 -752
  235. package/lib/node/XMLHttpRequest-BtDNZipW.cjs.map +0 -1
  236. package/lib/node/XMLHttpRequest-Dw6Wm-UU.mjs +0 -746
  237. package/lib/node/XMLHttpRequest-Dw6Wm-UU.mjs.map +0 -1
  238. package/lib/node/bufferUtils-DxPxwff_.mjs +0 -20
  239. package/lib/node/bufferUtils-DxPxwff_.mjs.map +0 -1
  240. package/lib/node/bufferUtils-S5_-2eN4.cjs +0 -38
  241. package/lib/node/bufferUtils-S5_-2eN4.cjs.map +0 -1
  242. package/lib/node/chunk-CbDLau6x.cjs +0 -34
  243. package/lib/node/fetch-CaC3rGEu.mjs +0 -252
  244. package/lib/node/fetch-CaC3rGEu.mjs.map +0 -1
  245. package/lib/node/fetch-D2ClLNN-.cjs +0 -259
  246. package/lib/node/fetch-D2ClLNN-.cjs.map +0 -1
  247. package/lib/node/fetchUtils-BKJ1XmiO.mjs +0 -480
  248. package/lib/node/fetchUtils-BKJ1XmiO.mjs.map +0 -1
  249. package/lib/node/fetchUtils-umV5xXBy.cjs +0 -546
  250. package/lib/node/fetchUtils-umV5xXBy.cjs.map +0 -1
  251. package/lib/node/getRawRequest-B6znU6il.cjs +0 -36
  252. package/lib/node/getRawRequest-B6znU6il.cjs.map +0 -1
  253. package/lib/node/getRawRequest-C2-1urzA.mjs +0 -24
  254. package/lib/node/getRawRequest-C2-1urzA.mjs.map +0 -1
  255. package/lib/node/handleRequest-C-cKYjIh.cjs +0 -222
  256. package/lib/node/handleRequest-C-cKYjIh.cjs.map +0 -1
  257. package/lib/node/handleRequest-FIQv5pwH.mjs +0 -192
  258. package/lib/node/handleRequest-FIQv5pwH.mjs.map +0 -1
  259. package/lib/node/hasConfigurableGlobal-BiTmog1u.mjs.map +0 -1
  260. package/lib/node/hasConfigurableGlobal-MjY06_Ok.cjs +0 -108
  261. package/lib/node/hasConfigurableGlobal-MjY06_Ok.cjs.map +0 -1
  262. package/lib/node/index-BJ5E5aW-.d.cts +0 -113
  263. package/lib/node/index-DfoF45ih.d.mts +0 -113
  264. package/lib/node/index.cjs +0 -53
  265. package/lib/node/index.cjs.map +0 -1
  266. package/lib/node/index.d.cts +0 -104
  267. package/lib/node/index.d.mts +0 -104
  268. package/lib/node/index.mjs.map +0 -1
  269. package/lib/node/interceptors/ClientRequest/index.cjs +0 -6
  270. package/lib/node/interceptors/ClientRequest/index.d.cts +0 -2
  271. package/lib/node/interceptors/ClientRequest/index.d.mts +0 -3
  272. package/lib/node/interceptors/ClientRequest/index.mjs +0 -6
  273. package/lib/node/interceptors/XMLHttpRequest/index.cjs +0 -7
  274. package/lib/node/interceptors/XMLHttpRequest/index.d.cts +0 -14
  275. package/lib/node/interceptors/XMLHttpRequest/index.d.mts +0 -14
  276. package/lib/node/interceptors/XMLHttpRequest/index.mjs +0 -7
  277. package/lib/node/interceptors/fetch/index.cjs +0 -6
  278. package/lib/node/interceptors/fetch/index.d.cts +0 -12
  279. package/lib/node/interceptors/fetch/index.d.mts +0 -12
  280. package/lib/node/interceptors/fetch/index.mjs +0 -6
  281. package/lib/node/node-DIKcnzhK.cjs +0 -39
  282. package/lib/node/node-DIKcnzhK.cjs.map +0 -1
  283. package/lib/node/node-lsdNwZEW.mjs +0 -27
  284. package/lib/node/node-lsdNwZEW.mjs.map +0 -1
  285. package/lib/node/presets/node.cjs +0 -23
  286. package/lib/node/presets/node.cjs.map +0 -1
  287. package/lib/node/presets/node.d.cts +0 -13
  288. package/lib/node/presets/node.d.mts +0 -15
  289. package/lib/node/presets/node.mjs +0 -23
  290. package/lib/node/presets/node.mjs.map +0 -1
  291. package/lib/node/utils/node/index.cjs +0 -4
  292. package/lib/node/utils/node/index.d.cts +0 -16
  293. package/lib/node/utils/node/index.d.mts +0 -16
  294. package/lib/node/utils/node/index.mjs +0 -3
  295. package/presets/browser/package.json +0 -5
  296. package/presets/node/package.json +0 -11
  297. package/src/BatchInterceptor.test.ts +0 -255
  298. package/src/BatchInterceptor.ts +0 -96
  299. package/src/Interceptor.test.ts +0 -205
  300. package/src/Interceptor.ts +0 -249
  301. package/src/getRawRequest.ts +0 -21
  302. package/src/interceptors/ClientRequest/MockHttpSocket.ts +0 -724
  303. package/src/interceptors/ClientRequest/agents.ts +0 -110
  304. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +0 -54
  305. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +0 -45
  306. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +0 -427
  307. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +0 -268
  308. package/src/interceptors/ClientRequest/utils/parserUtils.ts +0 -48
  309. package/src/interceptors/Socket/MockSocket.test.ts +0 -264
  310. package/src/interceptors/Socket/MockSocket.ts +0 -58
  311. package/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +0 -26
  312. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts +0 -52
  313. package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +0 -33
  314. package/src/interceptors/XMLHttpRequest/index.ts +0 -40
  315. package/src/interceptors/fetch/index.ts +0 -203
  316. package/src/utils/bufferUtils.ts +0 -22
  317. package/src/utils/canParseUrl.ts +0 -13
  318. package/src/utils/emitAsync.ts +0 -25
  319. package/src/utils/nextTick.ts +0 -11
  320. package/src/utils/node/index.ts +0 -39
  321. /package/src/{createRequestId.ts → create-request-id.ts} +0 -0
  322. /package/src/{InterceptorError.ts → interceptor-error.ts} +0 -0
  323. /package/src/interceptors/WebSocket/utils/{bindEvent.ts → bind-event.ts} +0 -0
  324. /package/src/interceptors/XMLHttpRequest/polyfills/{EventPolyfill.ts → event-polyfill.ts} +0 -0
  325. /package/src/interceptors/XMLHttpRequest/utils/{getBodyByteLength.ts → get-body-byte-length.ts} +0 -0
  326. /package/src/interceptors/XMLHttpRequest/utils/{isDomParserSupportedType.ts → is-dom-parser-supported-type.ts} +0 -0
  327. /package/src/interceptors/fetch/utils/{createNetworkError.ts → create-network-error.ts} +0 -0
  328. /package/src/utils/{findPropertySource.ts → find-property-source.ts} +0 -0
  329. /package/src/utils/{getCleanUrl.ts → get-clean-url.ts} +0 -0
  330. /package/src/utils/{getValueBySymbol.ts → get-value-by-symbol.ts} +0 -0
  331. /package/src/utils/{isNodeLikeError.ts → is-node-like-error.ts} +0 -0
  332. /package/src/utils/{isObject.ts → is-object.ts} +0 -0
  333. /package/src/utils/{isPropertyAccessible.ts → is-property-accessible.ts} +0 -0
  334. /package/src/utils/{parseJson.ts → parse-json.ts} +0 -0
  335. /package/src/utils/{resolveWebSocketUrl.ts → resolve-web-socket-url.ts} +0 -0
@@ -1,26 +1,26 @@
1
+ import { until } from '@open-draft/until'
1
2
  import { invariant } from 'outvariant'
2
- import { isNodeProcess } from 'is-node-process'
3
- import type { Logger } from '@open-draft/logger'
4
- import { concatArrayBuffer } from './utils/concatArrayBuffer'
5
- import { createEvent } from './utils/createEvent'
3
+ import type { Logger } from '../../utils/logger'
4
+ import type { HttpResponseType } from '../../events/http'
5
+ import { concatArrayBuffer } from './utils/concat-array-buffer'
6
+ import { createEvent } from './utils/create-event'
6
7
  import {
7
8
  decodeBuffer,
8
9
  encodeBuffer,
9
10
  toArrayBuffer,
10
- } from '../../utils/bufferUtils'
11
- import { createProxy } from '../../utils/createProxy'
12
- import { isDomParserSupportedType } from './utils/isDomParserSupportedType'
13
- import { parseJson } from '../../utils/parseJson'
14
- import { createResponse } from './utils/createResponse'
15
- import { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'
16
- import { createRequestId } from '../../createRequestId'
17
- import { getBodyByteLength } from './utils/getBodyByteLength'
18
- import { setRawRequest } from '../../getRawRequest'
19
- import { FetchRequest } from '../../utils/fetchUtils'
11
+ } from '../../utils/buffer-utils'
12
+ import { createProxy } from '../../utils/create-proxy'
13
+ import { isDomParserSupportedType } from './utils/is-dom-parser-supported-type'
14
+ import { parseJson } from '../../utils/parse-json'
15
+ import { createResponse } from './utils/create-response'
16
+ import { createRequestId } from '../../create-request-id'
17
+ import { getBodyByteLength } from './utils/get-body-byte-length'
18
+ import { FetchRequest, FetchResponse } from '../../utils/fetch-utils'
19
+ import { isResponseError } from '../../utils/response-utils'
20
20
 
21
21
  const kIsRequestHandled = Symbol('kIsRequestHandled')
22
- const IS_NODE = isNodeProcess()
23
22
  const kFetchRequest = Symbol('kFetchRequest')
23
+ const MAX_REDIRECTS = 20
24
24
 
25
25
  /**
26
26
  * An `XMLHttpRequest` instance controller that allows us
@@ -40,7 +40,7 @@ export class XMLHttpRequestController {
40
40
  this: XMLHttpRequestController,
41
41
  args: {
42
42
  response: Response
43
- isMockedResponse: boolean
43
+ responseType: HttpResponseType
44
44
  request: Request
45
45
  requestId: string
46
46
  }
@@ -48,10 +48,13 @@ export class XMLHttpRequestController {
48
48
 
49
49
  [kIsRequestHandled]: boolean;
50
50
  [kFetchRequest]?: Request
51
+
52
+ private sync: boolean = false
51
53
  private method: string = 'GET'
52
54
  private url: URL = null as any
53
55
  private requestHeaders: Headers
54
- private responseBuffer: Uint8Array
56
+ private responseBuffer: Uint8Array<ArrayBuffer>
57
+ private redirectCount: number
55
58
  private events: Map<keyof XMLHttpRequestEventTargetEventMap, Array<Function>>
56
59
  private uploadEvents: Map<
57
60
  keyof XMLHttpRequestEventTargetEventMap,
@@ -64,6 +67,7 @@ export class XMLHttpRequestController {
64
67
  ) {
65
68
  this[kIsRequestHandled] = false
66
69
 
70
+ this.redirectCount = 0
67
71
  this.events = new Map()
68
72
  this.uploadEvents = new Map()
69
73
  this.requestId = createRequestId()
@@ -71,32 +75,16 @@ export class XMLHttpRequestController {
71
75
  this.responseBuffer = new Uint8Array()
72
76
 
73
77
  this.request = createProxy(initialRequest, {
74
- setProperty: ([propertyName, nextValue], invoke) => {
75
- switch (propertyName) {
76
- case 'ontimeout': {
77
- const eventName = propertyName.slice(
78
- 2
79
- ) as keyof XMLHttpRequestEventTargetEventMap
80
-
81
- /**
82
- * @note Proxy callbacks to event listeners because JSDOM has trouble
83
- * translating these properties to callbacks. It seemed to be operating
84
- * on events exclusively.
85
- */
86
- this.request.addEventListener(eventName, nextValue as any)
87
-
88
- return invoke()
89
- }
90
-
91
- default: {
92
- return invoke()
93
- }
94
- }
95
- },
96
78
  methodCall: ([methodName, args], invoke) => {
97
79
  switch (methodName) {
98
80
  case 'open': {
99
- const [method, url] = args as [string, string | undefined]
81
+ const [method, url, async] = args as [
82
+ string,
83
+ string | undefined,
84
+ boolean | undefined,
85
+ ]
86
+
87
+ this.sync = !(async ?? true)
100
88
 
101
89
  if (typeof url === 'undefined') {
102
90
  this.method = 'GET'
@@ -106,8 +94,7 @@ export class XMLHttpRequestController {
106
94
  this.url = toAbsoluteUrl(url)
107
95
  }
108
96
 
109
- this.logger = this.logger.extend(`${this.method} ${this.url.href}`)
110
- this.logger.info('open', this.method, this.url.href)
97
+ this.logger.verbose('open %s %s', this.method, this.url.href)
111
98
 
112
99
  return invoke()
113
100
  }
@@ -119,7 +106,7 @@ export class XMLHttpRequestController {
119
106
  ]
120
107
 
121
108
  this.registerEvent(eventName, listener)
122
- this.logger.info('addEventListener', eventName, listener)
109
+ this.logger.verbose('addEventListener', eventName, listener)
123
110
 
124
111
  return invoke()
125
112
  }
@@ -128,7 +115,7 @@ export class XMLHttpRequestController {
128
115
  const [name, value] = args as [string, string]
129
116
  this.requestHeaders.set(name, value)
130
117
 
131
- this.logger.info('setRequestHeader', name, value)
118
+ this.logger.verbose('setRequestHeader', name, value)
132
119
 
133
120
  return invoke()
134
121
  }
@@ -138,6 +125,13 @@ export class XMLHttpRequestController {
138
125
  body?: XMLHttpRequestBodyInit | Document | null,
139
126
  ]
140
127
 
128
+ if (this.sync) {
129
+ console.warn(
130
+ `Failed to intercept an XMLHttpRequest (${this.method} ${this.url}): synchronous requests are not supported. This request will be performed as-is.`
131
+ )
132
+ return invoke()
133
+ }
134
+
141
135
  this.request.addEventListener('load', () => {
142
136
  if (typeof this.onResponse !== 'undefined') {
143
137
  // Create a Fetch API Response representation of whichever
@@ -156,7 +150,7 @@ export class XMLHttpRequestController {
156
150
  // Notify the consumer about the response.
157
151
  this.onResponse.call(this, {
158
152
  response: fetchResponse,
159
- isMockedResponse: this[kIsRequestHandled],
153
+ responseType: this[kIsRequestHandled] ? 'mock' : 'original',
160
154
  request: fetchRequest,
161
155
  requestId: this.requestId!,
162
156
  })
@@ -184,27 +178,11 @@ export class XMLHttpRequestController {
184
178
  onceRequestSettled.finally(() => {
185
179
  // If the consumer didn't handle the request (called `.respondWith()`) perform it as-is.
186
180
  if (!this[kIsRequestHandled]) {
187
- this.logger.info(
181
+ this.logger.verbose(
188
182
  'request callback settled but request has not been handled (readystate %d), performing as-is...',
189
183
  this.request.readyState
190
184
  )
191
185
 
192
- /**
193
- * @note Set the intercepted request ID on the original request in Node.js
194
- * so that if it triggers any other interceptors, they don't attempt
195
- * to process it once again.
196
- *
197
- * For instance, XMLHttpRequest is often implemented via "http.ClientRequest"
198
- * and we don't want for both XHR and ClientRequest interceptors to
199
- * handle the same request at the same time (e.g. emit the "response" event twice).
200
- */
201
- if (IS_NODE) {
202
- this.request.setRequestHeader(
203
- INTERNAL_REQUEST_ID_HEADER_NAME,
204
- this.requestId!
205
- )
206
- }
207
-
208
186
  return invoke()
209
187
  }
210
188
  })
@@ -254,7 +232,7 @@ export class XMLHttpRequestController {
254
232
  Function,
255
233
  ]
256
234
  this.registerUploadEvent(eventName, listener)
257
- this.logger.info('upload.addEventListener', eventName, listener)
235
+ this.logger.verbose('upload.addEventListener', eventName, listener)
258
236
 
259
237
  return invoke()
260
238
  }
@@ -272,7 +250,7 @@ export class XMLHttpRequestController {
272
250
  const nextEvents = prevEvents.concat(listener)
273
251
  this.events.set(eventName, nextEvents)
274
252
 
275
- this.logger.info('registered event "%s"', eventName, listener)
253
+ this.logger.verbose('registered event "%s"', eventName, listener)
276
254
  }
277
255
 
278
256
  private registerUploadEvent(
@@ -283,7 +261,7 @@ export class XMLHttpRequestController {
283
261
  const nextEvents = prevEvents.concat(listener)
284
262
  this.uploadEvents.set(eventName, nextEvents)
285
263
 
286
- this.logger.info('registered upload event "%s"', eventName, listener)
264
+ this.logger.verbose('registered upload event "%s"', eventName, listener)
287
265
  }
288
266
 
289
267
  /**
@@ -301,92 +279,13 @@ export class XMLHttpRequestController {
301
279
  */
302
280
  this[kIsRequestHandled] = true
303
281
 
304
- /**
305
- * Dispatch request upload events for requests with a body.
306
- * @see https://github.com/mswjs/interceptors/issues/573
307
- */
308
- if (this[kFetchRequest]) {
309
- const totalRequestBodyLength = await getBodyByteLength(
310
- this[kFetchRequest]
311
- )
312
-
313
- this.trigger('loadstart', this.request.upload, {
314
- loaded: 0,
315
- total: totalRequestBodyLength,
316
- })
317
- this.trigger('progress', this.request.upload, {
318
- loaded: totalRequestBodyLength,
319
- total: totalRequestBodyLength,
320
- })
321
- this.trigger('load', this.request.upload, {
322
- loaded: totalRequestBodyLength,
323
- total: totalRequestBodyLength,
324
- })
325
-
326
- this.trigger('loadend', this.request.upload, {
327
- loaded: totalRequestBodyLength,
328
- total: totalRequestBodyLength,
329
- })
330
- }
331
-
332
- this.logger.info(
282
+ this.logger.verbose(
333
283
  'responding with a mocked response: %d %s',
334
284
  response.status,
335
285
  response.statusText
336
286
  )
337
287
 
338
- define(this.request, 'status', response.status)
339
- define(this.request, 'statusText', response.statusText)
340
- define(this.request, 'responseURL', this.url.href)
341
-
342
- this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, {
343
- apply: (_, __, args: [name: string]) => {
344
- this.logger.info('getResponseHeader', args[0])
345
-
346
- if (this.request.readyState < this.request.HEADERS_RECEIVED) {
347
- this.logger.info('headers not received yet, returning null')
348
-
349
- // Headers not received yet, nothing to return.
350
- return null
351
- }
352
-
353
- const headerValue = response.headers.get(args[0])
354
- this.logger.info(
355
- 'resolved response header "%s" to',
356
- args[0],
357
- headerValue
358
- )
359
-
360
- return headerValue
361
- },
362
- })
363
-
364
- this.request.getAllResponseHeaders = new Proxy(
365
- this.request.getAllResponseHeaders,
366
- {
367
- apply: () => {
368
- this.logger.info('getAllResponseHeaders')
369
-
370
- if (this.request.readyState < this.request.HEADERS_RECEIVED) {
371
- this.logger.info('headers not received yet, returning empty string')
372
-
373
- // Headers not received yet, nothing to return.
374
- return ''
375
- }
376
-
377
- const headersList = Array.from(response.headers.entries())
378
- const allHeaders = headersList
379
- .map(([headerName, headerValue]) => {
380
- return `${headerName}: ${headerValue}`
381
- })
382
- .join('\r\n')
383
-
384
- this.logger.info('resolved all response headers to', allHeaders)
385
-
386
- return allHeaders
387
- },
388
- }
389
- )
288
+ FetchResponse.setUrl(this.url.href, response)
390
289
 
391
290
  // Update the response getters to resolve against the mocked response.
392
291
  Object.defineProperties(this.request, {
@@ -407,65 +306,278 @@ export class XMLHttpRequestController {
407
306
  },
408
307
  })
409
308
 
410
- const totalResponseBodyLength = await getBodyByteLength(response.clone())
309
+ // 1. Fire a progress event named loadstart at this with 0 and 0.
310
+ this.trigger('loadstart', this.request, { loaded: 0, total: 0 })
411
311
 
412
- this.logger.info('calculated response body length', totalResponseBodyLength)
312
+ // 2. Let requestBodyTransmitted be 0.
313
+ let requestBodyTransmitted = 0
314
+ let uploadComplete = false
413
315
 
414
- this.trigger('loadstart', this.request, {
415
- loaded: 0,
416
- total: totalResponseBodyLength,
417
- })
316
+ if (this[kFetchRequest]) {
317
+ const requestBodyLength = await getBodyByteLength(
318
+ this[kFetchRequest].clone()
319
+ )
418
320
 
419
- this.setReadyState(this.request.HEADERS_RECEIVED)
420
- this.setReadyState(this.request.LOADING)
321
+ // 5. If this’s upload complete flag is unset and this’s upload listener flag is set, then fire a progress event named loadstart at this’s upload object with requestBodyTransmitted and requestBodyLength.
322
+ if (!uploadComplete) {
323
+ this.trigger('loadstart', this.request.upload, {
324
+ loaded: 0,
325
+ total: requestBodyLength,
326
+ })
327
+ }
421
328
 
422
- const finalizeResponse = () => {
423
- this.logger.info('finalizing the mocked response...')
329
+ const processRequestBodyChunkLength = (bytesLength: number) => {
330
+ requestBodyTransmitted += bytesLength
424
331
 
332
+ if (requestBodyTransmitted < requestBodyLength) {
333
+ this.trigger('progress', this.request.upload, {
334
+ loaded: requestBodyTransmitted,
335
+ total: requestBodyLength,
336
+ })
337
+ }
338
+ }
339
+
340
+ const processRequestEndOfBody = () => {
341
+ uploadComplete = true
342
+
343
+ this.trigger('progress', this.request.upload, {
344
+ loaded: requestBodyTransmitted,
345
+ total: requestBodyLength,
346
+ })
347
+ this.trigger('load', this.request.upload, {
348
+ loaded: requestBodyTransmitted,
349
+ total: requestBodyLength,
350
+ })
351
+ this.trigger('loadend', this.request.upload, {
352
+ loaded: requestBodyTransmitted,
353
+ total: requestBodyLength,
354
+ })
355
+ }
356
+
357
+ if (this[kFetchRequest]?.body != null) {
358
+ const reader = this[kFetchRequest].body.getReader()
359
+
360
+ while (true) {
361
+ const { value, done } = await reader.read()
362
+
363
+ if (done) {
364
+ processRequestEndOfBody()
365
+ break
366
+ }
367
+
368
+ processRequestBodyChunkLength(value.byteLength)
369
+ }
370
+ } else {
371
+ processRequestEndOfBody()
372
+ }
373
+ }
374
+
375
+ let timedOut = false
376
+ const responseReadController = new AbortController()
377
+
378
+ const requestErrorSteps = (
379
+ event: keyof XMLHttpRequestEventTargetEventMap
380
+ ) => {
425
381
  this.setReadyState(this.request.DONE)
426
382
 
427
- this.trigger('load', this.request, {
428
- loaded: this.responseBuffer.byteLength,
429
- total: totalResponseBodyLength,
430
- })
383
+ if (!uploadComplete) {
384
+ this.trigger(event, this.request.upload, {
385
+ loaded: 0,
386
+ total: 0,
387
+ })
388
+ this.trigger('loadend', this.request.upload, {
389
+ loaded: 0,
390
+ total: 0,
391
+ })
392
+ }
431
393
 
432
- this.trigger('loadend', this.request, {
433
- loaded: this.responseBuffer.byteLength,
434
- total: totalResponseBodyLength,
435
- })
394
+ this.trigger(event, this.request, { loaded: 0, total: 0 })
395
+ this.trigger('loadend', this.request, { loaded: 0, total: 0 })
436
396
  }
437
397
 
438
- if (response.body) {
439
- this.logger.info('mocked response has body, streaming...')
398
+ const processResponse = async (response: Response) => {
399
+ const handleErrors = () => {
400
+ if (timedOut) {
401
+ requestErrorSteps('timeout')
402
+ } else if (responseReadController.signal.aborted) {
403
+ requestErrorSteps('abort')
404
+ } else if (isResponseError(response)) {
405
+ requestErrorSteps('error')
406
+ }
407
+ }
408
+
409
+ handleErrors()
410
+
411
+ define(this.request, 'status', response.status)
412
+ define(this.request, 'statusText', response.statusText)
413
+
414
+ if (!this.request.responseURL) {
415
+ define(this.request, 'responseURL', response.url)
416
+ }
417
+
418
+ if (isResponseError(response)) {
419
+ return
420
+ }
421
+
422
+ /**
423
+ * @note The response body length is derived ONLY from the "content-length" header.
424
+ * If that response header is not set, the "total" in all progress events must be 0.
425
+ */
426
+ const responseBodyLength = Number(
427
+ response.headers.get('content-length') ?? '0'
428
+ )
429
+
430
+ this.setReadyState(this.request.HEADERS_RECEIVED)
431
+
432
+ let receivedBytes = 0
433
+ let lastReceivedResponseBytesAt = performance.now()
440
434
 
441
- const reader = response.body.getReader()
435
+ const processResponseBodyChunk = (bytesLength: number) => {
436
+ receivedBytes += bytesLength
442
437
 
443
- const readNextResponseBodyChunk = async () => {
444
- const { value, done } = await reader.read()
438
+ const now = performance.now()
439
+ const shouldBuffer =
440
+ now - lastReceivedResponseBytesAt <= 60 &&
441
+ receivedBytes < responseBodyLength
442
+ lastReceivedResponseBytesAt = now
445
443
 
446
- if (done) {
447
- this.logger.info('response body stream done!')
448
- finalizeResponse()
444
+ if (shouldBuffer) {
449
445
  return
450
446
  }
451
447
 
452
- if (value) {
453
- this.logger.info('read response body chunk:', value)
454
- this.responseBuffer = concatArrayBuffer(this.responseBuffer, value)
448
+ if (this.request.readyState === this.request.HEADERS_RECEIVED) {
449
+ this.setReadyState(this.request.LOADING, false)
450
+ }
455
451
 
456
- this.trigger('progress', this.request, {
457
- loaded: this.responseBuffer.byteLength,
458
- total: totalResponseBodyLength,
459
- })
452
+ this.trigger('readystatechange', this.request)
453
+ this.trigger('progress', this.request, {
454
+ loaded: receivedBytes,
455
+ total: responseBodyLength,
456
+ })
457
+ }
458
+
459
+ const processResponseBodyError = () => {
460
+ requestErrorSteps('error')
461
+ }
462
+
463
+ const processResponseEndOfBody = async () => {
464
+ handleErrors()
465
+
466
+ if (isResponseError(response)) {
467
+ return
460
468
  }
461
469
 
462
- readNextResponseBodyChunk()
470
+ // 3. Let transmitted be xhr’s received bytes’s length.
471
+ let transmitted = receivedBytes
472
+
473
+ // 9. Fire an event named readystatechange at xhr.
474
+ this.setReadyState(this.request.DONE)
475
+ // 10. Fire a progress event named load at xhr with transmitted and length.
476
+ this.trigger('load', this.request, {
477
+ loaded: transmitted,
478
+ total: responseBodyLength,
479
+ })
480
+ // 11. Fire a progress event named loadend at xhr with transmitted and length.
481
+ this.trigger('loadend', this.request, {
482
+ loaded: transmitted,
483
+ total: responseBodyLength,
484
+ })
485
+ }
486
+
487
+ // 7. If this’s response’s body is null, then run handle response end-of-body for this and return.
488
+ if (response.body == null) {
489
+ processResponseEndOfBody()
490
+ } else {
491
+ const reader = response.body.getReader()
492
+
493
+ while (true) {
494
+ if (responseReadController.signal.aborted) {
495
+ break
496
+ }
497
+
498
+ try {
499
+ const { value, done } = await reader.read()
500
+
501
+ if (done) {
502
+ processResponseEndOfBody()
503
+ return
504
+ }
505
+
506
+ processResponseBodyChunk(value.byteLength)
507
+ this.responseBuffer = concatArrayBuffer(this.responseBuffer, value)
508
+ } catch {
509
+ processResponseBodyError()
510
+ }
511
+ }
463
512
  }
513
+ }
514
+
515
+ // Redirects are followed as a part of the fetch controller. Since we don't have one,
516
+ // retrieve the final response and then continue with processing it instead of the mocked one.
517
+ const [redirectError, finalResponse] = await until(() => {
518
+ return this.followRedirects(response)
519
+ })
464
520
 
465
- readNextResponseBodyChunk()
466
- } else {
467
- finalizeResponse()
521
+ if (redirectError) {
522
+ return
468
523
  }
524
+
525
+ processResponse(finalResponse)
526
+
527
+ // 12.1, 12.2.
528
+ if (this.request.timeout) {
529
+ setTimeout(() => {
530
+ if (this.request.readyState !== this.request.DONE) {
531
+ timedOut = true
532
+ responseReadController.abort()
533
+ }
534
+ }, this.request.timeout)
535
+ }
536
+
537
+ this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, {
538
+ apply: (_, __, args: [name: string]) => {
539
+ this.logger.verbose('getResponseHeader', args[0])
540
+
541
+ if (this.request.readyState < this.request.HEADERS_RECEIVED) {
542
+ this.logger.verbose('headers not received yet, returning null')
543
+ return null
544
+ }
545
+
546
+ const headerValue = finalResponse.headers.get(args[0])
547
+ this.logger.verbose(
548
+ 'resolved response header "%s" to',
549
+ args[0],
550
+ headerValue
551
+ )
552
+
553
+ return headerValue
554
+ },
555
+ })
556
+
557
+ this.request.getAllResponseHeaders = new Proxy(
558
+ this.request.getAllResponseHeaders,
559
+ {
560
+ apply: () => {
561
+ this.logger.verbose('getAllResponseHeaders')
562
+
563
+ if (this.request.readyState < this.request.HEADERS_RECEIVED) {
564
+ this.logger.verbose('headers not received yet, returning empty string')
565
+ return ''
566
+ }
567
+
568
+ const headersList = Array.from(finalResponse.headers)
569
+ const allHeaders = headersList
570
+ .map(([headerName, headerValue]) => {
571
+ return `${headerName}: ${headerValue}`
572
+ })
573
+ .join('\r\n')
574
+
575
+ this.logger.verbose('resolved all response headers to', allHeaders)
576
+
577
+ return allHeaders
578
+ },
579
+ }
580
+ )
469
581
  }
470
582
 
471
583
  private responseBufferToText(): string {
@@ -473,7 +585,7 @@ export class XMLHttpRequestController {
473
585
  }
474
586
 
475
587
  get response(): unknown {
476
- this.logger.info(
588
+ this.logger.verbose(
477
589
  'getResponse (responseType: %s)',
478
590
  this.request.responseType
479
591
  )
@@ -485,14 +597,14 @@ export class XMLHttpRequestController {
485
597
  switch (this.request.responseType) {
486
598
  case 'json': {
487
599
  const responseJson = parseJson(this.responseBufferToText())
488
- this.logger.info('resolved response JSON', responseJson)
600
+ this.logger.verbose('resolved response JSON', responseJson)
489
601
 
490
602
  return responseJson
491
603
  }
492
604
 
493
605
  case 'arraybuffer': {
494
606
  const arrayBuffer = toArrayBuffer(this.responseBuffer)
495
- this.logger.info('resolved response ArrayBuffer', arrayBuffer)
607
+ this.logger.verbose('resolved response ArrayBuffer', arrayBuffer)
496
608
 
497
609
  return arrayBuffer
498
610
  }
@@ -504,7 +616,7 @@ export class XMLHttpRequestController {
504
616
  type: mimeType,
505
617
  })
506
618
 
507
- this.logger.info(
619
+ this.logger.verbose(
508
620
  'resolved response Blob (mime type: %s)',
509
621
  responseBlob,
510
622
  mimeType
@@ -515,7 +627,7 @@ export class XMLHttpRequestController {
515
627
 
516
628
  default: {
517
629
  const responseText = this.responseBufferToText()
518
- this.logger.info(
630
+ this.logger.verbose(
519
631
  'resolving "%s" response type as text',
520
632
  this.request.responseType,
521
633
  responseText
@@ -545,7 +657,7 @@ export class XMLHttpRequestController {
545
657
  }
546
658
 
547
659
  const responseText = this.responseBufferToText()
548
- this.logger.info('getResponseText: "%s"', responseText)
660
+ this.logger.verbose('getResponseText: "%s"', responseText)
549
661
 
550
662
  return responseText
551
663
  }
@@ -580,13 +692,55 @@ export class XMLHttpRequestController {
580
692
  return null
581
693
  }
582
694
 
695
+ private async followRedirects(response: Response): Promise<Response> {
696
+ const redirectLocation = response.headers.get('location')
697
+
698
+ if (
699
+ !redirectLocation ||
700
+ !FetchResponse.isRedirectResponse(response.status)
701
+ ) {
702
+ return response
703
+ }
704
+
705
+ this.redirectCount++
706
+
707
+ if (this.redirectCount > MAX_REDIRECTS) {
708
+ throw new Error('Too many redirects')
709
+ }
710
+
711
+ const redirectUrl = new URL(redirectLocation, location.href)
712
+ const redirectMethod = FetchResponse.isResponseWithBody(response.status)
713
+ ? this.method
714
+ : 'GET'
715
+
716
+ const redirectResponse = await new Promise<Response>((resolve, reject) => {
717
+ const request = new XMLHttpRequest()
718
+ request.responseType = this.request.responseType
719
+
720
+ request.addEventListener('load', () => {
721
+ this.url = new URL(request.responseURL)
722
+ resolve(createResponse(request, request.response))
723
+ })
724
+
725
+ request.addEventListener('error', () => {
726
+ this.errorWith()
727
+ reject(new Error('Redirect request failed'))
728
+ })
729
+
730
+ request.open(redirectMethod, redirectUrl.href)
731
+ request.send()
732
+ })
733
+
734
+ return this.followRedirects(redirectResponse)
735
+ }
736
+
583
737
  public errorWith(error?: Error): void {
584
738
  /**
585
739
  * @note Mark this request as handled even if it received a mock error.
586
740
  * This prevents the controller from trying to perform this request as-is.
587
741
  */
588
742
  this[kIsRequestHandled] = true
589
- this.logger.info('responding with an error')
743
+ this.logger.verbose('responding with an error')
590
744
 
591
745
  this.setReadyState(this.request.DONE)
592
746
  this.trigger('error', this.request)
@@ -596,24 +750,31 @@ export class XMLHttpRequestController {
596
750
  /**
597
751
  * Transitions this request's `readyState` to the given one.
598
752
  */
599
- private setReadyState(nextReadyState: number): void {
600
- this.logger.info(
753
+ private setReadyState(
754
+ nextReadyState: number,
755
+ triggerReadyStateChangeEvent = true
756
+ ): void {
757
+ this.logger.verbose(
601
758
  'setReadyState: %d -> %d',
602
759
  this.request.readyState,
603
760
  nextReadyState
604
761
  )
605
762
 
606
763
  if (this.request.readyState === nextReadyState) {
607
- this.logger.info('ready state identical, skipping transition...')
764
+ this.logger.verbose('ready state identical, skipping transition...')
608
765
  return
609
766
  }
610
767
 
611
768
  define(this.request, 'readyState', nextReadyState)
612
769
 
613
- this.logger.info('set readyState to: %d', nextReadyState)
770
+ this.logger.verbose('set readyState to: %d', nextReadyState)
771
+
772
+ if (!triggerReadyStateChangeEvent) {
773
+ return
774
+ }
614
775
 
615
776
  if (nextReadyState !== this.request.UNSENT) {
616
- this.logger.info('triggering "readystatechange" event...')
777
+ this.logger.verbose('triggering "readystatechange" event...')
617
778
 
618
779
  this.trigger('readystatechange', this.request)
619
780
  }
@@ -634,11 +795,11 @@ export class XMLHttpRequestController {
634
795
  const callback = (target as XMLHttpRequest)[`on${eventName}`]
635
796
  const event = createEvent(target, eventName, options)
636
797
 
637
- this.logger.info('trigger "%s"', eventName, options || '')
798
+ this.logger.verbose('trigger "%s"', eventName, options || '')
638
799
 
639
800
  // Invoke direct callbacks.
640
801
  if (typeof callback === 'function') {
641
- this.logger.info('found a direct "%s" callback, calling...', eventName)
802
+ this.logger.verbose('found a direct "%s" callback, calling...', eventName)
642
803
  callback.call(target as XMLHttpRequest, event)
643
804
  }
644
805
 
@@ -648,7 +809,7 @@ export class XMLHttpRequestController {
648
809
 
649
810
  for (const [registeredEventName, listeners] of events) {
650
811
  if (registeredEventName === eventName) {
651
- this.logger.info(
812
+ this.logger.verbose(
652
813
  'found %d listener(s) for "%s" event, calling...',
653
814
  listeners.length,
654
815
  eventName
@@ -665,7 +826,7 @@ export class XMLHttpRequestController {
665
826
  private toFetchApiRequest(
666
827
  body: XMLHttpRequestBodyInit | Document | null | undefined
667
828
  ): Request {
668
- this.logger.info('converting request to a Fetch API Request...')
829
+ this.logger.verbose('converting request to a Fetch API Request...')
669
830
 
670
831
  // If the `Document` is used as the body of this XMLHttpRequest,
671
832
  // set its inner text as the Fetch API Request body.
@@ -679,9 +840,7 @@ export class XMLHttpRequestController {
679
840
  * @see https://xhr.spec.whatwg.org/#cross-origin-credentials
680
841
  */
681
842
  credentials: this.request.withCredentials ? 'include' : 'same-origin',
682
- body: ['GET', 'HEAD'].includes(this.method.toUpperCase())
683
- ? null
684
- : resolvedBody,
843
+ body: resolvedBody,
685
844
  })
686
845
 
687
846
  const proxyHeaders = createProxy(fetchRequest.headers, {
@@ -710,9 +869,9 @@ export class XMLHttpRequestController {
710
869
  },
711
870
  })
712
871
  define(fetchRequest, 'headers', proxyHeaders)
713
- setRawRequest(fetchRequest, this.request)
872
+ // setRawRequest(fetchRequest, this.request)
714
873
 
715
- this.logger.info('converted request to a Fetch API Request!', fetchRequest)
874
+ this.logger.verbose('converted request to a Fetch API Request!', fetchRequest)
716
875
 
717
876
  return fetchRequest
718
877
  }