or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# @pollyjs/adapter-fetch

1

2

The @pollyjs/adapter-fetch package provides a fetch adapter that enables seamless recording and replaying of HTTP interactions using the browser's native fetch API and Request/Response objects. It integrates with Polly.JS to intercept fetch calls, preserve request/response data, and replay interactions for deterministic testing.

3

4

## Package Information

5

6

- **Package Name**: @pollyjs/adapter-fetch

7

- **Package Type**: npm

8

- **Language**: JavaScript (with TypeScript definitions)

9

- **Installation**: `npm install @pollyjs/adapter-fetch -D`

10

11

## Core Imports

12

13

```javascript

14

import FetchAdapter from '@pollyjs/adapter-fetch';

15

```

16

17

For CommonJS:

18

19

```javascript

20

const FetchAdapter = require('@pollyjs/adapter-fetch');

21

```

22

23

## Basic Usage

24

25

```javascript

26

import { Polly } from '@pollyjs/core';

27

import FetchAdapter from '@pollyjs/adapter-fetch';

28

29

// Register the adapter with Polly

30

Polly.register(FetchAdapter);

31

32

// Create a Polly instance that uses the fetch adapter

33

const polly = new Polly('Recording Name', {

34

adapters: ['fetch']

35

});

36

37

// The adapter will now intercept all fetch calls

38

const response = await fetch('/api/users');

39

const data = await response.json();

40

41

// Stop recording/replaying

42

await polly.stop();

43

```

44

45

## Capabilities

46

47

### FetchAdapter Class

48

49

The main adapter class that extends the base Polly.JS Adapter to provide fetch API interception and request/response handling.

50

51

```javascript { .api }

52

/**

53

* Fetch adapter that patches the global fetch function and Request constructor

54

* to enable recording and replaying of HTTP interactions.

55

*/

56

export default class FetchAdapter extends Adapter {

57

/**

58

* Static identifier for the adapter

59

* @returns {string} Always returns 'fetch'

60

*/

61

static get id(): string;

62

63

/**

64

* Default configuration options for the adapter

65

* @returns {object} Configuration object with context property

66

*/

67

get defaultOptions(): {

68

context?: any; // Global context object (default: global)

69

};

70

71

/**

72

* Called when adapter connects to Polly instance.

73

* Patches global fetch and Request constructor.

74

*/

75

onConnect(): void;

76

77

/**

78

* Called when adapter disconnects from Polly instance.

79

* Restores original global fetch and Request constructor.

80

*/

81

onDisconnect(): void;

82

83

/**

84

* Called when a request is being processed.

85

* Handles abort signal setup and event listeners.

86

* @param {object} pollyRequest - The Polly request object

87

*/

88

onRequest(pollyRequest: object): void;

89

90

/**

91

* Makes the actual fetch request and processes the response.

92

* Handles binary data conversion and buffer compatibility.

93

* @param {object} pollyRequest - The Polly request object

94

* @returns {Promise<object>} Response object with statusCode, headers, body, encoding

95

*/

96

async onFetchResponse(pollyRequest: object): Promise<{

97

statusCode: number;

98

headers: object;

99

body: string;

100

encoding?: string;

101

}>;

102

103

/**

104

* Called when responding to the original caller.

105

* Handles response construction and error scenarios.

106

* @param {object} pollyRequest - The Polly request object

107

* @param {Error} error - Any error that occurred during processing

108

*/

109

onRespond(pollyRequest: object, error?: Error): void;

110

}

111

```

112

113

### Configuration Options

114

115

The adapter accepts configuration options through the Polly instance:

116

117

```javascript { .api }

118

interface AdapterOptions {

119

/**

120

* Global context object containing fetch, Request, Response, Headers.

121

* Defaults to the global object (window in browsers, global in Node.js).

122

*/

123

context?: {

124

fetch: Function;

125

Request: new (url: string | Request, options?: RequestInit) => Request;

126

Response: new (body?: any, options?: ResponseInit) => Response;

127

Headers: new (headers?: HeadersInit) => Headers;

128

};

129

}

130

```

131

132

**Usage Example:**

133

134

```javascript

135

const polly = new Polly('Recording', {

136

adapters: ['fetch'],

137

adapterOptions: {

138

fetch: {

139

context: window // Explicitly specify the global context

140

}

141

}

142

});

143

```

144

145

## Features

146

147

### Request Interception

