or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

fixture-testing.mdglobal-management.mdindex.mdrecording-playback.mdrequest-interception.mdrequest-matching.mdresponse-definition.md

response-definition.mddocs/

0

# Response Definition

1

2

This document covers how to define mock responses for intercepted HTTP requests using nock's Interceptor interface.

3

4

## Basic Response Definition

5

6

The primary method for defining responses is the `reply` method, which has several overloads for different use cases.

7

8

```javascript { .api }

9

interface Interceptor {

10

reply(responseCode?: number, body?: ReplyBody, headers?: ReplyHeaders): Scope;

11

reply(

12

replyFn: (uri: string, body: Body) => ReplyFnResult | Promise<ReplyFnResult>

13

): Scope;

14

reply(

15

replyFnWithCallback: (

16

uri: string,

17

body: Body,

18

callback: (err: NodeJS.ErrnoException | null, result: ReplyFnResult) => void

19

) => void

20

): Scope;

21

reply(

22

statusCode: number,

23

replyBodyFn: (uri: string, body: Body) => ReplyBody | Promise<ReplyBody>,

24

headers?: ReplyHeaders

25

): Scope;

26

reply(

27

statusCode: number,

28

replyBodyFnWithCallback: (

29

uri: string,

30

body: Body,

31

callback: (err: NodeJS.ErrnoException | null, result: ReplyBody) => void

32

) => void,

33

headers?: ReplyHeaders

34

): Scope;

35

}

36

```

37

38

### Static Responses

39

40

```javascript

41

// Basic 200 OK response

42

nock("https://api.example.com")

43

.get("/users")

44

.reply(200);

45

46

// With response body

47

nock("https://api.example.com")

48

.get("/users")

49

.reply(200, [{ id: 1, name: "Alice" }]);

50

51

// With custom headers

52

nock("https://api.example.com")

53

.get("/users")

54

.reply(200, [{ id: 1, name: "Alice" }], {

55

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

56

"X-Total-Count": "1"

57

});

58

59

// Different status codes

60

nock("https://api.example.com")

61

.post("/users")

62

.reply(201, { id: 2, name: "Bob" });

63

64

nock("https://api.example.com")

65

.get("/users/999")

66

.reply(404, { error: "User not found" });

67

```

68

69

### Dynamic Responses

70

71

Use functions to generate responses based on the request:

72

73

```javascript

74

// Function returning response data

75

nock("https://api.example.com")

76

.get(/\/users\/(\d+)/)

77

.reply(200, (uri, requestBody) => {

78

const id = uri.match(/\/users\/(\d+)/)[1];

79

return { id: parseInt(id), name: `User ${id}` };

80

});

81

82

// Function returning full response

83

nock("https://api.example.com")

84

.post("/users")

85

.reply((uri, requestBody) => {

86

const user = JSON.parse(requestBody);

87

if (!user.name) {

88

return [400, { error: "Name is required" }];

89

}

90

return [201, { ...user, id: Math.floor(Math.random() * 1000) }];

91

});

92

93

// Async function support

94

nock("https://api.example.com")

95

.get("/users")

96

.reply(async (uri, requestBody) => {

97

// Simulate async operation

98

await new Promise(resolve => setTimeout(resolve, 100));

99

return [200, { message: "Users loaded asynchronously" }];

100

});

101

```

102

103

### Callback-Style Dynamic Responses

104

105

For more complex scenarios requiring callback-style responses:

106

107

```javascript

108

nock("https://api.example.com")

109

.get("/users")

110

.reply(function(uri, requestBody, callback) {

111

// 'this' refers to the interceptor context

112

const req = this.req;

113

114

// Simulate async operation

115

setTimeout(() => {

116

callback(null, [200, { users: [], requestId: req.headers["x-request-id"] }]);

117

}, 100);

118

});

119

```

120

121

## Response Body Types

122

123

```javascript { .api }

124

type ReplyBody = string | Record<string, any> | Buffer | ReadStream;

125

```

126

127

Nock supports various response body types:

128

129

### JSON Objects

130

131

```javascript

132

nock("https://api.example.com")

133

.get("/user")

134

.reply(200, { id: 1, name: "Alice", active: true });

135

```

136

137

### Plain Text

138

139

```javascript

140

nock("https://api.example.com")

141

.get("/status")

142

.reply(200, "Server is healthy");

143

```

144

145

### Buffer Data

146

147

```javascript

148

const imageBuffer = Buffer.from("fake-image-data");

149

nock("https://api.example.com")

150

.get("/image.png")

151

.reply(200, imageBuffer, { "Content-Type": "image/png" });

152

```

153

154

### Stream Data

155

156

```javascript

157

const fs = require("fs");

158

const stream = fs.createReadStream("./test-data.json");

159

160

nock("https://api.example.com")

161

.get("/large-dataset")

162

.reply(200, stream, { "Content-Type": "application/json" });

163

```

164

165

## Error Responses

166

167

### Reply with Error

168

169

Generate network-level errors instead of HTTP error responses:

170

171

```javascript { .api }

172

replyWithError(errorMessage: string | object): Scope;

173

```

174

175

```javascript

176

// String error message

177

nock("https://api.example.com")

178

.get("/users")

179

.replyWithError("Network timeout");

180

181

// Error object

182

nock("https://api.example.com")

183

.get("/users")

184

.replyWithError({

185

code: "ECONNREFUSED",

186

message: "Connection refused"

187

});

188

189

// This will cause the HTTP request to fail with the specified error

190

```

191

192

