0
# XMLHttpRequest Mocking
1
2
Low-level XMLHttpRequest replacement providing complete control over the request/response lifecycle, response types, and progress events. This gives you fine-grained control over every aspect of HTTP request simulation.
3
4
## Capabilities
5
6
### Fake XHR Activation
7
8
Enable fake XMLHttpRequest globally or for specific scopes.
9
10
```javascript { .api }
11
/**
12
* @typedef {Object} FakeXHRModule
13
* @property {XHRUtilities} xhr - XHR utilities
14
* @property {Function} FakeXMLHttpRequest - FakeXMLHttpRequest constructor
15
* @property {Function} useFakeXMLHttpRequest - Function that returns FakeXMLHttpRequest constructor
16
*/
17
18
/**
19
* Replace global XMLHttpRequest with fake implementation
20
* @returns {Function} FakeXMLHttpRequest constructor
21
*/
22
function useFakeXMLHttpRequest() {
23
// Implementation
24
}
25
26
/**
27
* Create fake XMLHttpRequest for specific global scope
28
* @param {Object} globalScope - Global object (window in browser, global in Node.js)
29
* @returns {FakeXHRModule} Object with xhr utilities and FakeXMLHttpRequest
30
*/
31
function fakeXMLHttpRequestFor(globalScope) {
32
// Implementation
33
}
34
```
35
36
**Usage Example:**
37
38
```javascript
39
const nise = require("nise");
40
41
// Replace global XMLHttpRequest
42
const FakeXHR = nise.fakeXhr.useFakeXMLHttpRequest();
43
44
// Now all XMLHttpRequest usage in your code uses the fake
45
const xhr = new XMLHttpRequest(); // Actually creates FakeXMLHttpRequest
46
47
// Restore original later
48
FakeXHR.restore();
49
```
50
51
### FakeXMLHttpRequest Constructor
52
53
Create individual fake XMLHttpRequest instances.
54
55
```javascript { .api }
56
/**
57
* @typedef {Object} FakeXHRConfig
58
* @property {function(string): void} [logger] - Custom logging function
59
* @property {boolean} [useImmediateExceptions] - Throw errors immediately vs on next tick
60
* @property {function(Function, number): *} [setTimeout] - Custom setTimeout function
61
*/
62
63
/**
64
* Create a new fake XMLHttpRequest instance
65
* @param {FakeXHRConfig} [config] - Optional configuration
66
*/
67
function FakeXMLHttpRequest(config) {
68
// Implementation
69
}
70
```
71
72
### Standard XMLHttpRequest Interface
73
74
Complete XMLHttpRequest API implementation.
75
76
```javascript { .api }
77
/**
78
* Initialize a request
79
* @param {string} method - HTTP method
80
* @param {string} url - Request URL
81
* @param {boolean} [async] - Async flag (default: true)
82
* @param {string} [username] - Optional username for authentication
83
* @param {string} [password] - Optional password for authentication
84
* @returns {void}
85
*/
86
open(method, url, async, username, password) {
87
// Implementation
88
}
89
90
/**
91
* Send the request
92
* @param {string|FormData|ArrayBuffer} [data] - Optional request body data
93
* @returns {void}
94
*/
95
send(data) {
96
// Implementation
97
}
98
99
/**
100
* Set a request header
101
* @param {string} header - Header name
102
* @param {string} value - Header value (must be string)
103
* @returns {void}
104
*/
105
setRequestHeader(header, value) {
106
// Implementation
107
}
108
109
/**
110
* Get a response header value
111
* @param {string} header - Header name
112
* @returns {string|null} Header value or null if not found
113
*/
114
getResponseHeader(header) {
115
// Implementation
116
}
117
118
/**
119
* Get all response headers as a string
120
* @returns {string} All headers in HTTP format
121
*/
122
getAllResponseHeaders() {
123
// Implementation
124
}
125
126
/**
127
* Abort the current request
128
* @returns {void}
129
*/
130
abort() {
131
// Implementation
132
}
133
134
/**
135
* Override the MIME type of the response
136
* @param {string} type - MIME type to use
137
* @returns {void}
138
*/
139
overrideMimeType(type) {
140
// Implementation
141
}
142
```
143
144
### XMLHttpRequest Properties
145
146
All standard XMLHttpRequest properties are supported.
147
148
```javascript { .api }
149
/**
150
* @typedef {Object} FakeXMLHttpRequest
151
* @property {0} UNSENT - State constant
152
* @property {1} OPENED - State constant
153
* @property {2} HEADERS_RECEIVED - State constant
154
* @property {3} LOADING - State constant
155
* @property {4} DONE - State constant
156
* @property {number} readyState - Current state
157
* @property {number} status - HTTP status code
158
* @property {string} statusText - HTTP status text
159
* @property {string} responseURL - Response URL
160
* @property {*} response - Response data
161
* @property {string} responseText - Response as text
162
* @property {Document|null} responseXML - Response as XML document
163
* @property {string} responseType - Expected response type ("", "text", "json", "blob", "arraybuffer", "document")
164
* @property {number} timeout - Request timeout in milliseconds (if supported by platform)
165
* @property {boolean} withCredentials - Whether to send credentials (if CORS is supported)
166
* @property {XMLHttpRequestUpload} upload - Upload event target
167
* @property {function(Event): void|null} onreadystatechange - Ready state change event handler
168
* @property {function(ProgressEvent): void|null} onloadstart - Load start event handler
169
* @property {function(ProgressEvent): void|null} onprogress - Progress event handler
170
* @property {function(ProgressEvent): void|null} onload - Load event handler
171
* @property {function(ProgressEvent): void|null} onloadend - Load end event handler
172
* @property {function(ProgressEvent): void|null} onerror - Error event handler
173
* @property {function(ProgressEvent): void|null} onabort - Abort event handler
174
* @property {function(ProgressEvent): void|null} ontimeout - Timeout event handler
175
*/
176
```
177
178
### Mock-Specific Methods
179
180
Additional methods for controlling the fake XMLHttpRequest behavior.
181
182
```javascript { .api }
183
/**
184
* Set the response status code
185
* @param {number} status - HTTP status code
186
* @returns {void}
187
*/
188
setStatus(status) {
189
// Implementation
190
}
191
192
/**
193
* Set response headers
194
* @param {Object.<string, string>} headers - Object with header name/value pairs
195
* @returns {void}
196
*/
197
setResponseHeaders(headers) {
198
// Implementation
199
}
200
201
/**
202
* Set the response body
203
* @param {string|ArrayBuffer|Blob} body - Response body data
204
* @returns {void}
205
*/
206
setResponseBody(body) {
207
// Implementation
208
}
209
210
/**
211
* Set complete response (status, headers, and body)
212
* @param {number} status - HTTP status code
213
* @param {Object.<string, string>} headers - Response headers object
214
* @param {string|ArrayBuffer} body - Response body
215
* @returns {void}
216
*/
217
respond(status, headers, body) {
218
// Implementation
219
}
220
221
/**
222
* Trigger an error state
223
* @returns {void}
224
*/
225
error() {
226
// Implementation
227
}
228
229
/**
230
* Trigger a timeout
231
* @returns {void}
232
*/
233
triggerTimeout() {
234
// Implementation
235
}
236
```
237
238
**Usage Example:**
239
240
```javascript
241
const nise = require("nise");
242
243
// Create fake XHR instance
244
const xhr = new nise.fakeXhr.FakeXMLHttpRequest();
245
246
// Set up event handlers
247
xhr.onreadystatechange = function() {
248
if (xhr.readyState === 4) {
249
console.log(`Response: ${xhr.responseText}`);
250
}
251
};
252
253
// Initialize and send request
254
xhr.open("GET", "/api/data");
255
xhr.send();
256
257
// Simulate response
258
xhr.respond(200, { "Content-Type": "application/json" }, '{"data": "test"}');
259
```
260
261
### Progress Events
262
263
Simulate upload and download progress events.
264
265
```javascript { .api }
266
/**
267
* @typedef {Object} ProgressEventInit
268
* @property {number} loaded - Bytes loaded
269
* @property {number} total - Total bytes
270
*/
271
272
/**
273
* Simulate upload progress
274
* @param {ProgressEventInit} progressEventRaw - Progress event data
275
* @returns {void}
276
*/
277
uploadProgress(progressEventRaw) {
278
// Implementation
279
}
280
281
/**
282
* Simulate download progress
283
* @param {ProgressEventInit} progressEventRaw - Progress event data
284
* @returns {void}
285
*/
286
downloadProgress(progressEventRaw) {
287
// Implementation
288
}
289
290
/**
291
* Simulate upload error
292
* @param {*} error - Error details
293
* @returns {void}
294
*/
295
uploadError(error) {
296
// Implementation
297
}
298
```
299
300
**Usage Example:**
301
302
```javascript
303
const xhr = new nise.fakeXhr.FakeXMLHttpRequest();
304
305
xhr.upload.onprogress = function(event) {
306
console.log(`Upload: ${event.loaded}/${event.total}`);
307
};
308
309
xhr.onprogress = function(event) {
310
console.log(`Download: ${event.loaded}/${event.total}`);
311
};
312
313
xhr.open("POST", "/upload");
314
xhr.send(new FormData());
315
316
// Simulate upload progress
317
xhr.uploadProgress({ loaded: 50, total: 100 });
318
xhr.uploadProgress({ loaded: 100, total: 100 });
319
320
// Simulate response with download progress
321
xhr.setStatus(200);
322
xhr.setResponseHeaders({ "Content-Length": "1000" });
323
xhr.downloadProgress({ loaded: 500, total: 1000 });
324
xhr.setResponseBody("response data");
325
xhr.downloadProgress({ loaded: 1000, total: 1000 });
326
```
327
328
### Request Filtering
329
330
Filter requests to allow some to pass through to real XMLHttpRequest.
331
332
```javascript { .api }
333
/**
334
* Add a filter function to determine which requests should use real XHR
335
* @param {function(string, string, boolean, string=, string=): boolean} filterFn - Function that returns true to use real XHR
336
* @returns {void}
337
*/
338
static addFilter(filterFn) {
339
// Implementation
340
}
341
342
/**
343
* Enable request filtering
344
* @type {boolean}
345
*/
346
static useFilters = false;
347
348
/**
349
* Convert fake XHR to real XHR for this request
350
* @param {FakeXMLHttpRequest} fakeXhr - The fake XHR instance
351
* @param {Array} xhrArgs - Arguments passed to open()
352
* @returns {void}
353
*/
354
static defake(fakeXhr, xhrArgs) {
355
// Implementation
356
}
357
```
358
359
**Usage Example:**
360
361
```javascript
362
const nise = require("nise");
363
364
// Enable filtering
365
nise.fakeXhr.FakeXMLHttpRequest.useFilters = true;
366
367
// Add filter to allow real requests to external APIs
368
nise.fakeXhr.FakeXMLHttpRequest.addFilter(function(method, url) {
369
// Use real XHR for external URLs
370
return url.startsWith("https://api.external.com");
371
});
372
373
// Replace global XHR
374
const FakeXHR = nise.fakeXhr.useFakeXMLHttpRequest();
375
376
// Internal requests use fake XHR
377
const internalXhr = new XMLHttpRequest();
378
internalXhr.open("GET", "/api/internal"); // Uses fake XHR
379
380
// External requests use real XHR
381
const externalXhr = new XMLHttpRequest();
382
externalXhr.open("GET", "https://api.external.com/data"); // Uses real XHR
383
```
384
385
### Response Type Handling
386
387
Support for different response types (text, json, blob, arraybuffer, document).
388
389
```javascript { .api }
390
/**
391
* @typedef {Object} ResponseTypeHandling - Response type conversion and validation
392
* @property {string} responseType - Set before send() to specify expected response type ("", "text", "json", "blob", "arraybuffer", "document")
393
* @property {*} response - Response data in the format specified by responseType
394
* @property {string} responseText - Response as text (for responseType "" or "text")
395
* @property {Document|null} responseXML - Response as XML document (for responseType "document" or XML content)
396
*/
397
```
398
399
**Usage Example:**
400
401
```javascript
402
const xhr = new nise.fakeXhr.FakeXMLHttpRequest();
403
404
// JSON response
405
xhr.open("GET", "/api/data");
406
xhr.responseType = "json";
407
xhr.send();
408
xhr.respond(200, { "Content-Type": "application/json" }, '{"name": "Alice"}');
409
console.log(xhr.response); // {name: "Alice"} (parsed object)
410
411
// ArrayBuffer response
412
const xhr2 = new nise.fakeXhr.FakeXMLHttpRequest();
413
xhr2.open("GET", "/api/binary");
414
xhr2.responseType = "arraybuffer";
415
xhr2.send();
416
xhr2.respond(200, {}, "binary data");
417
console.log(xhr2.response instanceof ArrayBuffer); // true
418
```
419
420
### Static Utilities
421
422
Utility methods and properties available on the FakeXMLHttpRequest constructor.
423
424
```javascript { .api }
425
/**
426
* HTTP status codes mapping
427
* @type {Object.<number, string>}
428
*/
429
static statusCodes = {};
430
431
/**
432
* Parse XML text into Document
433
* @param {string} text - XML text to parse
434
* @returns {Document|null} Parsed document or null if parsing failed
435
*/
436
static parseXML(text) {
437
// Implementation
438
}
439
440
/**
441
* Callback called when new FakeXMLHttpRequest instances are created
442
* @type {function(FakeXMLHttpRequest): void|null}
443
*/
444
static onCreate = null;
445
```
446
447
**Usage Example:**
448
449
```javascript
450
const nise = require("nise");
451
452
// Set up onCreate callback for all new XHR instances
453
nise.fakeXhr.FakeXMLHttpRequest.onCreate = function(xhr) {
454
console.log("New XHR created:", xhr);
455
// Could set default headers, event handlers, etc.
456
};
457
458
// Check status codes
459
console.log(nise.fakeXhr.FakeXMLHttpRequest.statusCodes[404]); // "Not Found"
460
461
// Parse XML
462
const doc = nise.fakeXhr.FakeXMLHttpRequest.parseXML("<root><item>test</item></root>");
463
console.log(doc.querySelector("item").textContent); // "test"
464
```