or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdbrowser-automation.mdclient-functions.mdelement-selection.mdindex.mdprogrammatic-api.mdrequest-interception.mduser-roles.md

request-interception.mddocs/

0

# Request Interception

1

2

TestCafe provides powerful HTTP request and response interception capabilities through request hooks, allowing you to monitor, log, and mock network traffic during test execution.

3

4

## Capabilities

5

6

### Request Logging

7

8

Monitor and log HTTP requests and responses for debugging and verification.

9

10

```javascript { .api }

11

/**

12

* Creates a request logger to monitor HTTP traffic

13

* @param requestFilterRuleInit - Filter rule to specify which requests to log

14

* @param logOptions - Configuration options for logging behavior

15

* @returns RequestLogger instance for attaching to tests

16

*/

17

function RequestLogger(

18

requestFilterRuleInit?: string | RegExp | object | Function,

19

logOptions?: RequestLoggerOptions

20

): RequestLogger;

21

22

interface RequestLogger {

23

/** Array of logged request objects */

24

requests: LoggedRequest[];

25

26

/** Number of requests that have been logged */

27

count: number;

28

29

/**

30

* Checks if request matching criteria was logged

31

* @param predicate - Function to test each logged request

32

* @returns True if matching request exists

33

*/

34

contains(predicate: (request: LoggedRequest) => boolean): boolean;

35

36

/**

37

* Clears all logged requests

38

*/

39

clear(): void;

40

}

41

42

interface RequestLoggerOptions {

43

/** Log request body content */

44

logRequestBody?: boolean;

45

46

/** Log response body content */

47

logResponseBody?: boolean;

48

49

/** Stringify request body */

50

stringifyRequestBody?: boolean;

51

52

/** Stringify response body */

53

stringifyResponseBody?: boolean;

54

}

55

56

interface LoggedRequest {

57

/** Request information */

58

request: {

59

url: string;

60

method: string;

61

headers: object;

62

body?: string;

63

isAjax: boolean;

64

};

65

66

/** Response information */

67

response: {

68

statusCode: number;

69

statusText: string;

70

headers: object;

71

body?: string;

72

};

73

}

74

```

75

76

**Usage Examples:**

77

78

```javascript

79

import { RequestLogger } from 'testcafe';

80

81

const logger = RequestLogger();

82

83

fixture('Request Logging')

84

.page('https://example.com')

85

.requestHooks(logger);

86

87

test('Monitor API calls', async t => {

88

await t.click('#load-data-button');

89

90

// Wait for requests to complete

91

await t.wait(2000);

92

93

// Check logged requests

94

await t.expect(logger.count).gte(1);

95

96

// Find specific API call

97

const apiCall = logger.requests.find(request =>

98

request.request.url.includes('/api/data')

99

);

100

101

await t.expect(apiCall).ok();

102

await t.expect(apiCall.response.statusCode).eql(200);

103

});

104

105

// Log only specific requests

106

const apiLogger = RequestLogger(/\/api\//, {

107

logRequestBody: true,

108

logResponseBody: true

109

});

110

111

test('Monitor specific API endpoints', async t => {

112

await t.click('#submit-form');

113

114

// Check API request was made

115

const postRequest = apiLogger.requests.find(req =>

116

req.request.method === 'POST' &&

117

req.request.url.includes('/api/submit')

118

);

119

120

await t.expect(postRequest).ok();

121

await t.expect(postRequest.request.body).contains('formData');

122

});

123

```

124

125

### Request Mocking

126

127

Mock HTTP requests and responses to control application behavior during tests.

128

129

```javascript { .api }

130

/**

131

* Creates a request mock for intercepting and responding to HTTP requests

132

* @returns RequestMock instance for configuring mock responses

133

*/

134

function RequestMock(): RequestMock;

135

136

interface RequestMock {

137

/**

138

* Configures mock to respond to requests matching the filter

139

* @param requestFilterRuleInit - Filter rule to match requests

140

* @param responseEventConfigurer - Response configuration

141

* @returns RequestMock instance for chaining

142

*/

143

onRequestTo(

144

requestFilterRuleInit: string | RegExp | object | Function,

145

responseEventConfigurer: ResponseEventConfigurer

146

): RequestMock;

147

}

148

149

interface ResponseEventConfigurer {

150

/**

151

* Responds with specified data and status

152

* @param body - Response body content

153

* @param statusCode - HTTP status code (default: 200)

154

* @param headers - Response headers

155

* @returns Response configuration

156

*/

157

respond(body?: any, statusCode?: number, headers?: object): void;

158

159

/**

160

* Responds with data from file

161

* @param filePath - Path to response file

162

* @param statusCode - HTTP status code (default: 200)

163

* @param headers - Response headers

164

* @returns Response configuration

165

*/

166

respondWithFile(filePath: string, statusCode?: number, headers?: object): void;

167

}

168

```

