undici 7.3.0 → 7.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,31 +11,44 @@ const {
11
11
  kNetConnect,
12
12
  kGetNetConnect,
13
13
  kOptions,
14
- kFactory
14
+ kFactory,
15
+ kMockAgentRegisterCallHistory,
16
+ kMockAgentIsCallHistoryEnabled,
17
+ kMockAgentAddCallHistoryLog,
18
+ kMockAgentMockCallHistoryInstance,
19
+ kMockCallHistoryAddLog
15
20
  } = require('./mock-symbols')
16
21
  const MockClient = require('./mock-client')
17
22
  const MockPool = require('./mock-pool')
18
- const { matchValue, buildMockOptions } = require('./mock-utils')
23
+ const { matchValue, buildAndValidateMockOptions } = require('./mock-utils')
19
24
  const { InvalidArgumentError, UndiciError } = require('../core/errors')
20
25
  const Dispatcher = require('../dispatcher/dispatcher')
21
26
  const PendingInterceptorsFormatter = require('./pending-interceptors-formatter')
27
+ const { MockCallHistory } = require('./mock-call-history')
22
28
 
23
29
  class MockAgent extends Dispatcher {
24
30
  constructor (opts) {
25
31
  super(opts)
26
32
 
33
+ const mockOptions = buildAndValidateMockOptions(opts)
34
+
27
35
  this[kNetConnect] = true
28
36
  this[kIsMockActive] = true
37
+ this[kMockAgentIsCallHistoryEnabled] = mockOptions?.enableCallHistory ?? false
29
38
 
30
39
  // Instantiate Agent and encapsulate
31
- if ((opts?.agent && typeof opts.agent.dispatch !== 'function')) {
40
+ if (opts?.agent && typeof opts.agent.dispatch !== 'function') {
32
41
  throw new InvalidArgumentError('Argument opts.agent must implement Agent')
33
42
  }
34
43
  const agent = opts?.agent ? opts.agent : new Agent(opts)
35
44
  this[kAgent] = agent
36
45
 
37
46
  this[kClients] = agent[kClients]
38
- this[kOptions] = buildMockOptions(opts)
47
+ this[kOptions] = mockOptions
48
+
49
+ if (this[kMockAgentIsCallHistoryEnabled]) {
50
+ this[kMockAgentRegisterCallHistory]()
51
+ }
39
52
  }
40
53
 
41
54
  get (origin) {
@@ -51,10 +64,14 @@ class MockAgent extends Dispatcher {
51
64
  dispatch (opts, handler) {
52
65
  // Call MockAgent.get to perform additional setup before dispatching as normal
53
66
  this.get(opts.origin)
67
+
68
+ this[kMockAgentAddCallHistoryLog](opts)
69
+
54
70
  return this[kAgent].dispatch(opts, handler)
55
71
  }
56
72
 
57
73
  async close () {
74
+ this.clearCallHistory()
58
75
  await this[kAgent].close()
59
76
  this[kClients].clear()
60
77
  }
@@ -85,12 +102,50 @@ class MockAgent extends Dispatcher {
85
102
  this[kNetConnect] = false
86
103
  }
87
104
 
105
+ enableCallHistory () {
106
+ this[kMockAgentIsCallHistoryEnabled] = true
107
+
108
+ return this
109
+ }
110
+
111
+ disableCallHistory () {
112
+ this[kMockAgentIsCallHistoryEnabled] = false
113
+
114
+ return this
115
+ }
116
+
117
+ getCallHistory () {
118
+ return this[kMockAgentMockCallHistoryInstance]
119
+ }
120
+
121
+ clearCallHistory () {
122
+ if (this[kMockAgentMockCallHistoryInstance] !== undefined) {
123
+ this[kMockAgentMockCallHistoryInstance].clear()
124
+ }
125
+ }
126
+
88
127
  // This is required to bypass issues caused by using global symbols - see:
89
128
  // https://github.com/nodejs/undici/issues/1447
90
129
  get isMockActive () {
91
130
  return this[kIsMockActive]
92
131
  }
93
132
 
133
+ [kMockAgentRegisterCallHistory] () {
134
+ if (this[kMockAgentMockCallHistoryInstance] === undefined) {
135
+ this[kMockAgentMockCallHistoryInstance] = new MockCallHistory()
136
+ }
137
+ }
138
+
139
+ [kMockAgentAddCallHistoryLog] (opts) {
140
+ if (this[kMockAgentIsCallHistoryEnabled]) {
141
+ // additional setup when enableCallHistory class method is used after mockAgent instantiation
142
+ this[kMockAgentRegisterCallHistory]()
143
+
144
+ // add call history log on every call (intercepted or not)
145
+ this[kMockAgentMockCallHistoryInstance][kMockCallHistoryAddLog](opts)
146
+ }
147
+ }
148
+
94
149
  [kMockAgentSet] (origin, dispatcher) {
95
150
  this[kClients].set(origin, dispatcher)
96
151
  }
@@ -0,0 +1,248 @@
1
+ 'use strict'
2
+
3
+ const { kMockCallHistoryAddLog } = require('./mock-symbols')
4
+ const { InvalidArgumentError } = require('../core/errors')
5
+
6
+ function handleFilterCallsWithOptions (criteria, options, handler, store) {
7
+ switch (options.operator) {
8
+ case 'OR':
9
+ store.push(...handler(criteria))
10
+
11
+ return store
12
+ case 'AND':
13
+ return handler.call({ logs: store }, criteria)
14
+ default:
15
+ // guard -- should never happens because buildAndValidateFilterCallsOptions is called before
16
+ throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \'OR\' or \'AND\'')
17
+ }
18
+ }
19
+
20
+ function buildAndValidateFilterCallsOptions (options = {}) {
21
+ const finalOptions = {}
22
+
23
+ if ('operator' in options) {
24
+ if (typeof options.operator !== 'string' || (options.operator.toUpperCase() !== 'OR' && options.operator.toUpperCase() !== 'AND')) {
25
+ throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \'OR\' or \'AND\'')
26
+ }
27
+
28
+ return {
29
+ ...finalOptions,
30
+ operator: options.operator.toUpperCase()
31
+ }
32
+ }
33
+
34
+ return finalOptions
35
+ }
36
+
37
+ function makeFilterCalls (parameterName) {
38
+ return (parameterValue) => {
39
+ if (typeof parameterValue === 'string' || parameterValue == null) {
40
+ return this.logs.filter((log) => {
41
+ return log[parameterName] === parameterValue
42
+ })
43
+ }
44
+ if (parameterValue instanceof RegExp) {
45
+ return this.logs.filter((log) => {
46
+ return parameterValue.test(log[parameterName])
47
+ })
48
+ }
49
+
50
+ throw new InvalidArgumentError(`${parameterName} parameter should be one of string, regexp, undefined or null`)
51
+ }
52
+ }
53
+ function computeUrlWithMaybeSearchParameters (requestInit) {
54
+ // path can contains query url parameters
55
+ // or query can contains query url parameters
56
+ try {
57
+ const url = new URL(requestInit.path, requestInit.origin)
58
+
59
+ // requestInit.path contains query url parameters
60
+ // requestInit.query is then undefined
61
+ if (url.search.length !== 0) {
62
+ return url
63
+ }
64
+
65
+ // requestInit.query can be populated here
66
+ url.search = new URLSearchParams(requestInit.query).toString()
67
+
68
+ return url
69
+ } catch (error) {
70
+ throw new InvalidArgumentError('An error occurred when computing MockCallHistoryLog.url', { cause: error })
71
+ }
72
+ }
73
+
74
+ class MockCallHistoryLog {
75
+ constructor (requestInit = {}) {
76
+ this.body = requestInit.body
77
+ this.headers = requestInit.headers
78
+ this.method = requestInit.method
79
+
80
+ const url = computeUrlWithMaybeSearchParameters(requestInit)
81
+
82
+ this.fullUrl = url.toString()
83
+ this.origin = url.origin
84
+ this.path = url.pathname
85
+ this.searchParams = Object.fromEntries(url.searchParams)
86
+ this.protocol = url.protocol
87
+ this.host = url.host
88
+ this.port = url.port
89
+ this.hash = url.hash
90
+ }
91
+
92
+ toMap () {
93
+ return new Map([
94
+ ['protocol', this.protocol],
95
+ ['host', this.host],
96
+ ['port', this.port],
97
+ ['origin', this.origin],
98
+ ['path', this.path],
99
+ ['hash', this.hash],
100
+ ['searchParams', this.searchParams],
101
+ ['fullUrl', this.fullUrl],
102
+ ['method', this.method],
103
+ ['body', this.body],
104
+ ['headers', this.headers]]
105
+ )
106
+ }
107
+
108
+ toString () {
109
+ const options = { betweenKeyValueSeparator: '->', betweenPairSeparator: '|' }
110
+ let result = ''
111
+
112
+ this.toMap().forEach((value, key) => {
113
+ if (typeof value === 'string' || value === undefined || value === null) {
114
+ result = `${result}${key}${options.betweenKeyValueSeparator}${value}${options.betweenPairSeparator}`
115
+ }
116
+ if ((typeof value === 'object' && value !== null) || Array.isArray(value)) {
117
+ result = `${result}${key}${options.betweenKeyValueSeparator}${JSON.stringify(value)}${options.betweenPairSeparator}`
118
+ }
119
+ // maybe miss something for non Record / Array headers and searchParams here
120
+ })
121
+
122
+ // delete last betweenPairSeparator
123
+ return result.slice(0, -1)
124
+ }
125
+ }
126
+
127
+ class MockCallHistory {
128
+ logs = []
129
+
130
+ calls () {
131
+ return this.logs
132
+ }
133
+
134
+ firstCall () {
135
+ return this.logs.at(0)
136
+ }
137
+
138
+ lastCall () {
139
+ return this.logs.at(-1)
140
+ }
141
+
142
+ nthCall (number) {
143
+ if (typeof number !== 'number') {
144
+ throw new InvalidArgumentError('nthCall must be called with a number')
145
+ }
146
+ if (!Number.isInteger(number)) {
147
+ throw new InvalidArgumentError('nthCall must be called with an integer')
148
+ }
149
+ if (Math.sign(number) !== 1) {
150
+ throw new InvalidArgumentError('nthCall must be called with a positive value. use firstCall or lastCall instead')
151
+ }
152
+
153
+ // non zero based index. this is more human readable
154
+ return this.logs.at(number - 1)
155
+ }
156
+
157
+ filterCalls (criteria, options) {
158
+ // perf
159
+ if (this.logs.length === 0) {
160
+ return this.logs
161
+ }
162
+ if (typeof criteria === 'function') {
163
+ return this.logs.filter(criteria)
164
+ }
165
+ if (criteria instanceof RegExp) {
166
+ return this.logs.filter((log) => {
167
+ return criteria.test(log.toString())
168
+ })
169
+ }
170
+ if (typeof criteria === 'object' && criteria !== null) {
171
+ // no criteria - returning all logs
172
+ if (Object.keys(criteria).length === 0) {
173
+ return this.logs
174
+ }
175
+
176
+ const finalOptions = { operator: 'OR', ...buildAndValidateFilterCallsOptions(options) }
177
+
178
+ let maybeDuplicatedLogsFiltered = []
179
+ if ('protocol' in criteria) {
180
+ maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered)
181
+ }
182
+ if ('host' in criteria) {
183
+ maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered)
184
+ }
185
+ if ('port' in criteria) {
186
+ maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered)
187
+ }
188
+ if ('origin' in criteria) {
189
+ maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered)
190
+ }
191
+ if ('path' in criteria) {
192
+ maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered)
193
+ }
194
+ if ('hash' in criteria) {
195
+ maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered)
196
+ }
197
+ if ('fullUrl' in criteria) {
198
+ maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered)
199
+ }
200
+ if ('method' in criteria) {
201
+ maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered)
202
+ }
203
+
204
+ const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)]
205
+
206
+ return uniqLogsFiltered
207
+ }
208
+
209
+ throw new InvalidArgumentError('criteria parameter should be one of function, regexp, or object')
210
+ }
211
+
212
+ filterCallsByProtocol = makeFilterCalls.call(this, 'protocol')
213
+
214
+ filterCallsByHost = makeFilterCalls.call(this, 'host')
215
+
216
+ filterCallsByPort = makeFilterCalls.call(this, 'port')
217
+
218
+ filterCallsByOrigin = makeFilterCalls.call(this, 'origin')
219
+
220
+ filterCallsByPath = makeFilterCalls.call(this, 'path')
221
+
222
+ filterCallsByHash = makeFilterCalls.call(this, 'hash')
223
+
224
+ filterCallsByFullUrl = makeFilterCalls.call(this, 'fullUrl')
225
+
226
+ filterCallsByMethod = makeFilterCalls.call(this, 'method')
227
+
228
+ clear () {
229
+ this.logs = []
230
+ }
231
+
232
+ [kMockCallHistoryAddLog] (requestInit) {
233
+ const log = new MockCallHistoryLog(requestInit)
234
+
235
+ this.logs.push(log)
236
+
237
+ return log
238
+ }
239
+
240
+ * [Symbol.iterator] () {
241
+ for (const log of this.calls()) {
242
+ yield log
243
+ }
244
+ }
245
+ }
246
+
247
+ module.exports.MockCallHistory = MockCallHistory
248
+ module.exports.MockCallHistoryLog = MockCallHistoryLog
@@ -21,5 +21,10 @@ module.exports = {
21
21
  kNetConnect: Symbol('net connect'),
22
22
  kGetNetConnect: Symbol('get net connect'),
23
23
  kConnected: Symbol('connected'),
24
- kIgnoreTrailingSlash: Symbol('ignore trailing slash')
24
+ kIgnoreTrailingSlash: Symbol('ignore trailing slash'),
25
+ kMockAgentMockCallHistoryInstance: Symbol('mock agent mock call history name'),
26
+ kMockAgentRegisterCallHistory: Symbol('mock agent register mock call history'),
27
+ kMockAgentAddCallHistoryLog: Symbol('mock agent add call history log'),
28
+ kMockAgentIsCallHistoryEnabled: Symbol('mock agent is call history enabled'),
29
+ kMockCallHistoryAddLog: Symbol('mock call history add log')
25
30
  }
