@mswjs/interceptors 0.16.6 → 0.17.2

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 (43) hide show
  1. package/README.md +181 -57
  2. package/lib/InteractiveIsomorphicRequest.d.ts +7 -0
  3. package/lib/InteractiveIsomorphicRequest.js +37 -0
  4. package/lib/InteractiveIsomorphicRequest.js.map +1 -0
  5. package/lib/IsomorphicRequest.d.ts +24 -0
  6. package/lib/IsomorphicRequest.js +107 -0
  7. package/lib/IsomorphicRequest.js.map +1 -0
  8. package/lib/RemoteHttpInterceptor.d.ts +1 -1
  9. package/lib/RemoteHttpInterceptor.js +12 -8
  10. package/lib/RemoteHttpInterceptor.js.map +1 -1
  11. package/lib/glossary.d.ts +2 -17
  12. package/lib/glossary.js.map +1 -1
  13. package/lib/index.d.ts +3 -0
  14. package/lib/index.js +6 -1
  15. package/lib/index.js.map +1 -1
  16. package/lib/interceptors/ClientRequest/NodeClientRequest.js +9 -27
  17. package/lib/interceptors/ClientRequest/NodeClientRequest.js.map +1 -1
  18. package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js.map +1 -1
  19. package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.d.ts +1 -2
  20. package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js +19 -27
  21. package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js.map +1 -1
  22. package/lib/interceptors/XMLHttpRequest/index.d.ts +2 -1
  23. package/lib/interceptors/XMLHttpRequest/index.js.map +1 -1
  24. package/lib/interceptors/fetch/index.js +22 -25
  25. package/lib/interceptors/fetch/index.js.map +1 -1
  26. package/lib/utils/bufferUtils.d.ts +3 -0
  27. package/lib/utils/bufferUtils.js +20 -0
  28. package/lib/utils/bufferUtils.js.map +1 -0
  29. package/package.json +3 -2
  30. package/src/InteractiveIsomorphicRequest.ts +24 -0
  31. package/src/IsomorphicRequest.test.ts +106 -0
  32. package/src/IsomorphicRequest.ts +86 -0
  33. package/src/RemoteHttpInterceptor.ts +18 -18
  34. package/src/glossary.ts +2 -19
  35. package/src/index.ts +3 -0
  36. package/src/interceptors/ClientRequest/NodeClientRequest.test.ts +2 -8
  37. package/src/interceptors/ClientRequest/NodeClientRequest.ts +14 -35
  38. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +4 -4
  39. package/src/interceptors/XMLHttpRequest/XMLHttpRequestOverride.ts +21 -23
  40. package/src/interceptors/XMLHttpRequest/index.ts +2 -5
  41. package/src/interceptors/fetch/index.ts +28 -19
  42. package/src/utils/bufferUtils.test.ts +20 -0
  43. package/src/utils/bufferUtils.ts +19 -0