169

170

**Usage Examples:**

171

172

```javascript

173

import { RequestMock } from 'testcafe';

174

175

// Mock API responses

176

const mockAPI = RequestMock()

177

.onRequestTo(/\/api\/users/)

178

.respond([

179

{ id: 1, name: 'John Doe', email: 'john@example.com' },

180

{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }

181

], 200, {

182

'Content-Type': 'application/json',

183

'Access-Control-Allow-Origin': '*'

184

})

185

.onRequestTo(/\/api\/error/)

186

.respond({ error: 'Not found' }, 404);

187

188

fixture('Request Mocking')

189

.page('https://example.com')

190

.requestHooks(mockAPI);

191

192

test('Mock successful API response', async t => {

193

await t.click('#load-users-button');

194

195

// Verify mocked data is displayed

196

await t.expect(Selector('.user-list .user-item').count).eql(2);

197

await t.expect(Selector('.user-item').nth(0).innerText).contains('John Doe');

198

});

199

200

test('Mock error response', async t => {

201

await t.click('#trigger-error-button');

202

203

// Verify error handling

204

await t.expect(Selector('.error-message').innerText).contains('Not found');

205

});

206

207

// Mock with file response

208

const fileMock = RequestMock()

209

.onRequestTo(/\/api\/large-data/)

210

.respondWithFile('./fixtures/large-response.json', 200, {

211

'Content-Type': 'application/json'

212

});

213

```

214

215

### Custom Request Hooks

216

217

Create custom request hooks for advanced request/response processing.

218

219

```javascript { .api }

220

/**

221

* Base class for creating custom request hooks

222

*/

223

class RequestHook {

224

/**

225

* Creates custom request hook

226

* @param requestFilterRuleInit - Filter rule to specify which requests to intercept

227

*/

228

constructor(requestFilterRuleInit?: string | RegExp | object | Function);

229

230

/**

231

* Called when request is made (override in subclass)

232

* @param event - Request event object

233

* @returns Promise for async processing

234

*/

235

onRequest(event: RequestEvent): Promise<void>;

236

237

/**

238

* Called when response is received (override in subclass)

239

* @param event - Response event object

240

* @returns Promise for async processing

241

*/

242

onResponse(event: ResponseEvent): Promise<void>;

243

}

244

245

interface RequestEvent {

246

/** Request information */

247

request: {

248

url: string;

249

method: string;

250

headers: object;

251

body: string;

252

isAjax: boolean;

253

};

254

255

/** Modify request headers */

256

setHeaders(headers: object): void;

257

258

/** Remove request header */

259

removeHeader(name: string): void;

260

}

261

262

interface ResponseEvent {

263

/** Request information */

264

request: {

265

url: string;

266

method: string;

267

headers: object;

268

body: string;

269

isAjax: boolean;

270

};

271

272

/** Response information */

273

response: {

274

statusCode: number;

275

statusText: string;

276

headers: object;

277

body: string;

278

};

279

280

/** Modify response headers */

281

setHeaders(headers: object): void;

282

283

/** Remove response header */

284

removeHeader(name: string): void;

285

}

286

```

287

288

**Usage Examples:**

289

290

```javascript

291

import { RequestHook } from 'testcafe';

292

293

// Custom authentication hook

294

class AuthHook extends RequestHook {

295

constructor() {

296

super(/\/api\//);

297

}

298

299

async onRequest(event) {

300

// Add authentication header to API requests

301

event.setHeaders({

302

'Authorization': 'Bearer test-token',

303

'X-Test-Mode': 'true'

304

});

305

}

306

307

async onResponse(event) {

308

// Log API responses

309

console.log(`API ${event.request.method} ${event.request.url}: ${event.response.statusCode}`);

310

}

311

}

312

313

// Custom timing hook

314

class TimingHook extends RequestHook {

315

constructor() {

316

super();

317

this.requestTimes = new Map();

318

}

319

320

async onRequest(event) {

321

this.requestTimes.set(event.request.url, Date.now());

322

}

323

324

async onResponse(event) {

325

const startTime = this.requestTimes.get(event.request.url);

326

const duration = Date.now() - startTime;

327

console.log(`Request to ${event.request.url} took ${duration}ms`);

328

}

329

}

330

331

const authHook = new AuthHook();

332

const timingHook = new TimingHook();

333

334

fixture('Custom Request Hooks')

335

.page('https://example.com')

336

.requestHooks([authHook, timingHook]);

337

338

test('Custom request processing', async t => {

339

await t.click('#api-call-button');

340

341

// Requests will be processed by custom hooks

342

await t.wait(1000);

343

});

344

```

