or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdhttp-client.mdhttp-utilities.mdindex.mdrequest-response-mocking.mdtest-doubles.mdtest-sandbox.mdvalidation-helpers.md

http-client.mddocs/

0

# HTTP Client Testing

1

2

SuperTest integration and utilities for creating HTTP clients for testing REST applications and request handlers.

3

4

## Capabilities

5

6

### SuperTest Integration

7

8

Complete SuperTest library re-export for HTTP testing.

9

10

```typescript { .api }

11

/**

12

* SuperTest library for HTTP endpoint testing

13

* Provides fluent API for making HTTP requests and assertions

14

*/

15

const supertest: typeof import("supertest");

16

17

/**

18

* SuperTest client type for making HTTP requests

19

*/

20

type Client = supertest.SuperTest<supertest.Test>;

21

```

22

23

**Usage Examples:**

24

25

```typescript

26

import { supertest } from "@loopback/testlab";

27

import express from "express";

28

29

const app = express();

30

app.get("/users", (req, res) => res.json([{id: 1, name: "Alice"}]));

31

32

// Direct SuperTest usage

33

await supertest(app)

34

.get("/users")

35

.expect(200)

36

.expect("Content-Type", /json/)

37

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

38

```

39

40

### Client for Handler Function

41

42

Creates a SuperTest client for testing HTTP handler functions without starting a server.

43

44

```typescript { .api }

45

/**

46

* Create a SuperTest client connected to an HTTP server listening

47

* on an ephemeral port and calling handler to handle incoming requests

48

* @param handler - Request handler function

49

* @returns SuperTest client for making requests

50

*/

51

function createClientForHandler(

52

handler: (req: http.IncomingMessage, res: http.ServerResponse) => void

53

): Client;

54

```

55

56

**Usage Examples:**

57

58

```typescript

59

import { createClientForHandler, expect } from "@loopback/testlab";

60

import { IncomingMessage, ServerResponse } from "http";

61

62

// Simple handler

63

function simpleHandler(req: IncomingMessage, res: ServerResponse) {

64

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

65

res.end(JSON.stringify({message: "Hello World"}));

66

}

67

68

// Create client and test

69

const client = createClientForHandler(simpleHandler);

70

71

await client

72

.get("/")

73

.expect(200)

74

.expect("Content-Type", /json/)

75

.expect({message: "Hello World"});

76

77

// Handler with routing logic

78

function routingHandler(req: IncomingMessage, res: ServerResponse) {

79

const url = req.url;

80

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

81

82

if (url === "/users") {

83

res.end(JSON.stringify([{id: 1, name: "Alice"}]));

84

} else if (url === "/status") {

85

res.end(JSON.stringify({status: "ok"}));

86

} else {

87

res.writeHead(404);

88

res.end(JSON.stringify({error: "Not found"}));

89

}

90

}

91

92

const routingClient = createClientForHandler(routingHandler);

93

94

await routingClient.get("/users").expect(200).expect([{id: 1, name: "Alice"}]);

95

await routingClient.get("/status").expect(200).expect({status: "ok"});

96

await routingClient.get("/invalid").expect(404);

97

```

98

99

### Client for REST Application

100

101

Creates a SuperTest client for testing running LoopBack REST applications.

102

103

```typescript { .api }

104

/**

105

* Create a SuperTest client for a running RestApplication instance

106

* The app must be running and listening on a port

107

* @param app - A running RestApplication instance

108

* @returns SuperTest client for the application

109

* @throws Error if the application is not listening

110

*/

111

function createRestAppClient(app: RestApplicationLike): Client;

112

113

/**

114

* Interface for LoopBack-like REST applications

115

*/

116

interface RestApplicationLike {

117

restServer: RestServerLike;

118

}

119

120

/**

121

* Interface for LoopBack-like REST servers

122

*/

123

interface RestServerLike {

124

url?: string;

125

rootUrl?: string;

126

}

127

```

128

129

**Usage Examples:**

130

131