148

149

The adapter patches the global `fetch` function to intercept all fetch calls, supporting:

150

151

- **URL objects**: Accepts both string URLs and URL instances

152

- **Request objects**: Supports fetch calls with Request instances

153

- **All fetch options**: Headers, method, body, credentials, etc.

154

- **Request cloning**: Maintains fetch API clone semantics

155

156

### Response Handling

157

158

Comprehensive response processing including:

159

160

- **Binary data support**: Handles both text and binary response bodies

161

- **Encoding preservation**: Uses base64 encoding for binary content

162

- **Header serialization**: Converts Headers instances to plain objects

163

- **Status code mapping**: Preserves HTTP status codes and status text

164

- **Empty response handling**: Correctly handles 204 No Content responses

165

166

### Abort Signal Support

167

168

Full AbortController/AbortSignal integration:

169

170

```javascript

171

const controller = new AbortController();

172

173

// This request can be aborted

174

fetch('/api/data', { signal: controller.signal });

175

176

// Abort the request

177

controller.abort(); // Throws DOMException with name 'AbortError'

178

```

179

180

### Cross-Environment Compatibility

181

182

The adapter works across different JavaScript environments:

183

184

- **Browser environments**: Uses window.fetch and related globals

185

- **Node.js environments**: Works with fetch polyfills or native Node.js fetch

186

- **Different contexts**: Supports custom global contexts for testing scenarios

187

188

### Error Handling

189

190

Robust error handling for various scenarios:

191

192

- **Missing globals**: Validates fetch, Request, Response, Headers are available

193

- **Concurrent adapters**: Prevents multiple fetch adapters from running simultaneously

194

- **Network errors**: Properly propagates fetch network failures

195

- **Abort scenarios**: Handles request cancellation with proper DOMException

196

- **Buffer compatibility**: Manages ArrayBuffer differences across contexts

197

198

## Internal Implementation Details

199

200

The adapter uses several internal symbols and patterns:

201

202

- **Symbol-based marking**: Uses symbols to mark patched globals and prevent double-patching

203

- **Argument preservation**: Stores original Request constructor arguments for proper cloning

204

- **Lazy execution**: Operations are queued and executed when needed

205

- **Response URL fixing**: Manually sets response.url since Response constructor doesn't allow it

206

207

## Error Types

208

209

```javascript { .api }

210

/**

211

* Errors that may be thrown by the adapter

212

*/

213

interface AdapterErrors {

214

/** Thrown when required globals (fetch, Request, etc.) are not found */

215

AssertionError: Error;

216

217

/** Thrown when request is aborted via AbortSignal */

218

AbortError: DOMException;

219

220

/** Network or other fetch-related errors */

221

TypeError: Error;

222

}

223

```

224

225

**Common Error Scenarios:**

226

227

```javascript

228

// Missing globals

229

// Error: "fetch global not found."

230

231

// Concurrent adapters

232

// Error: "Running concurrent fetch adapters is unsupported, stop any running Polly instances."

233

234

// Aborted request

235

// DOMException: "The user aborted a request." (name: 'AbortError')

236

```

237

238

## Advanced Usage Patterns

239

240

### Custom Context

241

242

For testing or specialized environments:

243

244

```javascript

245

const customGlobals = {

246

fetch: mockFetch,

247

Request: MockRequest,

248

Response: MockResponse,

249

Headers: MockHeaders

250

};

251

252

const polly = new Polly('Test', {

253

adapters: ['fetch'],

254

adapterOptions: {

255

fetch: {

256

context: customGlobals

257

}

258

}

259

});

260

```

261

262

### Integration with Testing

263

264

Common pattern for test suites:

265

266

```javascript

267

import { Polly } from '@pollyjs/core';

268

import FetchAdapter from '@pollyjs/adapter-fetch';

269

270

// Register once in test setup

271

Polly.register(FetchAdapter);

272

273

describe('API Tests', () => {

274

let polly;

275

276

beforeEach(() => {

277

polly = new Polly('API Test', {

278

adapters: ['fetch'],

279

recordIfMissing: false // Use existing recordings

280

});

281

});

282

283

afterEach(async () => {

284

await polly.stop();

285

});

286

287

it('fetches user data', async () => {

288

const response = await fetch('/api/users/1');

289

const user = await response.json();

290

291

expect(user.id).toBe(1);

292

});

293

});

294

```