@@ -15,6 +15,7 @@ const {
15
15
  isPromise
16
16
  }
17
17
  } = require('node:util')
18
+ const { InvalidArgumentError } = require('../core/errors')
18
19
 
19
20
  function matchValue (match, value) {
20
21
  if (typeof match === 'string') {
@@ -124,8 +125,10 @@ function getResponseData (data) {
124
125
  return data
125
126
  } else if (typeof data === 'object') {
126
127
  return JSON.stringify(data)
127
- } else {
128
+ } else if (data) {
128
129
  return data.toString()
130
+ } else {
131
+ return ''
129
132
  }
130
133
  }
131
134
 
@@ -365,9 +368,14 @@ function checkNetConnect (netConnect, origin) {
365
368
  return false
366
369
  }
367
370
 
368
- function buildMockOptions (opts) {
371
+ function buildAndValidateMockOptions (opts) {
369
372
  if (opts) {
370
373
  const { agent, ...mockOptions } = opts
374
+
375
+ if ('enableCallHistory' in mockOptions && typeof mockOptions.enableCallHistory !== 'boolean') {
376
+ throw new InvalidArgumentError('options.enableCallHistory must to be a boolean')
377
+ }
378
+
371
379
  return mockOptions
372
380
  }
373
381
  }
@@ -385,7 +393,7 @@ module.exports = {
385
393
  mockDispatch,
386
394
  buildMockDispatch,
387
395
  checkNetConnect,
388
- buildMockOptions,
396
+ buildAndValidateMockOptions,
389
397
  getHeaderByName,
390
398
  buildHeadersFromArray
391
399
  }
package/lib/util/cache.js CHANGED
@@ -26,10 +26,14 @@ function makeCacheKey (opts) {
26
26
  if (typeof key !== 'string' || typeof val !== 'string') {
27
27
  throw new Error('opts.headers is not a valid header map')
28
28
  }
29
- headers[key] = val
29
+ headers[key.toLowerCase()] = val
30
30
  }
31
31
  } else if (typeof opts.headers === 'object') {
32
- headers = opts.headers
32
+ headers = {}
33
+
34
+ for (const key of Object.keys(opts.headers)) {
35
+ headers[key.toLowerCase()] = opts.headers[key]
36
+ }
33
37
  } else {
34
38
  throw new Error('opts.headers is not an object')
35
39
  }
@@ -260,19 +264,16 @@ function parseVaryHeader (varyHeader, headers) {
260
264
  return headers
261
265
  }
262
266
 
263
- const output = /** @type {Record<string, string | string[]>} */ ({})
267
+ const output = /** @type {Record<string, string | string[] | null>} */ ({})
264
268
 
265
269
  const varyingHeaders = typeof varyHeader === 'string'
266
270
  ? varyHeader.split(',')
267
271
  : varyHeader
272
+
268
273
  for (const header of varyingHeaders) {
269
274
  const trimmedHeader = header.trim().toLowerCase()
270
275
 
271
- if (headers[trimmedHeader]) {
272
- output[trimmedHeader] = headers[trimmedHeader]
273
- } else {
274
- return undefined
275
- }
276
+ output[trimmedHeader] = headers[trimmedHeader] ?? null
276
277
  }
277
278
 
278
279
  return output
@@ -23,7 +23,7 @@ try {
23
23
  const crypto = require('node:crypto')
24
24
  random = (max) => crypto.randomInt(0, max)
25
25
  } catch {
26
- random = (max) => Math.floor(Math.random(max))
26
+ random = (max) => Math.floor(Math.random() * max)
27
27
  }
28
28
 
29
29
  const textEncoder = new TextEncoder()
@@ -37,6 +37,14 @@ const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => {
37
37
 
38
38
  const dependentControllerMap = new WeakMap()
39
39
 
40
+ let abortSignalHasEventHandlerLeakWarning
41
+
42
+ try {
43
+ abortSignalHasEventHandlerLeakWarning = getMaxListeners(new AbortController().signal) > 0
44
+ } catch {
45
+ abortSignalHasEventHandlerLeakWarning = false
46
+ }
47
+
40
48
  function buildAbort (acRef) {
41
49
  return abort
42
50
 
@@ -424,15 +432,10 @@ class Request {
424
432
  const acRef = new WeakRef(ac)
425
433
  const abort = buildAbort(acRef)
426
434
 
427
- // Third-party AbortControllers may not work with these.
428
- // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619.
429
- try {
430
- // If the max amount of listeners is equal to the default, increase it
431
- // This is only available in node >= v19.9.0
432
- if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) {
433
- setMaxListeners(1500, signal)
434
- }
435
- } catch {}
435
+ // If the max amount of listeners is equal to the default, increase it
436
+ if (abortSignalHasEventHandlerLeakWarning && getMaxListeners(signal) === defaultMaxListeners) {
437
+ setMaxListeners(1500, signal)
438
+ }
436
439
 
437
440
  util.addAbortListener(signal, abort)
438
441
  // The third argument must be a registry key to be unregistered.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "7.3.0",
3
+ "version": "7.5.0",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {
@@ -70,7 +70,7 @@ declare namespace CacheHandler {
70
70
  statusCode: number
71
71
  statusMessage: string
72
72
  headers: Record<string, string | string[]>
73
- vary?: Record<string, string | string[]>
73
+ vary?: Record<string, string | string[] | null>
74
74
  etag?: string
75
75
  cacheControlDirectives?: CacheControlDirectives
76
76
  cachedAt: number
@@ -88,7 +88,7 @@ declare namespace CacheHandler {
88
88
  statusCode: number
89
89
  statusMessage: string
90
90
  headers: Record<string, string | string[]>
91
- vary?: Record<string, string | string[]>
91
+ vary?: Record<string, string | string[] | null>
92
92
  etag?: string
93
93
  body?: Readable | Iterable<Buffer> | AsyncIterable<Buffer> | Buffer | Iterable<string> | AsyncIterable<string> | string
94
94
  cacheControlDirectives: CacheControlDirectives,
package/types/client.d.ts CHANGED
@@ -70,7 +70,7 @@ export declare namespace Client {
70
70
  /** TODO */
71
71
  maxRedirections?: number;
72
72
  /** TODO */
73
- connect?: buildConnector.BuildOptions | buildConnector.connector;
73
+ connect?: Partial<buildConnector.BuildOptions> | buildConnector.connector;
74
74
  /** TODO */
75
75
  maxRequestsPerClient?: number;
76
76
  /** TODO */
package/types/index.d.ts CHANGED
@@ -12,6 +12,7 @@ import Agent from './agent'
12
12
  import MockClient from './mock-client'
13
13
  import MockPool from './mock-pool'
14
14
  import MockAgent from './mock-agent'
15
+ import { MockCallHistory, MockCallHistoryLog } from './mock-call-history'
15
16
  import mockErrors from './mock-errors'
16
17
  import ProxyAgent from './proxy-agent'
17
18
  import EnvHttpProxyAgent from './env-http-proxy-agent'
@@ -31,7 +32,7 @@ export * from './content-type'
31
32
  export * from './cache'
32
33
  export { Interceptable } from './mock-interceptor'
33
34
 
34
- export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, interceptors, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent, EnvHttpProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler, RetryAgent }
35
+ export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, interceptors, MockClient, MockPool, MockAgent, MockCallHistory, MockCallHistoryLog, mockErrors, ProxyAgent, EnvHttpProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler, RetryAgent }
35
36
  export default Undici
36
37
 
37
38
  declare namespace Undici {
@@ -55,6 +56,8 @@ declare namespace Undici {
55
56
  const MockClient: typeof import('./mock-client').default
56
57
  const MockPool: typeof import('./mock-pool').default
57
58
  const MockAgent: typeof import('./mock-agent').default
59
+ const MockCallHistory: typeof import('./mock-call-history').MockCallHistory
60
+ const MockCallHistoryLog: typeof import('./mock-call-history').MockCallHistoryLog
58
61
  const mockErrors: typeof import('./mock-errors').default
59
62
  const fetch: typeof import('./fetch').fetch
60
63
  const Headers: typeof import('./fetch').Headers
@@ -2,6 +2,7 @@ import Agent from './agent'
2
2
  import Dispatcher from './dispatcher'
3
3
  import { Interceptable, MockInterceptor } from './mock-interceptor'
4
4
  import MockDispatch = MockInterceptor.MockDispatch
5
+ import { MockCallHistory } from './mock-call-history'
5
6
 
6
7
  export default MockAgent
7
8
 
@@ -31,6 +32,14 @@ declare class MockAgent<TMockAgentOptions extends MockAgent.Options = MockAgent.
31
32
  enableNetConnect (host: ((host: string) => boolean)): void
32
33
  /** Causes all requests to throw when requests are not matched in a MockAgent intercept. */
33
34
  disableNetConnect (): void
35
+ /** get call history. returns the MockAgent call history or undefined if the option is not enabled. */
36
+ getCallHistory (): MockCallHistory | undefined
37
+ /** clear every call history. Any MockCallHistoryLog will be deleted on the MockCallHistory instance */
38
+ clearCallHistory (): void
39
+ /** Enable call history. Any subsequence calls will then be registered. */
40
+ enableCallHistory (): this
41
+ /** Disable call history. Any subsequence calls will then not be registered. */
42
+ disableCallHistory (): this
34
43
  pendingInterceptors (): PendingInterceptor[]
35
44
  assertNoPendingInterceptors (options?: {
36
45
  pendingInterceptorsFormatter?: PendingInterceptorsFormatter;
@@ -49,5 +58,8 @@ declare namespace MockAgent {
49
58
 
50
59
  /** Ignore trailing slashes in the path */
51
60
  ignoreTrailingSlash?: boolean;
61
+
62
+ /** Enable call history. you can either call MockAgent.enableCallHistory(). default false */
63
+ enableCallHistory?: boolean
52
64
  }
53
65
  }