### Reply with File

193

194

Respond with the contents of a file:

195

196

```javascript { .api }

197

replyWithFile(statusCode: number, fileName: string, headers?: ReplyHeaders): Scope;

198

```

199

200

```javascript

201

nock("https://api.example.com")

202

.get("/config")

203

.replyWithFile(200, "./test-fixtures/config.json", {

204

"Content-Type": "application/json"

205

});

206

```

207

208

## Response Headers

209

210

```javascript { .api }

211

type ReplyHeaders =

212

| Record<string, ReplyHeaderValue>

213

| Map<string, ReplyHeaderValue>

214

| ReplyHeaderValue[];

215

216

type ReplyHeaderValue = string | string[] | ReplyHeaderFunction;

217

218

type ReplyHeaderFunction = (

219

req: ClientRequest,

220

res: IncomingMessage,

221

body: string | Buffer

222

) => string | string[];

223

```

224

225

### Static Headers

226

227

```javascript

228

// Object format

229

nock("https://api.example.com")

230

.get("/users")

231

.reply(200, [], {

232

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

233

"X-Total-Count": "0"

234

});

235

236

// Array format (key-value pairs)

237

nock("https://api.example.com")

238

.get("/users")

239

.reply(200, [], [

240

"Content-Type", "application/json",

241

"X-Total-Count", "0"

242

]);

243

244

// Map format

245

const headers = new Map();

246

headers.set("Content-Type", "application/json");

247

headers.set("X-Total-Count", "0");

248

249

nock("https://api.example.com")

250

.get("/users")

251

.reply(200, [], headers);

252

```

253

254

### Multiple Values

255

256

```javascript

257

// Multiple values for same header

258

nock("https://api.example.com")

259

.get("/users")

260

.reply(200, [], {

261

"Set-Cookie": ["session=abc123", "theme=dark"]

262

});

263

```

264

265

### Dynamic Headers

266

267

```javascript

268

nock("https://api.example.com")

269

.get("/users")

270

.reply(200, [], {

271

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

272

"X-Request-Time": (req, res, body) => new Date().toISOString(),

273

"X-Body-Length": (req, res, body) => body.length.toString()

274

});

275

```

276

277

## Response Timing

278

279

Control the timing of responses to simulate network latency or slow servers.

280

281

### Basic Delay

282

283

```javascript { .api }

284

delay(ms: number): this;

285

```

286

287

```javascript

288

// Delay response by 1 second

289

nock("https://api.example.com")

290

.get("/users")

291

.delay(1000)

292

.reply(200, []);

293

```

294

295

### Advanced Delay Options

296

297

```javascript { .api }

298

delay(opts: { head?: number; body?: number }): this;

299

```

300

301

```javascript

302

// Separate delays for headers and body

303

nock("https://api.example.com")

304

.get("/users")

305

.delay({

306

head: 100, // Delay headers by 100ms

307

body: 500 // Delay body by additional 500ms

308

})

309

.reply(200, []);

310

```

311

312

### Deprecated Delay Methods

313

314

These methods are deprecated but still supported:

315

316

```javascript { .api }

317

delayBody(timeMs: number): this;

318

delayConnection(timeMs: number): this;

319

```

320

321

```javascript

322

// Deprecated - use delay() instead

323

nock("https://api.example.com")

324

.get("/users")

325

.delayConnection(200)

326

.delayBody(300)

327

.reply(200, []);

328

```

329

330

## Repetition Control

331

332

Control how many times an interceptor can be matched.

333

334

```javascript { .api }

335

interface Interceptor {

336

times(newCounter: number): this;

337

once(): this;

338

twice(): this;

339

thrice(): this;

340

optionally(flag?: boolean): this;

341

}

342

```

343

344

### Specific Repetition Counts

345

346

```javascript

347

// Match exactly 3 times

348

nock("https://api.example.com")

349

.get("/users")

350

.times(3)

351

.reply(200, []);

352

353

// Convenience methods

354

nock("https://api.example.com")

355

.get("/status")

356

.once() // Same as .times(1)

357

.reply(200, "OK");

358

359

nock("https://api.example.com")

360

.get("/health")

361

.twice() // Same as .times(2)

362

.reply(200, "Healthy");

363

364

nock("https://api.example.com")

365

.get("/ping")

366

.thrice() // Same as .times(3)

367

.reply(200, "Pong");

368

```

369

370

### Optional Interceptors

371

372

```javascript

373

// This interceptor is optional for scope.done() checks

374

nock("https://api.example.com")

375

.get("/optional-endpoint")

376

.optionally()

377

.reply(200, "Optional response");

378

379

// Can also be toggled

380

nock("https://api.example.com")

381

.get("/conditional")

382

.optionally(process.env.NODE_ENV === "test")

383

.reply(200, "Conditional response");

384

```

385

386

## Response Function Context

387

388

When using function-based replies, the function receives a context with additional information:

389

390

```javascript { .api }

391

interface ReplyFnContext extends Interceptor {

392

req: ClientRequest & {

393

headers: Record<string, string>;

394

};

395

}

396

```

397

398

```javascript

399

nock("https://api.example.com")

400

.post("/users")

401

.reply(function(uri, requestBody) {

402

// 'this' provides access to the request context

403

const contentType = this.req.headers["content-type"];

404

const userAgent = this.req.headers["user-agent"];

405

406

return [200, {

407

message: "User created",

408

metadata: {

409

contentType,

410

userAgent,

411

timestamp: Date.now()

412

}

413

}];

414

});

415

```