345

346

### Request Filtering

347

348

Define sophisticated filters for targeting specific requests.

349

350

```javascript { .api }

351

// String URL filter

352

const stringFilter = 'https://api.example.com/users';

353

354

// RegExp URL filter

355

const regexpFilter = /\/api\/.*\/data/;

356

357

// Object filter with multiple criteria

358

const objectFilter = {

359

url: /\/api\//,

360

method: 'POST',

361

headers: {

362

'content-type': /application\/json/

363

}

364

};

365

366

// Function filter with custom logic

367

const functionFilter = (request) => {

368

return request.url.includes('/api/') &&

369

request.method === 'GET' &&

370

request.headers['authorization'];

371

};

372

```

373

374

**Usage Examples:**

375

376

```javascript

377

// Filter by URL pattern

378

const apiLogger = RequestLogger(/\/api\/v\d+\//);

379

380

// Filter POST requests to specific endpoint

381

const postLogger = RequestLogger({

382

url: 'https://api.example.com/submit',

383

method: 'POST'

384

});

385

386

// Filter by custom criteria

387

const customLogger = RequestLogger((request) => {

388

return request.isAjax &&

389

request.url.includes('/data') &&

390

!request.url.includes('/cache');

391

});

392

393

// Filter by headers

394

const authLogger = RequestLogger({

395

url: /\/api\//,

396

headers: {

397

'authorization': /Bearer .+/

398

}

399

});

400

401

fixture('Request Filtering')

402

.page('https://example.com')

403

.requestHooks([apiLogger, postLogger, customLogger, authLogger]);

404

405

test('Filtered request monitoring', async t => {

406

// Trigger various types of requests

407

await t

408

.click('#get-data-button')

409

.click('#post-form-button')

410

.click('#cached-request-button');

411

412

// Check filtered results

413

await t.expect(apiLogger.count).gte(1);

414

await t.expect(postLogger.count).eql(1);

415

await t.expect(customLogger.count).gte(1);

416

});

417

```

418

419

### Request Hook Attachment

420

421

Attach request hooks to tests, fixtures, or globally.

422

423

```javascript { .api }

424

// Fixture-level hooks

425

fixture('API Tests')

426

.page('https://example.com')

427

.requestHooks([logger, mock]);

428

429

// Test-level hooks

430

test('Specific test with hooks', async t => {

431

// Test implementation

432

}).requestHooks([specificLogger]);

433

434

// Multiple hooks

435

const hooks = [

436

RequestLogger(/\/api\//),

437

RequestMock().onRequestTo(/\/mock\//).respond({ success: true }),

438

new CustomHook()

439

];

440

441

fixture('Multiple Hooks')

442

.requestHooks(hooks);

443

```

444

445

**Usage Examples:**

446

447

```javascript

448

const globalLogger = RequestLogger();

449

const apiMock = RequestMock()

450

.onRequestTo(/\/api\/error/)

451

.respond({ error: 'Mocked error' }, 500);

452

453

// Apply to entire fixture

454

fixture('Request Hook Attachment')

455

.page('https://example.com')

456

.requestHooks([globalLogger, apiMock]);

457

458

test('Test with fixture hooks', async t => {

459

// Uses globalLogger and apiMock

460

await t.click('#api-button');

461

});

462

463

// Test-specific additional hooks

464

const testLogger = RequestLogger(/\/specific-api\//);

465

466

test('Test with additional hooks', async t => {

467

// Uses globalLogger, apiMock, and testLogger

468

await t.click('#specific-api-button');

469

}).requestHooks([testLogger]);

470

471

// Conditional hook attachment

472

const conditionalHook = process.env.NODE_ENV === 'test'

473

? RequestLogger()

474

: RequestMock().onRequestTo().respond();

475

476

fixture('Conditional Hooks')

477

.requestHooks([conditionalHook]);

478

```