```typescript

132

import { createRestAppClient, expect } from "@loopback/testlab";

133

134

// Assuming you have a LoopBack application

135

class MyApplication {

136

restServer = {

137

url: "http://localhost:3000",

138

rootUrl: "http://localhost:3000"

139

};

140

}

141

142

const app = new MyApplication();

143

144

// Create client for running application

145

const client = createRestAppClient(app);

146

147

// Test application endpoints

148

await client

149

.get("/ping")

150

.expect(200)

151

.expect({greeting: "Hello from LoopBack"});

152

153

await client

154

.post("/users")

155

.send({name: "Bob", email: "bob@example.com"})

156

.expect(201)

157

.expect((res) => {

158

expect(res.body).to.have.property("id");

159

expect(res.body.name).to.equal("Bob");

160

});

161

162

// Testing with different HTTP methods

163

await client.get("/users").expect(200);

164

await client.put("/users/1").send({name: "Updated"}).expect(200);

165

await client.delete("/users/1").expect(204);

166

```

167

168

### SuperTest Test Interface

169

170

Common SuperTest methods and assertions for HTTP testing.

171

172

```typescript { .api }

173

// SuperTest Test interface (partial - key methods)

174

interface Test {

175

// HTTP methods

176

get(url: string): Test;

177

post(url: string): Test;

178

put(url: string): Test;

179

patch(url: string): Test;

180

delete(url: string): Test;

181

head(url: string): Test;

182

options(url: string): Test;

183

184

// Request configuration

185

send(data: any): Test;

186

query(params: object | string): Test;

187

set(field: string, value: string): Test;

188

set(fields: object): Test;

189

auth(user: string, pass: string): Test;

190

attach(field: string, file: string, filename?: string): Test;

191

field(name: string, value: string): Test;

192

193

// Response expectations

194

expect(status: number): Test;

195

expect(status: number, callback?: (err: Error, res: Response) => void): Test;

196

expect(body: any): Test;

197

expect(field: string, value: string | RegExp): Test;

198

expect(callback: (res: Response) => void): Test;

199

200

// Execution

201

end(callback: (err: Error, res: Response) => void): void;

202

then(resolve: (res: Response) => void, reject?: (err: Error) => void): Promise<Response>;

203

}

204

```

205

206

**Usage Examples:**

207

208

```typescript

209

import { createClientForHandler } from "@loopback/testlab";

210

211

const client = createClientForHandler(handler);

212

213

// Method chaining

214

await client

215

.post("/api/users")

216

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

217

.set("Authorization", "Bearer token123")

218

.send({name: "Charlie", email: "charlie@example.com"})

219

.expect(201)

220

.expect("Content-Type", /json/)

221

.expect((res) => {

222

expect(res.body).to.have.property("id");

223

expect(res.body.name).to.equal("Charlie");

224

});

225

226

// Query parameters

227

await client

228

.get("/api/users")

229

.query({limit: 10, offset: 0})

230

.expect(200);

231

232

// File uploads

233

await client

234

.post("/api/upload")

235

.attach("file", "/path/to/file.jpg")

236

.field("description", "Profile picture")

237

.expect(200);

238

239

// Custom expectations

240

await client

241

.get("/api/status")

242

.expect((res) => {

243

expect(res.body.uptime).to.be.greaterThan(0);

244

expect(res.headers).to.have.property("x-api-version");

245

});

246

```

247

248

### Error Handling

249

250

Proper error handling patterns for HTTP client testing.

251

252

**Usage Examples:**

253

254

```typescript

255

import { createRestAppClient, expect } from "@loopback/testlab";

256

257

// Testing error responses

258

await client

259

.get("/api/nonexistent")

260

.expect(404)

261

.expect({error: "Resource not found"});

262

263

// Testing validation errors

264

await client

265

.post("/api/users")

266

.send({}) // Missing required fields

267

.expect(422)

268

.expect((res) => {

269

expect(res.body.error.details).to.be.an.Array();

270

});

271

272

// Testing authentication errors

273

await client

274

.get("/api/protected")

275

.expect(401)

276

.expect({error: "Unauthorized"});

277

278

// Handling client creation errors

279

try {

280

const nonRunningApp = { restServer: {} }; // No URL

281

const client = createRestAppClient(nonRunningApp);

282

} catch (error) {

283

expect(error.message).to.match(/not listening/);

284

}

285

```