@@ -0,0 +1,106 @@
1
+ import { Headers } from 'headers-polyfill/lib'
2
+ import { IsomorphicRequest } from './IsomorphicRequest'
3
+ import { encodeBuffer } from './utils/bufferUtils'
4
+
5
+ const url = new URL('http://dummy')
6
+ const body = encodeBuffer(JSON.stringify({ hello: 'world' }))
7
+
8
+ it('reads request body as json', async () => {
9
+ const request = new IsomorphicRequest(url, { body })
10
+
11
+ expect(request.bodyUsed).toBe(false)
12
+ expect(await request.json()).toEqual({ hello: 'world' })
13
+ expect(request.bodyUsed).toBe(true)
14
+ expect(() => request.json()).rejects.toThrow(
15
+ 'Failed to execute "json" on "IsomorphicRequest": body buffer already read'
16
+ )
17
+ })
18
+
19
+ it('reads request body as text', async () => {
20
+ const request = new IsomorphicRequest(url, { body })
21
+
22
+ expect(request.bodyUsed).toBe(false)
23
+ expect(await request.text()).toEqual(JSON.stringify({ hello: 'world' }))
24
+ expect(request.bodyUsed).toBe(true)
25
+ expect(() => request.text()).rejects.toThrow(
26
+ 'Failed to execute "text" on "IsomorphicRequest": body buffer already read'
27
+ )
28
+ })
29
+
30
+ it('reads request body as array buffer', async () => {
31
+ const request = new IsomorphicRequest(url, { body })
32
+
33
+ expect(request.bodyUsed).toBe(false)
34
+ expect(await request.arrayBuffer()).toEqual(encodeBuffer(`{"hello":"world"}`))
35
+ expect(request.bodyUsed).toBe(true)
36
+ expect(() => request.arrayBuffer()).rejects.toThrow(
37
+ 'Failed to execute "arrayBuffer" on "IsomorphicRequest": body buffer already read'
38
+ )
39
+ })
40
+
41
+ it('returns default method', () => {
42
+ const request = new IsomorphicRequest(url, { body })
43
+ expect(request.method).toEqual('GET')
44
+ })
45
+
46
+ it('returns given method', () => {
47
+ const request = new IsomorphicRequest(url, { body, method: 'POST' })
48
+ expect(request.method).toEqual('POST')
49
+ })
50
+
51
+ it('returns given credentials', () => {
52
+ const request = new IsomorphicRequest(url, { body, credentials: 'include' })
53
+ expect(request.credentials).toEqual('include')
54
+ })
55
+
56
+ it('returns default credentials', () => {
57
+ const request = new IsomorphicRequest(url, { body })
58
+ expect(request.credentials).toEqual('same-origin')
59
+ })
60
+
61
+ it('returns empty headers if not provided', () => {
62
+ const request = new IsomorphicRequest(url, { body })
63
+ expect(request.headers).toEqual(new Headers())
64
+ })
65
+
66
+ it('returns given headers', () => {
67
+ const request = new IsomorphicRequest(url, {
68
+ body,
69
+ headers: { 'Content-Type': 'application/json' },
70
+ })
71
+ expect(request.headers).toEqual(
72
+ new Headers({ 'Content-Type': 'application/json' })
73
+ )
74
+ })
75
+
76
+ it('returns a copy of isomorphic request instance', () => {
77
+ const request = new IsomorphicRequest(url, {
78
+ body,
79
+ headers: { foo: 'bar' },
80
+ })
81
+ const derivedRequest = new IsomorphicRequest(request)
82
+
83
+ expect(request.id).toBe(derivedRequest.id)
84
+ expect(request.url.href).toBe(derivedRequest.url.href)
85
+ expect(request['_body']).toEqual(derivedRequest['_body'])
86
+ expect(request.headers).toEqual(derivedRequest.headers)
87
+ expect(request.method).toBe(derivedRequest.method)
88
+ expect(request.credentials).toBe(derivedRequest.credentials)
89
+ expect(request.bodyUsed).toBe(false)
90
+ })
91
+
92
+ it('clones current isomorphic request instance', () => {
93
+ const request = new IsomorphicRequest(url, {
94
+ body,
95
+ headers: { foo: 'bar' },
96
+ })
97
+ const clonedRequest = request.clone()
98
+
99
+ expect(clonedRequest.id).toBe(request.id)
100
+ expect(clonedRequest.method).toBe(request.method)
101
+ expect(clonedRequest.url.href).toBe(request.url.href)
102
+ expect(clonedRequest.headers).toEqual(request.headers)
103
+ expect(clonedRequest.credentials).toBe(request.credentials)
104
+ expect(clonedRequest['_body']).toEqual(request['_body'])
105
+ expect(clonedRequest.bodyUsed).toBe(false)
106
+ })
@@ -0,0 +1,86 @@
1
+ import { Headers } from 'headers-polyfill/lib'
2
+ import { invariant } from 'outvariant'
3
+ import { decodeBuffer } from './utils/bufferUtils'
4
+ import { uuidv4 } from './utils/uuid'
5
+
6
+ export interface RequestInit {
7
+ method?: string
8
+ headers?: Record<string, string | string[]> | Headers
9
+ credentials?: RequestCredentials
10
+ body?: ArrayBuffer
11
+ }
12
+
13
+ export class IsomorphicRequest {
14
+ public id: string
15
+ public readonly url: URL
16
+ public readonly method: string
17
+ public readonly headers: Headers
18
+ public readonly credentials: RequestCredentials
19
+
20
+ private readonly _body: ArrayBuffer
21
+ private _bodyUsed: boolean
22
+
23
+ constructor(url: URL)
24
+ constructor(url: URL, init: RequestInit)
25
+ constructor(request: IsomorphicRequest)
26
+ constructor(input: IsomorphicRequest | URL, init: RequestInit = {}) {
27
+ const defaultBody = new ArrayBuffer(0)
28
+ this._bodyUsed = false
29
+
30
+ if (input instanceof IsomorphicRequest) {
31
+ this.id = input.id
32
+ this.url = input.url
33
+ this.method = input.method
34
+ this.headers = input.headers
35
+ this.credentials = input.credentials
36
+ this._body = input._body || defaultBody
37
+ return
38
+ }
39
+
40
+ this.id = uuidv4()
41
+ this.url = input
42
+ this.method = init.method || 'GET'
43
+ this.headers = new Headers(init.headers)
44
+ this.credentials = init.credentials || 'same-origin'
45
+ this._body = init.body || defaultBody
46
+ }
47
+
48
+ public get bodyUsed(): boolean {
49
+ return this._bodyUsed
50
+ }
51
+
52
+ public async text(): Promise<string> {
53
+ invariant(
54
+ !this.bodyUsed,
55
+ 'Failed to execute "text" on "IsomorphicRequest": body buffer already read'
56
+ )
57
+
58
+ this._bodyUsed = true
59
+ return decodeBuffer(this._body)
60
+ }
61
+
62
+ public async json<T = any>(): Promise<T> {
63
+ invariant(
64
+ !this.bodyUsed,
65
+ 'Failed to execute "json" on "IsomorphicRequest": body buffer already read'
66
+ )
67
+
68
+ this._bodyUsed = true
69
+ const text = decodeBuffer(this._body)
70
+ return JSON.parse(text)
71
+ }
72
+
73
+ public async arrayBuffer(): Promise<ArrayBuffer> {
74
+ invariant(
75
+ !this.bodyUsed,
76
+ 'Failed to execute "arrayBuffer" on "IsomorphicRequest": body buffer already read'
77
+ )
78
+
79
+ this._bodyUsed = true
80
+ return this._body
81
+ }
82
+
83
+ public clone(): IsomorphicRequest {
84
+ return new IsomorphicRequest(this)
85
+ }
86
+ }
@@ -1,16 +1,14 @@
1
1
  import { ChildProcess } from 'child_process'
