0
# Utility Functions
1
2
xhr-mock provides several utility functions for advanced mocking scenarios including delays, one-time responses, response sequences, and request proxying to real servers.
3
4
## Capabilities
5
6
### Once Function
7
8
Creates a mock handler that only responds to the first request, then becomes inactive.
9
10
```typescript { .api }
11
/**
12
* Create a mock that only responds once
13
* @param mock - Mock object or function to use for the single response
14
* @returns MockFunction that responds only to the first matching request
15
*/
16
function once(mock: MockFunction | MockObject): MockFunction;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import mock, { once } from 'xhr-mock';
23
24
// One-time response with object
25
mock.get('/api/special-offer', once({
26
status: 200,
27
body: JSON.stringify({ offer: 'Limited time 50% off!' })
28
}));
29
30
// One-time response with function
31
mock.post('/api/trial-signup', once((req, res) => {
32
const email = JSON.parse(req.body()).email;
33
return res.status(201).body(JSON.stringify({
34
message: 'Trial activated',
35
36
}));
37
}));
38
39
// After the first request, subsequent requests will not match this handler
40
```
41
42
### Delay Function
43
44
Adds a delay to mock responses to simulate network latency or slow servers.
45
46
```typescript { .api }
47
/**
48
* Add delay to mock responses
49
* @param mock - Mock object or function to delay
50
* @param ms - Delay in milliseconds (default: 1500)
51
* @returns MockFunction that responds after the specified delay
52
*/
53
function delay(mock: MockFunction | MockObject, ms?: number): MockFunction;
54
```
55
56
**Usage Examples:**
57
58
```typescript
59
import mock, { delay } from 'xhr-mock';
60
61
// Default delay (1500ms)
62
mock.get('/api/slow-endpoint', delay({
63
status: 200,
64
body: JSON.stringify({ data: 'This took a while...' })
65
}));
66
67
// Custom delay (3 seconds)
68
mock.post('/api/upload', delay({
69
status: 201,
70
body: JSON.stringify({ message: 'Upload complete' })
71
}, 3000));
72
73
// Delay with function
74
mock.get('/api/processing', delay((req, res) => {
75
return res.status(200).body(JSON.stringify({
76
status: 'processed',
77
timestamp: Date.now()
78
}));
79
}, 2000));
80
```
81
82
### Sequence Function
83
84
Returns different responses for consecutive requests to the same endpoint.
85
86
```typescript { .api }
87
/**
88
* Return different responses for consecutive requests
89
* @param mocks - Array of mock objects or functions to use in sequence
90
* @returns MockFunction that cycles through the provided mocks
91
*/
92
function sequence(mocks: (MockFunction | MockObject)[]): MockFunction;
93
```
94
95
**Usage Examples:**
96
97
```typescript
98
import mock, { sequence } from 'xhr-mock';
99
100
// Different status codes for each request
101
mock.get('/api/flaky-service', sequence([
102
{ status: 200, body: 'Success on first try' },
103
{ status: 500, body: 'Server error on second try' },
104
{ status: 200, body: 'Success on third try' }
105
]));
106
107
// Mixed objects and functions
108
mock.post('/api/batch-process', sequence([
109
(req, res) => res.status(202).body('Processing started'),
110
{ status: 202, body: 'Still processing...' },
111
{ status: 200, body: 'Processing complete' }
112
// After the third request, no more responses (undefined returned)
113
]));
114
115
// First request gets first response, second gets second, etc.
116
// After all responses are used, subsequent requests get no response
117
```
118
119
### Proxy Function
120
121
Forwards unhandled requests to real servers, allowing you to mock some endpoints while letting others pass through.
122
123
```typescript { .api }
124
/**
125
* Proxy unhandled requests to real servers
126
* @param req - MockRequest object representing the incoming request
127
* @param res - MockResponse object to populate with the real response
128
* @returns Promise resolving to MockResponse with real server data
129
*/
130
function proxy(req: MockRequest, res: MockResponse): Promise<MockResponse>;
131
```
132
133
**Usage Examples:**
134
135
```typescript
136
import mock, { proxy } from 'xhr-mock';
137
138
mock.setup();
139
140
// Mock specific endpoints
141
mock.post('/api/auth/login', {
142
status: 200,
143
body: JSON.stringify({ token: 'fake-jwt-token' })
144
});
145
146
// Proxy all other requests to real servers
147
mock.use(proxy);
148
149
// This request will be mocked
150
fetch('/api/auth/login', {
151
method: 'POST',
152
body: JSON.stringify({ username: 'test', password: 'test' })
153
});
154
155
// This request will be proxied to the real server
156
fetch('https://api.github.com/users/octocat');
157
```
158
159
**Advanced Proxy Usage:**
160
161
```typescript
162
// Selective proxying with custom logic
163
mock.use((req, res) => {
164
const url = req.url();
165
166
// Mock localhost requests
167
if (url.host === 'localhost') {
168
return res.status(200).body('Mocked localhost response');
169
}
170
171
// Proxy external requests
172
if (url.host.includes('api.external.com')) {
173
return proxy(req, res);
174
}
175
176
// Default response for everything else
177
return res.status(404).body('Not found');
178
});
179
```
180
181
## Combining Utilities
182
183
Utilities can be combined to create complex mocking scenarios:
184
185
```typescript
186
import mock, { once, delay, sequence } from 'xhr-mock';
187
188
// One-time delayed response
189
mock.get('/api/setup', once(delay({
190
status: 200,
191
body: JSON.stringify({ initialized: true })
192
}, 2000)));
193
194
// Delayed sequence
195
mock.get('/api/polling', delay(sequence([
196
{ status: 202, body: 'Processing...' },
197
{ status: 202, body: 'Still processing...' },
198
{ status: 200, body: 'Complete!' }
199
]), 1000));
200
201
// Complex scenario: First request is delayed, subsequent requests are fast
202
let firstRequest = true;
203
mock.get('/api/cache-warmup', (req, res) => {
204
const response = res.status(200).body('Data loaded');
205
206
if (firstRequest) {
207
firstRequest = false;
208
return delay(() => response, 3000)(req, res);
209
}
210
211
return response;
212
});
213
```
214
215
## Error Simulation
216
217
Create realistic error scenarios for testing error handling:
218
219
```typescript
220
// Simulate network errors
221
mock.get('/api/unreliable', () => {
222
return Promise.reject(new Error('Network error'));
223
});
224
225
// Simulate timeouts (return a promise that never resolves)
226
mock.get('/api/timeout', () => {
227
return new Promise(() => {}); // Never resolves
228
});
229
230
// Then in your test setup:
231
const xhr = new XMLHttpRequest();
232
xhr.timeout = 1000; // 1 second timeout
233
xhr.ontimeout = () => console.log('Request timed out');
234
xhr.onerror = () => console.log('Network error occurred');
235
```
236
237
## Types
238
239
```typescript { .api }
240
type MockFunction = (
241
request: MockRequest,
242
response: MockResponse
243
) => undefined | MockResponse | Promise<undefined | MockResponse>;
244
245
interface MockObject {
246
status?: number;
247
reason?: string;
248
headers?: MockHeaders;
249
body?: any;
250
}
251
252
type MockHeaders = {[name: string]: string};
253
```