2
2
  import { Headers } from 'headers-polyfill'
3
- import type {
4
- HttpRequestEventMap,
5
- InteractiveIsomorphicRequest,
6
- IsomorphicRequest,
7
- } from './glossary'
3
+ import { HttpRequestEventMap } from './glossary'
8
4
  import { Interceptor } from './Interceptor'
9
5
  import { BatchInterceptor } from './BatchInterceptor'
10
6
  import { ClientRequestInterceptor } from './interceptors/ClientRequest'
11
7
  import { XMLHttpRequestInterceptor } from './interceptors/XMLHttpRequest'
12
- import { createLazyCallback } from './utils/createLazyCallback'
13
8
  import { toIsoResponse } from './utils/toIsoResponse'
9
+ import { IsomorphicRequest } from './IsomorphicRequest'
10
+ import { bufferFrom } from './interceptors/XMLHttpRequest/utils/bufferFrom'
11
+ import { InteractiveIsomorphicRequest } from './InteractiveIsomorphicRequest'
14
12
 
15
13
  export class RemoteHttpInterceptor extends BatchInterceptor<
16
14
  [ClientRequestInterceptor, XMLHttpRequestInterceptor]
@@ -59,7 +57,7 @@ export class RemoteHttpInterceptor extends BatchInterceptor<
59
57
  }
60
58
  })
61
59
 
62
- // Listen for the mocked resopnse message from the parent.
60
+ // Listen for the mocked response message from the parent.
63
61
  this.log(
64
62
  'add "message" listener to the parent process',
65
63
  handleParentMessage
@@ -118,17 +116,19 @@ export class RemoteHttpResolver extends Interceptor<HttpRequestEventMap> {
118
116
  return
119
117
  }
120
118
 
121
- const isomorphicRequest: IsomorphicRequest = JSON.parse(
122
- serializedRequest,
123
- requestReviver
124
- )
119
+ const requestJson = JSON.parse(serializedRequest, requestReviver)
120
+ log('parsed intercepted request', requestJson)
125
121
 
126
- log('parsed intercepted request', isomorphicRequest)
122
+ const body = bufferFrom(requestJson.body)
127
123
 
128
- const interactiveIsomorphicRequest: InteractiveIsomorphicRequest = {
129
- ...isomorphicRequest,
130
- respondWith: createLazyCallback(),
131
- }
124
+ const isomorphicRequest = new IsomorphicRequest(requestJson.url, {
125
+ ...requestJson,
126
+ body: body.buffer,
127
+ })
128
+
129
+ const interactiveIsomorphicRequest = new InteractiveIsomorphicRequest(
130
+ isomorphicRequest
131
+ )
132
132
 
133
133
  this.emitter.emit('request', interactiveIsomorphicRequest)
134
134
  await this.emitter.untilIdle('request', ({ args: [request] }) => {
@@ -143,14 +143,14 @@ export class RemoteHttpResolver extends Interceptor<HttpRequestEventMap> {
143
143
  const serializedResponse = JSON.stringify(mockedResponse)
144
144
 
145
145
  this.process.send(
146
- `response:${isomorphicRequest.id}:${serializedResponse}`,
146
+ `response:${requestJson.id}:${serializedResponse}`,
147
147
  (error) => {
148
148
  if (error) {
149
149
  return
150
150
  }
151
151
 
152
152
  if (mockedResponse) {
153
- // Emit an optimistinc "response" event at this point,
153
+ // Emit an optimistic "response" event at this point,
154
154
  // not to rely on the back-and-forth signaling for the sake of the event.
155
155
  this.emitter.emit(
156
156
  'response',
package/src/glossary.ts CHANGED
@@ -1,28 +1,11 @@
1
1
  import type { HeadersObject, Headers } from 'headers-polyfill'
2
- import type { LazyCallback } from './utils/createLazyCallback'
2
+ import type { InteractiveIsomorphicRequest } from './InteractiveIsomorphicRequest'
3
+ import type { IsomorphicRequest } from './IsomorphicRequest'
3
4
 
4
5
  export const IS_PATCHED_MODULE: unique symbol = Symbol('isPatchedModule')
5
6
 
6
7
  export type RequestCredentials = 'omit' | 'include' | 'same-origin'
7
8
 
8
- export interface IsomorphicRequest {
9
- id: string
10
- url: URL
11
- method: string
12
- headers: Headers
13
- /**
14
- * The value of the request client's "credentials" option
15
- * or a compatible alternative (i.e. `withCredentials` for `XMLHttpRequest`).
16
- * Always equals to "omit" in Node.js.
17
- */
18
- credentials: RequestCredentials
19
- body?: string
20
- }
21
-
22
- export interface InteractiveIsomorphicRequest extends IsomorphicRequest {
23
- respondWith: LazyCallback<(mockedResponse: MockedResponse) => void>
24
- }
25
-
26
9
  export interface IsomorphicResponse {
27
10
  status: number
28
11
  statusText: string
package/src/index.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  export * from './glossary'
2
2
  export * from './Interceptor'
3
3
  export * from './BatchInterceptor'
4
+ export * from './IsomorphicRequest'
5
+ export * from './InteractiveIsomorphicRequest'
4
6
 
5
7
  /* Utils */
6
8
  export { getCleanUrl } from './utils/getCleanUrl'
9
+ export { encodeBuffer, decodeBuffer } from './utils/bufferUtils'
@@ -139,10 +139,7 @@ test('emits the ENOTFOUND error connecting to a non-existing hostname given no m
139
139
  const emitter = new AsyncEventEmitter<HttpRequestEventMap>()
140
140
  const request = new NodeClientRequest(
141
141
  normalizeClientRequestArgs('http:', 'http://non-existing-url.com'),
142
- {
143
- emitter,
144
- log,
145
- }
142
+ { emitter, log }
146
143
  )
147
144
 
148
145
  request.on('error', (error: NodeJS.ErrnoException) => {
@@ -181,10 +178,7 @@ test('does not emit ENOTFOUND error connecting to an inactive server given mocke
181
178
  const handleError = jest.fn()
182
179
  const request = new NodeClientRequest(
183
180
  normalizeClientRequestArgs('http:', 'http://non-existing-url.com'),
184
- {
185
- emitter,
186
- log,
187
- }
181
+ { emitter, log }
188
182
  )
189
183
 
190
184
  emitter.on('request', async (request) => {
@@ -3,12 +3,7 @@ import type { RequestOptions } from 'http'
3
3
  import { ClientRequest, IncomingMessage } from 'http'
4
4
  import { until } from '@open-draft/until'
5
5
  import { Headers, objectToHeaders } from 'headers-polyfill/lib'
6
- import type {
7
- InteractiveIsomorphicRequest,
8
- IsomorphicRequest,
9
- MockedResponse,
10
- } from '../../glossary'
11
- import { uuidv4 } from '../../utils/uuid'
6
+ import { MockedResponse } from '../../glossary'
12
7
  import type { ClientRequestEmitter } from '.'
13
8
  import { concatChunkToBuffer } from './utils/concatChunkToBuffer'
14
9
  import {
@@ -21,12 +16,12 @@ import { getIncomingMessageBody } from './utils/getIncomingMessageBody'
21
16
  import { bodyBufferToString } from './utils/bodyBufferToString'
22
17
  import {
23
18
  ClientRequestWriteArgs,
24
- ClientRequestWriteCallback,
25
19
  normalizeClientRequestWriteArgs,
26
20
  } from './utils/normalizeClientRequestWriteArgs'
27
21
  import { cloneIncomingMessage } from './utils/cloneIncomingMessage'
28
- import { createLazyCallback } from '../../utils/createLazyCallback'
29
- import { invariant } from 'outvariant'
22
+ import { IsomorphicRequest } from '../../IsomorphicRequest'
23
+ import { InteractiveIsomorphicRequest } from '../../InteractiveIsomorphicRequest'
24
+ import { getArrayBuffer } from '../../utils/bufferUtils'
30
25
 
31
26
  export type Protocol = 'http' | 'https'
32
27
 
@@ -116,20 +111,9 @@ export class NodeClientRequest extends ClientRequest {
116
111
 
117
112
  const requestBody = this.getRequestBody(chunk)
118
113
  const isomorphicRequest = this.toIsomorphicRequest(requestBody)
119
- const interactiveIsomorphicRequest: InteractiveIsomorphicRequest = {
120
- ...isomorphicRequest,
121
- respondWith: createLazyCallback({
122
- maxCalls: 1,
123
- maxCallsCallback() {
124
- invariant(
125
- false,
126
- 'Failed to respond to "%s %s" request: the "request" event has already been responded to.',
127
- isomorphicRequest.method,
128
- isomorphicRequest.url.href
129
- )
130
- },
131
- }),
132
- }
114
+ const interactiveIsomorphicRequest = new InteractiveIsomorphicRequest(
115
+ isomorphicRequest
116
+ )
133
117
 
134
118
  // Notify the interceptor about the request.
135
119
  // This will call any "request" listeners the users have.
@@ -377,7 +361,7 @@ export class NodeClientRequest extends ClientRequest {
377
361
  this.agent.destroy()
378
362
  }
379
363
 
380
- private getRequestBody(chunk: ClientRequestEndChunk | null): string {
364
+ private getRequestBody(chunk: ClientRequestEndChunk | null): ArrayBuffer {
381
365
  const writtenRequestBody = bodyBufferToString(
382
366
  Buffer.concat(this.requestBody)
383
367
  )
@@ -388,16 +372,13 @@ export class NodeClientRequest extends ClientRequest {
388
372
  this.requestBody = concatChunkToBuffer(chunk, this.requestBody)
389
373
  }
390
374
 
391
- const resolvedRequestBody = bodyBufferToString(
392
- Buffer.concat(this.requestBody)
393
- )
394
-
375
+ const resolvedRequestBody = Buffer.concat(this.requestBody)
395
376
  this.log('resolved request body:', resolvedRequestBody)
396
377
 
397
- return resolvedRequestBody
378
+ return getArrayBuffer(resolvedRequestBody)
398
379
  }
399
380
 
400
- private toIsomorphicRequest(body: string): IsomorphicRequest {
381
+ private toIsomorphicRequest(body: ArrayBuffer): IsomorphicRequest {
401
382
  this.log('creating isomorphic request object...')
402
383
 
403
384
  const outgoingHeaders = this.getHeaders()
@@ -412,14 +393,12 @@ export class NodeClientRequest extends ClientRequest {
412
393
  headers.set(headerName.toLowerCase(), headerValue.toString())
413
394
  }
414
395
 
415
- const isomorphicRequest: IsomorphicRequest = {
416
- id: uuidv4(),
417
- url: this.url,
396
+ const isomorphicRequest = new IsomorphicRequest(this.url, {
397
+ body,
418
398
  method: this.options.method || 'GET',
419
399
  credentials: 'same-origin',
420
400
  headers,
421
- body,
422
- }
401
+ })
423
402
 
424
403
  this.log('successfully created isomorphic request!', isomorphicRequest)
425
404
  return isomorphicRequest
@@ -25,16 +25,16 @@ export function getIncomingMessageBody(
25
25
  stream.setEncoding(encoding)
26
26
  log('using encoding:', encoding)
27
27
 
28
- let body = '';
28
+ let body = ''
29
29
 
30
30
  stream.on('data', (responseBody) => {
31
31
  log('response body read:', responseBody)
32
- body += responseBody;
32
+ body += responseBody
33
33
  })
34
34
 
35
35
  stream.once('end', () => {
36
- log('response body end');
37
- resolve(body);
36
+ log('response body end')
37
+ resolve(body)
38
38
  })
39
39
 
40
40
  stream.once('error', (error) => {
@@ -11,14 +11,14 @@ import {
11
11
  headersToString,
12
12
  } from 'headers-polyfill'
13
13
  import { DOMParser } from '@xmldom/xmldom'
14
- import { InteractiveIsomorphicRequest, IsomorphicRequest } from '../../glossary'
15
14
  import { parseJson } from '../../utils/parseJson'
16
15
  import { toIsoResponse } from '../../utils/toIsoResponse'
17
- import { uuidv4 } from '../../utils/uuid'
18
16
  import { bufferFrom } from './utils/bufferFrom'
19
17
  import { createEvent } from './utils/createEvent'
20
18
  import type { XMLHttpRequestEmitter } from '.'
21
- import { createLazyCallback } from '../../utils/createLazyCallback'
19
+ import { IsomorphicRequest } from '../../IsomorphicRequest'
20
+ import { encodeBuffer } from '../../utils/bufferUtils'
21
+ import { InteractiveIsomorphicRequest } from '../../InteractiveIsomorphicRequest'
22
22
 
23
23
  type XMLHttpRequestEventHandler = (
24
24
  this: XMLHttpRequest,
@@ -84,7 +84,6 @@ export const createXMLHttpRequestOverride = (
84
84
  public statusText: string
85
85
  public user?: string
86
86
  public password?: string
87
- public data: string
88
87
  public async?: boolean
89
88
  public response: any
90
89
  public responseText: string
@@ -132,7 +131,6 @@ export const createXMLHttpRequestOverride = (
132
131
  this.withCredentials = false
133
132
  this.status = 200
134
133
  this.statusText = 'OK'
135
- this.data = ''
136
134
  this.response = ''
137
135
  this.responseType = 'text'
138
136
  this.responseText = ''
@@ -154,7 +152,7 @@ export const createXMLHttpRequestOverride = (
154
152
  this.readyState = nextState
155
153
 
156
154
  if (nextState !== this.UNSENT) {
157
- this.log('triggerring readystate change...')
155
+ this.log('triggering readystate change...')
158
156
  this.trigger('readystatechange')
159
157
  }
160
158
  }
@@ -195,7 +193,6 @@ export const createXMLHttpRequestOverride = (
195
193
  this.setReadyState(this.UNSENT)
196
194
  this.status = 200
197
195
  this.statusText = 'OK'
198
- this.data = ''
199
196
  this.response = null as any
200
197
  this.responseText = null as any
201
198
  this.responseXML = null as any
@@ -229,10 +226,14 @@ export const createXMLHttpRequestOverride = (
229
226
  }
230
227
  }
231
228
 
232
- public send(data?: string) {
229
+ public send(data?: string | ArrayBuffer) {
233
230
  this.log('send %s %s', this.method, this.url)
234
-
235
- this.data = data || ''
231
+ let buffer: ArrayBuffer
232
+ if (typeof data === 'string') {
233
+ buffer = encodeBuffer(data)
234
+ } else {
235
+ buffer = data || new ArrayBuffer(0)
236
+ }
236
237
 
237
238
  let url: URL
238
239
 
@@ -248,19 +249,16 @@ export const createXMLHttpRequestOverride = (
248
249
  this.log('request headers', this._requestHeaders)
249
250
 
250
251
  // Create an intercepted request instance exposed to the request intercepting middleware.
251
- const isomorphicRequest: IsomorphicRequest = {
252
- id: uuidv4(),
253
- url,
252
+ const isomorphicRequest = new IsomorphicRequest(url, {
253
+ body: buffer,
254
254
  method: this.method,
255
255
  headers: this._requestHeaders,
256
256
  credentials: this.withCredentials ? 'include' : 'omit',
257
- body: this.data,
258
- }
257
+ })
259
258
 
260
- const interactiveIsomorphicRequest: InteractiveIsomorphicRequest = {
261
- ...isomorphicRequest,
262
- respondWith: createLazyCallback(),
263
- }
259
+ const interactiveIsomorphicRequest = new InteractiveIsomorphicRequest(
260
+ isomorphicRequest
261
+ )
264
262
 
265
263
  this.log(
266
264
  'emitting the "request" event for %d listener(s)...',
@@ -331,8 +329,8 @@ export const createXMLHttpRequestOverride = (
331
329
  if (mockedResponse.body && this.response) {
332
330
  this.setReadyState(this.LOADING)
333
331
 
334
- // Presense of the mocked response implies a response body (not null).
335
- // Presense of the coerced `this.response` implies the mocked body is valid.
332
+ // Presence of the mocked response implies a response body (not null).
333
+ // Presence of the coerced `this.response` implies the mocked body is valid.
336
334
  const bodyBuffer = bufferFrom(mockedResponse.body)
337
335
 
338
336
  // Trigger a progress event based on the mocked response body.
@@ -428,8 +426,8 @@ export const createXMLHttpRequestOverride = (
428
426
  originalRequest.timeout = this.timeout
429
427
  }
430
428
 
431
- this.log('send', this.data)
432
- originalRequest.send(this.data)
429
+ this.log('send', data)
430
+ originalRequest.send(data)
433
431
  }
434
432
  })
435
433
  }
@@ -1,9 +1,6 @@
1
1
  import { invariant } from 'outvariant'
2
- import {
3
- HttpRequestEventMap,
4
- InteractiveIsomorphicRequest,
5
- IS_PATCHED_MODULE,
6
- } from '../../glossary'
2
+ import { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'
3
+ import { InteractiveIsomorphicRequest } from '../../InteractiveIsomorphicRequest'
7
4
  import { Interceptor } from '../../Interceptor'
8
5
  import { AsyncEventEmitter } from '../../utils/AsyncEventEmitter'
9
6
  import { createXMLHttpRequestOverride } from './XMLHttpRequestOverride'