format: prettify entire project
This commit is contained in:
217
node_modules/undici/lib/mock/mock-agent.js
generated
vendored
217
node_modules/undici/lib/mock/mock-agent.js
generated
vendored
@ -1,7 +1,7 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
const { kClients } = require('../core/symbols')
|
||||
const Agent = require('../dispatcher/agent')
|
||||
const { kClients } = require('../core/symbols');
|
||||
const Agent = require('../dispatcher/agent');
|
||||
const {
|
||||
kAgent,
|
||||
kMockAgentSet,
|
||||
@ -16,197 +16,216 @@ const {
|
||||
kMockAgentIsCallHistoryEnabled,
|
||||
kMockAgentAddCallHistoryLog,
|
||||
kMockAgentMockCallHistoryInstance,
|
||||
kMockCallHistoryAddLog
|
||||
} = require('./mock-symbols')
|
||||
const MockClient = require('./mock-client')
|
||||
const MockPool = require('./mock-pool')
|
||||
const { matchValue, buildAndValidateMockOptions } = require('./mock-utils')
|
||||
const { InvalidArgumentError, UndiciError } = require('../core/errors')
|
||||
const Dispatcher = require('../dispatcher/dispatcher')
|
||||
const PendingInterceptorsFormatter = require('./pending-interceptors-formatter')
|
||||
const { MockCallHistory } = require('./mock-call-history')
|
||||
kMockCallHistoryAddLog,
|
||||
} = require('./mock-symbols');
|
||||
const MockClient = require('./mock-client');
|
||||
const MockPool = require('./mock-pool');
|
||||
const { matchValue, buildAndValidateMockOptions } = require('./mock-utils');
|
||||
const { InvalidArgumentError, UndiciError } = require('../core/errors');
|
||||
const Dispatcher = require('../dispatcher/dispatcher');
|
||||
const PendingInterceptorsFormatter = require('./pending-interceptors-formatter');
|
||||
const { MockCallHistory } = require('./mock-call-history');
|
||||
|
||||
class MockAgent extends Dispatcher {
|
||||
constructor (opts) {
|
||||
super(opts)
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
|
||||
const mockOptions = buildAndValidateMockOptions(opts)
|
||||
const mockOptions = buildAndValidateMockOptions(opts);
|
||||
|
||||
this[kNetConnect] = true
|
||||
this[kIsMockActive] = true
|
||||
this[kMockAgentIsCallHistoryEnabled] = mockOptions?.enableCallHistory ?? false
|
||||
this[kNetConnect] = true;
|
||||
this[kIsMockActive] = true;
|
||||
this[kMockAgentIsCallHistoryEnabled] =
|
||||
mockOptions?.enableCallHistory ?? false;
|
||||
|
||||
// Instantiate Agent and encapsulate
|
||||
if (opts?.agent && typeof opts.agent.dispatch !== 'function') {
|
||||
throw new InvalidArgumentError('Argument opts.agent must implement Agent')
|
||||
throw new InvalidArgumentError(
|
||||
'Argument opts.agent must implement Agent'
|
||||
);
|
||||
}
|
||||
const agent = opts?.agent ? opts.agent : new Agent(opts)
|
||||
this[kAgent] = agent
|
||||
const agent = opts?.agent ? opts.agent : new Agent(opts);
|
||||
this[kAgent] = agent;
|
||||
|
||||
this[kClients] = agent[kClients]
|
||||
this[kOptions] = mockOptions
|
||||
this[kClients] = agent[kClients];
|
||||
this[kOptions] = mockOptions;
|
||||
|
||||
if (this[kMockAgentIsCallHistoryEnabled]) {
|
||||
this[kMockAgentRegisterCallHistory]()
|
||||
this[kMockAgentRegisterCallHistory]();
|
||||
}
|
||||
}
|
||||
|
||||
get (origin) {
|
||||
let dispatcher = this[kMockAgentGet](origin)
|
||||
get(origin) {
|
||||
let dispatcher = this[kMockAgentGet](origin);
|
||||
|
||||
if (!dispatcher) {
|
||||
dispatcher = this[kFactory](origin)
|
||||
this[kMockAgentSet](origin, dispatcher)
|
||||
dispatcher = this[kFactory](origin);
|
||||
this[kMockAgentSet](origin, dispatcher);
|
||||
}
|
||||
return dispatcher
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
dispatch (opts, handler) {
|
||||
dispatch(opts, handler) {
|
||||
// Call MockAgent.get to perform additional setup before dispatching as normal
|
||||
this.get(opts.origin)
|
||||
this.get(opts.origin);
|
||||
|
||||
this[kMockAgentAddCallHistoryLog](opts)
|
||||
this[kMockAgentAddCallHistoryLog](opts);
|
||||
|
||||
return this[kAgent].dispatch(opts, handler)
|
||||
return this[kAgent].dispatch(opts, handler);
|
||||
}
|
||||
|
||||
async close () {
|
||||
this.clearCallHistory()
|
||||
await this[kAgent].close()
|
||||
this[kClients].clear()
|
||||
async close() {
|
||||
this.clearCallHistory();
|
||||
await this[kAgent].close();
|
||||
this[kClients].clear();
|
||||
}
|
||||
|
||||
deactivate () {
|
||||
this[kIsMockActive] = false
|
||||
deactivate() {
|
||||
this[kIsMockActive] = false;
|
||||
}
|
||||
|
||||
activate () {
|
||||
this[kIsMockActive] = true
|
||||
activate() {
|
||||
this[kIsMockActive] = true;
|
||||
}
|
||||
|
||||
enableNetConnect (matcher) {
|
||||
if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) {
|
||||
enableNetConnect(matcher) {
|
||||
if (
|
||||
typeof matcher === 'string' ||
|
||||
typeof matcher === 'function' ||
|
||||
matcher instanceof RegExp
|
||||
) {
|
||||
if (Array.isArray(this[kNetConnect])) {
|
||||
this[kNetConnect].push(matcher)
|
||||
this[kNetConnect].push(matcher);
|
||||
} else {
|
||||
this[kNetConnect] = [matcher]
|
||||
this[kNetConnect] = [matcher];
|
||||
}
|
||||
} else if (typeof matcher === 'undefined') {
|
||||
this[kNetConnect] = true
|
||||
this[kNetConnect] = true;
|
||||
} else {
|
||||
throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.')
|
||||
throw new InvalidArgumentError(
|
||||
'Unsupported matcher. Must be one of String|Function|RegExp.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
disableNetConnect () {
|
||||
this[kNetConnect] = false
|
||||
disableNetConnect() {
|
||||
this[kNetConnect] = false;
|
||||
}
|
||||
|
||||
enableCallHistory () {
|
||||
this[kMockAgentIsCallHistoryEnabled] = true
|
||||
enableCallHistory() {
|
||||
this[kMockAgentIsCallHistoryEnabled] = true;
|
||||
|
||||
return this
|
||||
return this;
|
||||
}
|
||||
|
||||
disableCallHistory () {
|
||||
this[kMockAgentIsCallHistoryEnabled] = false
|
||||
disableCallHistory() {
|
||||
this[kMockAgentIsCallHistoryEnabled] = false;
|
||||
|
||||
return this
|
||||
return this;
|
||||
}
|
||||
|
||||
getCallHistory () {
|
||||
return this[kMockAgentMockCallHistoryInstance]
|
||||
getCallHistory() {
|
||||
return this[kMockAgentMockCallHistoryInstance];
|
||||
}
|
||||
|
||||
clearCallHistory () {
|
||||
clearCallHistory() {
|
||||
if (this[kMockAgentMockCallHistoryInstance] !== undefined) {
|
||||
this[kMockAgentMockCallHistoryInstance].clear()
|
||||
this[kMockAgentMockCallHistoryInstance].clear();
|
||||
}
|
||||
}
|
||||
|
||||
// This is required to bypass issues caused by using global symbols - see:
|
||||
// https://github.com/nodejs/undici/issues/1447
|
||||
get isMockActive () {
|
||||
return this[kIsMockActive]
|
||||
get isMockActive() {
|
||||
return this[kIsMockActive];
|
||||
}
|
||||
|
||||
[kMockAgentRegisterCallHistory] () {
|
||||
[kMockAgentRegisterCallHistory]() {
|
||||
if (this[kMockAgentMockCallHistoryInstance] === undefined) {
|
||||
this[kMockAgentMockCallHistoryInstance] = new MockCallHistory()
|
||||
this[kMockAgentMockCallHistoryInstance] = new MockCallHistory();
|
||||
}
|
||||
}
|
||||
|
||||
[kMockAgentAddCallHistoryLog] (opts) {
|
||||
[kMockAgentAddCallHistoryLog](opts) {
|
||||
if (this[kMockAgentIsCallHistoryEnabled]) {
|
||||
// additional setup when enableCallHistory class method is used after mockAgent instantiation
|
||||
this[kMockAgentRegisterCallHistory]()
|
||||
this[kMockAgentRegisterCallHistory]();
|
||||
|
||||
// add call history log on every call (intercepted or not)
|
||||
this[kMockAgentMockCallHistoryInstance][kMockCallHistoryAddLog](opts)
|
||||
this[kMockAgentMockCallHistoryInstance][kMockCallHistoryAddLog](opts);
|
||||
}
|
||||
}
|
||||
|
||||
[kMockAgentSet] (origin, dispatcher) {
|
||||
this[kClients].set(origin, dispatcher)
|
||||
[kMockAgentSet](origin, dispatcher) {
|
||||
this[kClients].set(origin, dispatcher);
|
||||
}
|
||||
|
||||
[kFactory] (origin) {
|
||||
const mockOptions = Object.assign({ agent: this }, this[kOptions])
|
||||
return this[kOptions] && this[kOptions].connections === 1
|
||||
? new MockClient(origin, mockOptions)
|
||||
: new MockPool(origin, mockOptions)
|
||||
[kFactory](origin) {
|
||||
const mockOptions = Object.assign({ agent: this }, this[kOptions]);
|
||||
return this[kOptions] && this[kOptions].connections === 1 ?
|
||||
new MockClient(origin, mockOptions)
|
||||
: new MockPool(origin, mockOptions);
|
||||
}
|
||||
|
||||
[kMockAgentGet] (origin) {
|
||||
[kMockAgentGet](origin) {
|
||||
// First check if we can immediately find it
|
||||
const client = this[kClients].get(origin)
|
||||
const client = this[kClients].get(origin);
|
||||
if (client) {
|
||||
return client
|
||||
return client;
|
||||
}
|
||||
|
||||
// If the origin is not a string create a dummy parent pool and return to user
|
||||
if (typeof origin !== 'string') {
|
||||
const dispatcher = this[kFactory]('http://localhost:9999')
|
||||
this[kMockAgentSet](origin, dispatcher)
|
||||
return dispatcher
|
||||
const dispatcher = this[kFactory]('http://localhost:9999');
|
||||
this[kMockAgentSet](origin, dispatcher);
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
// If we match, create a pool and assign the same dispatches
|
||||
for (const [keyMatcher, nonExplicitDispatcher] of Array.from(this[kClients])) {
|
||||
if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) {
|
||||
const dispatcher = this[kFactory](origin)
|
||||
this[kMockAgentSet](origin, dispatcher)
|
||||
dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches]
|
||||
return dispatcher
|
||||
for (const [keyMatcher, nonExplicitDispatcher] of Array.from(
|
||||
this[kClients]
|
||||
)) {
|
||||
if (
|
||||
nonExplicitDispatcher &&
|
||||
typeof keyMatcher !== 'string' &&
|
||||
matchValue(keyMatcher, origin)
|
||||
) {
|
||||
const dispatcher = this[kFactory](origin);
|
||||
this[kMockAgentSet](origin, dispatcher);
|
||||
dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches];
|
||||
return dispatcher;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[kGetNetConnect] () {
|
||||
return this[kNetConnect]
|
||||
[kGetNetConnect]() {
|
||||
return this[kNetConnect];
|
||||
}
|
||||
|
||||
pendingInterceptors () {
|
||||
const mockAgentClients = this[kClients]
|
||||
pendingInterceptors() {
|
||||
const mockAgentClients = this[kClients];
|
||||
|
||||
return Array.from(mockAgentClients.entries())
|
||||
.flatMap(([origin, scope]) => scope[kDispatches].map(dispatch => ({ ...dispatch, origin })))
|
||||
.filter(({ pending }) => pending)
|
||||
.flatMap(([origin, scope]) =>
|
||||
scope[kDispatches].map((dispatch) => ({ ...dispatch, origin }))
|
||||
)
|
||||
.filter(({ pending }) => pending);
|
||||
}
|
||||
|
||||
assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) {
|
||||
const pending = this.pendingInterceptors()
|
||||
assertNoPendingInterceptors({
|
||||
pendingInterceptorsFormatter = new PendingInterceptorsFormatter(),
|
||||
} = {}) {
|
||||
const pending = this.pendingInterceptors();
|
||||
|
||||
if (pending.length === 0) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
throw new UndiciError(
|
||||
pending.length === 1
|
||||
? `1 interceptor is pending:\n\n${pendingInterceptorsFormatter.format(pending)}`.trim()
|
||||
: `${pending.length} interceptors are pending:\n\n${pendingInterceptorsFormatter.format(pending)}`.trim()
|
||||
)
|
||||
pending.length === 1 ?
|
||||
`1 interceptor is pending:\n\n${pendingInterceptorsFormatter.format(pending)}`.trim()
|
||||
: `${pending.length} interceptors are pending:\n\n${pendingInterceptorsFormatter.format(pending)}`.trim()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MockAgent
|
||||
module.exports = MockAgent;
|
||||
|
268
node_modules/undici/lib/mock/mock-call-history.js
generated
vendored
268
node_modules/undici/lib/mock/mock-call-history.js
generated
vendored
@ -1,95 +1,108 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
const { kMockCallHistoryAddLog } = require('./mock-symbols')
|
||||
const { InvalidArgumentError } = require('../core/errors')
|
||||
const { kMockCallHistoryAddLog } = require('./mock-symbols');
|
||||
const { InvalidArgumentError } = require('../core/errors');
|
||||
|
||||
function handleFilterCallsWithOptions (criteria, options, handler, store) {
|
||||
function handleFilterCallsWithOptions(criteria, options, handler, store) {
|
||||
switch (options.operator) {
|
||||
case 'OR':
|
||||
store.push(...handler(criteria))
|
||||
store.push(...handler(criteria));
|
||||
|
||||
return store
|
||||
return store;
|
||||
case 'AND':
|
||||
return handler.call({ logs: store }, criteria)
|
||||
return handler.call({ logs: store }, criteria);
|
||||
default:
|
||||
// guard -- should never happens because buildAndValidateFilterCallsOptions is called before
|
||||
throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \'OR\' or \'AND\'')
|
||||
throw new InvalidArgumentError(
|
||||
"options.operator must to be a case insensitive string equal to 'OR' or 'AND'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function buildAndValidateFilterCallsOptions (options = {}) {
|
||||
const finalOptions = {}
|
||||
function buildAndValidateFilterCallsOptions(options = {}) {
|
||||
const finalOptions = {};
|
||||
|
||||
if ('operator' in options) {
|
||||
if (typeof options.operator !== 'string' || (options.operator.toUpperCase() !== 'OR' && options.operator.toUpperCase() !== 'AND')) {
|
||||
throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \'OR\' or \'AND\'')
|
||||
if (
|
||||
typeof options.operator !== 'string' ||
|
||||
(options.operator.toUpperCase() !== 'OR' &&
|
||||
options.operator.toUpperCase() !== 'AND')
|
||||
) {
|
||||
throw new InvalidArgumentError(
|
||||
"options.operator must to be a case insensitive string equal to 'OR' or 'AND'"
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...finalOptions,
|
||||
operator: options.operator.toUpperCase()
|
||||
}
|
||||
operator: options.operator.toUpperCase(),
|
||||
};
|
||||
}
|
||||
|
||||
return finalOptions
|
||||
return finalOptions;
|
||||
}
|
||||
|
||||
function makeFilterCalls (parameterName) {
|
||||
function makeFilterCalls(parameterName) {
|
||||
return (parameterValue) => {
|
||||
if (typeof parameterValue === 'string' || parameterValue == null) {
|
||||
return this.logs.filter((log) => {
|
||||
return log[parameterName] === parameterValue
|
||||
})
|
||||
return log[parameterName] === parameterValue;
|
||||
});
|
||||
}
|
||||
if (parameterValue instanceof RegExp) {
|
||||
return this.logs.filter((log) => {
|
||||
return parameterValue.test(log[parameterName])
|
||||
})
|
||||
return parameterValue.test(log[parameterName]);
|
||||
});
|
||||
}
|
||||
|
||||
throw new InvalidArgumentError(`${parameterName} parameter should be one of string, regexp, undefined or null`)
|
||||
}
|
||||
throw new InvalidArgumentError(
|
||||
`${parameterName} parameter should be one of string, regexp, undefined or null`
|
||||
);
|
||||
};
|
||||
}
|
||||
function computeUrlWithMaybeSearchParameters (requestInit) {
|
||||
function computeUrlWithMaybeSearchParameters(requestInit) {
|
||||
// path can contains query url parameters
|
||||
// or query can contains query url parameters
|
||||
try {
|
||||
const url = new URL(requestInit.path, requestInit.origin)
|
||||
const url = new URL(requestInit.path, requestInit.origin);
|
||||
|
||||
// requestInit.path contains query url parameters
|
||||
// requestInit.query is then undefined
|
||||
if (url.search.length !== 0) {
|
||||
return url
|
||||
return url;
|
||||
}
|
||||
|
||||
// requestInit.query can be populated here
|
||||
url.search = new URLSearchParams(requestInit.query).toString()
|
||||
url.search = new URLSearchParams(requestInit.query).toString();
|
||||
|
||||
return url
|
||||
return url;
|
||||
} catch (error) {
|
||||
throw new InvalidArgumentError('An error occurred when computing MockCallHistoryLog.url', { cause: error })
|
||||
throw new InvalidArgumentError(
|
||||
'An error occurred when computing MockCallHistoryLog.url',
|
||||
{ cause: error }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MockCallHistoryLog {
|
||||
constructor (requestInit = {}) {
|
||||
this.body = requestInit.body
|
||||
this.headers = requestInit.headers
|
||||
this.method = requestInit.method
|
||||
constructor(requestInit = {}) {
|
||||
this.body = requestInit.body;
|
||||
this.headers = requestInit.headers;
|
||||
this.method = requestInit.method;
|
||||
|
||||
const url = computeUrlWithMaybeSearchParameters(requestInit)
|
||||
const url = computeUrlWithMaybeSearchParameters(requestInit);
|
||||
|
||||
this.fullUrl = url.toString()
|
||||
this.origin = url.origin
|
||||
this.path = url.pathname
|
||||
this.searchParams = Object.fromEntries(url.searchParams)
|
||||
this.protocol = url.protocol
|
||||
this.host = url.host
|
||||
this.port = url.port
|
||||
this.hash = url.hash
|
||||
this.fullUrl = url.toString();
|
||||
this.origin = url.origin;
|
||||
this.path = url.pathname;
|
||||
this.searchParams = Object.fromEntries(url.searchParams);
|
||||
this.protocol = url.protocol;
|
||||
this.host = url.host;
|
||||
this.port = url.port;
|
||||
this.hash = url.hash;
|
||||
}
|
||||
|
||||
toMap () {
|
||||
toMap() {
|
||||
return new Map([
|
||||
['protocol', this.protocol],
|
||||
['host', this.host],
|
||||
@ -101,148 +114,201 @@ class MockCallHistoryLog {
|
||||
['fullUrl', this.fullUrl],
|
||||
['method', this.method],
|
||||
['body', this.body],
|
||||
['headers', this.headers]]
|
||||
)
|
||||
['headers', this.headers],
|
||||
]);
|
||||
}
|
||||
|
||||
toString () {
|
||||
const options = { betweenKeyValueSeparator: '->', betweenPairSeparator: '|' }
|
||||
let result = ''
|
||||
toString() {
|
||||
const options = {
|
||||
betweenKeyValueSeparator: '->',
|
||||
betweenPairSeparator: '|',
|
||||
};
|
||||
let result = '';
|
||||
|
||||
this.toMap().forEach((value, key) => {
|
||||
if (typeof value === 'string' || value === undefined || value === null) {
|
||||
result = `${result}${key}${options.betweenKeyValueSeparator}${value}${options.betweenPairSeparator}`
|
||||
result = `${result}${key}${options.betweenKeyValueSeparator}${value}${options.betweenPairSeparator}`;
|
||||
}
|
||||
if ((typeof value === 'object' && value !== null) || Array.isArray(value)) {
|
||||
result = `${result}${key}${options.betweenKeyValueSeparator}${JSON.stringify(value)}${options.betweenPairSeparator}`
|
||||
if (
|
||||
(typeof value === 'object' && value !== null) ||
|
||||
Array.isArray(value)
|
||||
) {
|
||||
result = `${result}${key}${options.betweenKeyValueSeparator}${JSON.stringify(value)}${options.betweenPairSeparator}`;
|
||||
}
|
||||
// maybe miss something for non Record / Array headers and searchParams here
|
||||
})
|
||||
});
|
||||
|
||||
// delete last betweenPairSeparator
|
||||
return result.slice(0, -1)
|
||||
return result.slice(0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
class MockCallHistory {
|
||||
logs = []
|
||||
logs = [];
|
||||
|
||||
calls () {
|
||||
return this.logs
|
||||
calls() {
|
||||
return this.logs;
|
||||
}
|
||||
|
||||
firstCall () {
|
||||
return this.logs.at(0)
|
||||
firstCall() {
|
||||
return this.logs.at(0);
|
||||
}
|
||||
|
||||
lastCall () {
|
||||
return this.logs.at(-1)
|
||||
lastCall() {
|
||||
return this.logs.at(-1);
|
||||
}
|
||||
|
||||
nthCall (number) {
|
||||
nthCall(number) {
|
||||
if (typeof number !== 'number') {
|
||||
throw new InvalidArgumentError('nthCall must be called with a number')
|
||||
throw new InvalidArgumentError('nthCall must be called with a number');
|
||||
}
|
||||
if (!Number.isInteger(number)) {
|
||||
throw new InvalidArgumentError('nthCall must be called with an integer')
|
||||
throw new InvalidArgumentError('nthCall must be called with an integer');
|
||||
}
|
||||
if (Math.sign(number) !== 1) {
|
||||
throw new InvalidArgumentError('nthCall must be called with a positive value. use firstCall or lastCall instead')
|
||||
throw new InvalidArgumentError(
|
||||
'nthCall must be called with a positive value. use firstCall or lastCall instead'
|
||||
);
|
||||
}
|
||||
|
||||
// non zero based index. this is more human readable
|
||||
return this.logs.at(number - 1)
|
||||
return this.logs.at(number - 1);
|
||||
}
|
||||
|
||||
filterCalls (criteria, options) {
|
||||
filterCalls(criteria, options) {
|
||||
// perf
|
||||
if (this.logs.length === 0) {
|
||||
return this.logs
|
||||
return this.logs;
|
||||
}
|
||||
if (typeof criteria === 'function') {
|
||||
return this.logs.filter(criteria)
|
||||
return this.logs.filter(criteria);
|
||||
}
|
||||
if (criteria instanceof RegExp) {
|
||||
return this.logs.filter((log) => {
|
||||
return criteria.test(log.toString())
|
||||
})
|
||||
return criteria.test(log.toString());
|
||||
});
|
||||
}
|
||||
if (typeof criteria === 'object' && criteria !== null) {
|
||||
// no criteria - returning all logs
|
||||
if (Object.keys(criteria).length === 0) {
|
||||
return this.logs
|
||||
return this.logs;
|
||||
}
|
||||
|
||||
const finalOptions = { operator: 'OR', ...buildAndValidateFilterCallsOptions(options) }
|
||||
const finalOptions = {
|
||||
operator: 'OR',
|
||||
...buildAndValidateFilterCallsOptions(options),
|
||||
};
|
||||
|
||||
let maybeDuplicatedLogsFiltered = []
|
||||
let maybeDuplicatedLogsFiltered = [];
|
||||
if ('protocol' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered)
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(
|
||||
criteria.protocol,
|
||||
finalOptions,
|
||||
this.filterCallsByProtocol,
|
||||
maybeDuplicatedLogsFiltered
|
||||
);
|
||||
}
|
||||
if ('host' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered)
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(
|
||||
criteria.host,
|
||||
finalOptions,
|
||||
this.filterCallsByHost,
|
||||
maybeDuplicatedLogsFiltered
|
||||
);
|
||||
}
|
||||
if ('port' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered)
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(
|
||||
criteria.port,
|
||||
finalOptions,
|
||||
this.filterCallsByPort,
|
||||
maybeDuplicatedLogsFiltered
|
||||
);
|
||||
}
|
||||
if ('origin' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered)
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(
|
||||
criteria.origin,
|
||||
finalOptions,
|
||||
this.filterCallsByOrigin,
|
||||
maybeDuplicatedLogsFiltered
|
||||
);
|
||||
}
|
||||
if ('path' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered)
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(
|
||||
criteria.path,
|
||||
finalOptions,
|
||||
this.filterCallsByPath,
|
||||
maybeDuplicatedLogsFiltered
|
||||
);
|
||||
}
|
||||
if ('hash' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered)
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(
|
||||
criteria.hash,
|
||||
finalOptions,
|
||||
this.filterCallsByHash,
|
||||
maybeDuplicatedLogsFiltered
|
||||
);
|
||||
}
|
||||
if ('fullUrl' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered)
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(
|
||||
criteria.fullUrl,
|
||||
finalOptions,
|
||||
this.filterCallsByFullUrl,
|
||||
maybeDuplicatedLogsFiltered
|
||||
);
|
||||
}
|
||||
if ('method' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered)
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(
|
||||
criteria.method,
|
||||
finalOptions,
|
||||
this.filterCallsByMethod,
|
||||
maybeDuplicatedLogsFiltered
|
||||
);
|
||||
}
|
||||
|
||||
const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)]
|
||||
const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)];
|
||||
|
||||
return uniqLogsFiltered
|
||||
return uniqLogsFiltered;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentError('criteria parameter should be one of function, regexp, or object')
|
||||
throw new InvalidArgumentError(
|
||||
'criteria parameter should be one of function, regexp, or object'
|
||||
);
|
||||
}
|
||||
|
||||
filterCallsByProtocol = makeFilterCalls.call(this, 'protocol')
|
||||
filterCallsByProtocol = makeFilterCalls.call(this, 'protocol');
|
||||
|
||||
filterCallsByHost = makeFilterCalls.call(this, 'host')
|
||||
filterCallsByHost = makeFilterCalls.call(this, 'host');
|
||||
|
||||
filterCallsByPort = makeFilterCalls.call(this, 'port')
|
||||
filterCallsByPort = makeFilterCalls.call(this, 'port');
|
||||
|
||||
filterCallsByOrigin = makeFilterCalls.call(this, 'origin')
|
||||
filterCallsByOrigin = makeFilterCalls.call(this, 'origin');
|
||||
|
||||
filterCallsByPath = makeFilterCalls.call(this, 'path')
|
||||
filterCallsByPath = makeFilterCalls.call(this, 'path');
|
||||
|
||||
filterCallsByHash = makeFilterCalls.call(this, 'hash')
|
||||
filterCallsByHash = makeFilterCalls.call(this, 'hash');
|
||||
|
||||
filterCallsByFullUrl = makeFilterCalls.call(this, 'fullUrl')
|
||||
filterCallsByFullUrl = makeFilterCalls.call(this, 'fullUrl');
|
||||
|
||||
filterCallsByMethod = makeFilterCalls.call(this, 'method')
|
||||
filterCallsByMethod = makeFilterCalls.call(this, 'method');
|
||||
|
||||
clear () {
|
||||
this.logs = []
|
||||
clear() {
|
||||
this.logs = [];
|
||||
}
|
||||
|
||||
[kMockCallHistoryAddLog] (requestInit) {
|
||||
const log = new MockCallHistoryLog(requestInit)
|
||||
[kMockCallHistoryAddLog](requestInit) {
|
||||
const log = new MockCallHistoryLog(requestInit);
|
||||
|
||||
this.logs.push(log)
|
||||
this.logs.push(log);
|
||||
|
||||
return log
|
||||
return log;
|
||||
}
|
||||
|
||||
* [Symbol.iterator] () {
|
||||
*[Symbol.iterator]() {
|
||||
for (const log of this.calls()) {
|
||||
yield log
|
||||
yield log;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.MockCallHistory = MockCallHistory
|
||||
module.exports.MockCallHistoryLog = MockCallHistoryLog
|
||||
module.exports.MockCallHistory = MockCallHistory;
|
||||
module.exports.MockCallHistoryLog = MockCallHistoryLog;
|
||||
|
62
node_modules/undici/lib/mock/mock-client.js
generated
vendored
62
node_modules/undici/lib/mock/mock-client.js
generated
vendored
@ -1,8 +1,8 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
const { promisify } = require('node:util')
|
||||
const Client = require('../dispatcher/client')
|
||||
const { buildMockDispatch } = require('./mock-utils')
|
||||
const { promisify } = require('node:util');
|
||||
const Client = require('../dispatcher/client');
|
||||
const { buildMockDispatch } = require('./mock-utils');
|
||||
const {
|
||||
kDispatches,
|
||||
kMockAgent,
|
||||
@ -11,54 +11,56 @@ const {
|
||||
kOrigin,
|
||||
kOriginalDispatch,
|
||||
kConnected,
|
||||
kIgnoreTrailingSlash
|
||||
} = require('./mock-symbols')
|
||||
const { MockInterceptor } = require('./mock-interceptor')
|
||||
const Symbols = require('../core/symbols')
|
||||
const { InvalidArgumentError } = require('../core/errors')
|
||||
kIgnoreTrailingSlash,
|
||||
} = require('./mock-symbols');
|
||||
const { MockInterceptor } = require('./mock-interceptor');
|
||||
const Symbols = require('../core/symbols');
|
||||
const { InvalidArgumentError } = require('../core/errors');
|
||||
|
||||
/**
|
||||
* MockClient provides an API that extends the Client to influence the mockDispatches.
|
||||
*/
|
||||
class MockClient extends Client {
|
||||
constructor (origin, opts) {
|
||||
constructor(origin, opts) {
|
||||
if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') {
|
||||
throw new InvalidArgumentError('Argument opts.agent must implement Agent')
|
||||
throw new InvalidArgumentError(
|
||||
'Argument opts.agent must implement Agent'
|
||||
);
|
||||
}
|
||||
|
||||
super(origin, opts)
|
||||
super(origin, opts);
|
||||
|
||||
this[kMockAgent] = opts.agent
|
||||
this[kOrigin] = origin
|
||||
this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false
|
||||
this[kDispatches] = []
|
||||
this[kConnected] = 1
|
||||
this[kOriginalDispatch] = this.dispatch
|
||||
this[kOriginalClose] = this.close.bind(this)
|
||||
this[kMockAgent] = opts.agent;
|
||||
this[kOrigin] = origin;
|
||||
this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false;
|
||||
this[kDispatches] = [];
|
||||
this[kConnected] = 1;
|
||||
this[kOriginalDispatch] = this.dispatch;
|
||||
this[kOriginalClose] = this.close.bind(this);
|
||||
|
||||
this.dispatch = buildMockDispatch.call(this)
|
||||
this.close = this[kClose]
|
||||
this.dispatch = buildMockDispatch.call(this);
|
||||
this.close = this[kClose];
|
||||
}
|
||||
|
||||
get [Symbols.kConnected] () {
|
||||
return this[kConnected]
|
||||
get [Symbols.kConnected]() {
|
||||
return this[kConnected];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the base interceptor for mocking replies from undici.
|
||||
*/
|
||||
intercept (opts) {
|
||||
intercept(opts) {
|
||||
return new MockInterceptor(
|
||||
opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts },
|
||||
this[kDispatches]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async [kClose] () {
|
||||
await promisify(this[kOriginalClose])()
|
||||
this[kConnected] = 0
|
||||
this[kMockAgent][Symbols.kClients].delete(this[kOrigin])
|
||||
async [kClose]() {
|
||||
await promisify(this[kOriginalClose])();
|
||||
this[kConnected] = 0;
|
||||
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MockClient
|
||||
module.exports = MockClient;
|
||||
|
19
node_modules/undici/lib/mock/mock-errors.js
generated
vendored
19
node_modules/undici/lib/mock/mock-errors.js
generated
vendored
@ -1,19 +1,20 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
const { UndiciError } = require('../core/errors')
|
||||
const { UndiciError } = require('../core/errors');
|
||||
|
||||
/**
|
||||
* The request does not match any registered mock dispatches.
|
||||
*/
|
||||
class MockNotMatchedError extends UndiciError {
|
||||
constructor (message) {
|
||||
super(message)
|
||||
this.name = 'MockNotMatchedError'
|
||||
this.message = message || 'The request does not match any registered mock dispatches'
|
||||
this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED'
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'MockNotMatchedError';
|
||||
this.message =
|
||||
message || 'The request does not match any registered mock dispatches';
|
||||
this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
MockNotMatchedError
|
||||
}
|
||||
MockNotMatchedError,
|
||||
};
|
||||
|
193
node_modules/undici/lib/mock/mock-interceptor.js
generated
vendored
193
node_modules/undici/lib/mock/mock-interceptor.js
generated
vendored
@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
const { getResponseData, buildKey, addMockDispatch } = require('./mock-utils')
|
||||
const { getResponseData, buildKey, addMockDispatch } = require('./mock-utils');
|
||||
const {
|
||||
kDispatches,
|
||||
kDispatchKey,
|
||||
@ -8,49 +8,57 @@ const {
|
||||
kDefaultTrailers,
|
||||
kContentLength,
|
||||
kMockDispatch,
|
||||
kIgnoreTrailingSlash
|
||||
} = require('./mock-symbols')
|
||||
const { InvalidArgumentError } = require('../core/errors')
|
||||
const { serializePathWithQuery } = require('../core/util')
|
||||
kIgnoreTrailingSlash,
|
||||
} = require('./mock-symbols');
|
||||
const { InvalidArgumentError } = require('../core/errors');
|
||||
const { serializePathWithQuery } = require('../core/util');
|
||||
|
||||
/**
|
||||
* Defines the scope API for an interceptor reply
|
||||
*/
|
||||
class MockScope {
|
||||
constructor (mockDispatch) {
|
||||
this[kMockDispatch] = mockDispatch
|
||||
constructor(mockDispatch) {
|
||||
this[kMockDispatch] = mockDispatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delay a reply by a set amount in ms.
|
||||
*/
|
||||
delay (waitInMs) {
|
||||
if (typeof waitInMs !== 'number' || !Number.isInteger(waitInMs) || waitInMs <= 0) {
|
||||
throw new InvalidArgumentError('waitInMs must be a valid integer > 0')
|
||||
delay(waitInMs) {
|
||||
if (
|
||||
typeof waitInMs !== 'number' ||
|
||||
!Number.isInteger(waitInMs) ||
|
||||
waitInMs <= 0
|
||||
) {
|
||||
throw new InvalidArgumentError('waitInMs must be a valid integer > 0');
|
||||
}
|
||||
|
||||
this[kMockDispatch].delay = waitInMs
|
||||
return this
|
||||
this[kMockDispatch].delay = waitInMs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a defined reply, never mark as consumed.
|
||||
*/
|
||||
persist () {
|
||||
this[kMockDispatch].persist = true
|
||||
return this
|
||||
persist() {
|
||||
this[kMockDispatch].persist = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow one to define a reply for a set amount of matching requests.
|
||||
*/
|
||||
times (repeatTimes) {
|
||||
if (typeof repeatTimes !== 'number' || !Number.isInteger(repeatTimes) || repeatTimes <= 0) {
|
||||
throw new InvalidArgumentError('repeatTimes must be a valid integer > 0')
|
||||
times(repeatTimes) {
|
||||
if (
|
||||
typeof repeatTimes !== 'number' ||
|
||||
!Number.isInteger(repeatTimes) ||
|
||||
repeatTimes <= 0
|
||||
) {
|
||||
throw new InvalidArgumentError('repeatTimes must be a valid integer > 0');
|
||||
}
|
||||
|
||||
this[kMockDispatch].times = repeatTimes
|
||||
return this
|
||||
this[kMockDispatch].times = repeatTimes;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,62 +66,70 @@ class MockScope {
|
||||
* Defines an interceptor for a Mock
|
||||
*/
|
||||
class MockInterceptor {
|
||||
constructor (opts, mockDispatches) {
|
||||
constructor(opts, mockDispatches) {
|
||||
if (typeof opts !== 'object') {
|
||||
throw new InvalidArgumentError('opts must be an object')
|
||||
throw new InvalidArgumentError('opts must be an object');
|
||||
}
|
||||
if (typeof opts.path === 'undefined') {
|
||||
throw new InvalidArgumentError('opts.path must be defined')
|
||||
throw new InvalidArgumentError('opts.path must be defined');
|
||||
}
|
||||
if (typeof opts.method === 'undefined') {
|
||||
opts.method = 'GET'
|
||||
opts.method = 'GET';
|
||||
}
|
||||
// See https://github.com/nodejs/undici/issues/1245
|
||||
// As per RFC 3986, clients are not supposed to send URI
|
||||
// fragments to servers when they retrieve a document,
|
||||
if (typeof opts.path === 'string') {
|
||||
if (opts.query) {
|
||||
opts.path = serializePathWithQuery(opts.path, opts.query)
|
||||
opts.path = serializePathWithQuery(opts.path, opts.query);
|
||||
} else {
|
||||
// Matches https://github.com/nodejs/undici/blob/main/lib/web/fetch/index.js#L1811
|
||||
const parsedURL = new URL(opts.path, 'data://')
|
||||
opts.path = parsedURL.pathname + parsedURL.search
|
||||
const parsedURL = new URL(opts.path, 'data://');
|
||||
opts.path = parsedURL.pathname + parsedURL.search;
|
||||
}
|
||||
}
|
||||
if (typeof opts.method === 'string') {
|
||||
opts.method = opts.method.toUpperCase()
|
||||
opts.method = opts.method.toUpperCase();
|
||||
}
|
||||
|
||||
this[kDispatchKey] = buildKey(opts)
|
||||
this[kDispatches] = mockDispatches
|
||||
this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false
|
||||
this[kDefaultHeaders] = {}
|
||||
this[kDefaultTrailers] = {}
|
||||
this[kContentLength] = false
|
||||
this[kDispatchKey] = buildKey(opts);
|
||||
this[kDispatches] = mockDispatches;
|
||||
this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false;
|
||||
this[kDefaultHeaders] = {};
|
||||
this[kDefaultTrailers] = {};
|
||||
this[kContentLength] = false;
|
||||
}
|
||||
|
||||
createMockScopeDispatchData ({ statusCode, data, responseOptions }) {
|
||||
const responseData = getResponseData(data)
|
||||
const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {}
|
||||
const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers }
|
||||
const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers }
|
||||
createMockScopeDispatchData({ statusCode, data, responseOptions }) {
|
||||
const responseData = getResponseData(data);
|
||||
const contentLength =
|
||||
this[kContentLength] ? { 'content-length': responseData.length } : {};
|
||||
const headers = {
|
||||
...this[kDefaultHeaders],
|
||||
...contentLength,
|
||||
...responseOptions.headers,
|
||||
};
|
||||
const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers };
|
||||
|
||||
return { statusCode, data, headers, trailers }
|
||||
return { statusCode, data, headers, trailers };
|
||||
}
|
||||
|
||||
validateReplyParameters (replyParameters) {
|
||||
validateReplyParameters(replyParameters) {
|
||||
if (typeof replyParameters.statusCode === 'undefined') {
|
||||
throw new InvalidArgumentError('statusCode must be defined')
|
||||
throw new InvalidArgumentError('statusCode must be defined');
|
||||
}
|
||||
if (typeof replyParameters.responseOptions !== 'object' || replyParameters.responseOptions === null) {
|
||||
throw new InvalidArgumentError('responseOptions must be an object')
|
||||
if (
|
||||
typeof replyParameters.responseOptions !== 'object' ||
|
||||
replyParameters.responseOptions === null
|
||||
) {
|
||||
throw new InvalidArgumentError('responseOptions must be an object');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock an undici request with a defined reply.
|
||||
*/
|
||||
reply (replyOptionsCallbackOrStatusCode) {
|
||||
reply(replyOptionsCallbackOrStatusCode) {
|
||||
// Values of reply aren't available right now as they
|
||||
// can only be available when the reply callback is invoked.
|
||||
if (typeof replyOptionsCallbackOrStatusCode === 'function') {
|
||||
@ -122,25 +138,36 @@ class MockInterceptor {
|
||||
// when invoked.
|
||||
const wrappedDefaultsCallback = (opts) => {
|
||||
// Our reply options callback contains the parameter for statusCode, data and options.
|
||||
const resolvedData = replyOptionsCallbackOrStatusCode(opts)
|
||||
const resolvedData = replyOptionsCallbackOrStatusCode(opts);
|
||||
|
||||
// Check if it is in the right format
|
||||
if (typeof resolvedData !== 'object' || resolvedData === null) {
|
||||
throw new InvalidArgumentError('reply options callback must return an object')
|
||||
throw new InvalidArgumentError(
|
||||
'reply options callback must return an object'
|
||||
);
|
||||
}
|
||||
|
||||
const replyParameters = { data: '', responseOptions: {}, ...resolvedData }
|
||||
this.validateReplyParameters(replyParameters)
|
||||
const replyParameters = {
|
||||
data: '',
|
||||
responseOptions: {},
|
||||
...resolvedData,
|
||||
};
|
||||
this.validateReplyParameters(replyParameters);
|
||||
// Since the values can be obtained immediately we return them
|
||||
// from this higher order function that will be resolved later.
|
||||
return {
|
||||
...this.createMockScopeDispatchData(replyParameters)
|
||||
}
|
||||
}
|
||||
...this.createMockScopeDispatchData(replyParameters),
|
||||
};
|
||||
};
|
||||
|
||||
// Add usual dispatch data, but this time set the data parameter to function that will eventually provide data.
|
||||
const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] })
|
||||
return new MockScope(newMockDispatch)
|
||||
const newMockDispatch = addMockDispatch(
|
||||
this[kDispatches],
|
||||
this[kDispatchKey],
|
||||
wrappedDefaultsCallback,
|
||||
{ ignoreTrailingSlash: this[kIgnoreTrailingSlash] }
|
||||
);
|
||||
return new MockScope(newMockDispatch);
|
||||
}
|
||||
|
||||
// We can have either one or three parameters, if we get here,
|
||||
@ -150,60 +177,70 @@ class MockInterceptor {
|
||||
const replyParameters = {
|
||||
statusCode: replyOptionsCallbackOrStatusCode,
|
||||
data: arguments[1] === undefined ? '' : arguments[1],
|
||||
responseOptions: arguments[2] === undefined ? {} : arguments[2]
|
||||
}
|
||||
this.validateReplyParameters(replyParameters)
|
||||
responseOptions: arguments[2] === undefined ? {} : arguments[2],
|
||||
};
|
||||
this.validateReplyParameters(replyParameters);
|
||||
|
||||
// Send in-already provided data like usual
|
||||
const dispatchData = this.createMockScopeDispatchData(replyParameters)
|
||||
const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] })
|
||||
return new MockScope(newMockDispatch)
|
||||
const dispatchData = this.createMockScopeDispatchData(replyParameters);
|
||||
const newMockDispatch = addMockDispatch(
|
||||
this[kDispatches],
|
||||
this[kDispatchKey],
|
||||
dispatchData,
|
||||
{ ignoreTrailingSlash: this[kIgnoreTrailingSlash] }
|
||||
);
|
||||
return new MockScope(newMockDispatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock an undici request with a defined error.
|
||||
*/
|
||||
replyWithError (error) {
|
||||
replyWithError(error) {
|
||||
if (typeof error === 'undefined') {
|
||||
throw new InvalidArgumentError('error must be defined')
|
||||
throw new InvalidArgumentError('error must be defined');
|
||||
}
|
||||
|
||||
const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error }, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] })
|
||||
return new MockScope(newMockDispatch)
|
||||
const newMockDispatch = addMockDispatch(
|
||||
this[kDispatches],
|
||||
this[kDispatchKey],
|
||||
{ error },
|
||||
{ ignoreTrailingSlash: this[kIgnoreTrailingSlash] }
|
||||
);
|
||||
return new MockScope(newMockDispatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default reply headers on the interceptor for subsequent replies
|
||||
*/
|
||||
defaultReplyHeaders (headers) {
|
||||
defaultReplyHeaders(headers) {
|
||||
if (typeof headers === 'undefined') {
|
||||
throw new InvalidArgumentError('headers must be defined')
|
||||
throw new InvalidArgumentError('headers must be defined');
|
||||
}
|
||||
|
||||
this[kDefaultHeaders] = headers
|
||||
return this
|
||||
this[kDefaultHeaders] = headers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default reply trailers on the interceptor for subsequent replies
|
||||
*/
|
||||
defaultReplyTrailers (trailers) {
|
||||
defaultReplyTrailers(trailers) {
|
||||
if (typeof trailers === 'undefined') {
|
||||
throw new InvalidArgumentError('trailers must be defined')
|
||||
throw new InvalidArgumentError('trailers must be defined');
|
||||
}
|
||||
|
||||
this[kDefaultTrailers] = trailers
|
||||
return this
|
||||
this[kDefaultTrailers] = trailers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set reply content length header for replies on the interceptor
|
||||
*/
|
||||
replyContentLength () {
|
||||
this[kContentLength] = true
|
||||
return this
|
||||
replyContentLength() {
|
||||
this[kContentLength] = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.MockInterceptor = MockInterceptor
|
||||
module.exports.MockScope = MockScope
|
||||
module.exports.MockInterceptor = MockInterceptor;
|
||||
module.exports.MockScope = MockScope;
|
||||
|
62
node_modules/undici/lib/mock/mock-pool.js
generated
vendored
62
node_modules/undici/lib/mock/mock-pool.js
generated
vendored
@ -1,8 +1,8 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
const { promisify } = require('node:util')
|
||||
const Pool = require('../dispatcher/pool')
|
||||
const { buildMockDispatch } = require('./mock-utils')
|
||||
const { promisify } = require('node:util');
|
||||
const Pool = require('../dispatcher/pool');
|
||||
const { buildMockDispatch } = require('./mock-utils');
|
||||
const {
|
||||
kDispatches,
|
||||
kMockAgent,
|
||||
@ -11,54 +11,56 @@ const {
|
||||
kOrigin,
|
||||
kOriginalDispatch,
|
||||
kConnected,
|
||||
kIgnoreTrailingSlash
|
||||
} = require('./mock-symbols')
|
||||
const { MockInterceptor } = require('./mock-interceptor')
|
||||
const Symbols = require('../core/symbols')
|
||||
const { InvalidArgumentError } = require('../core/errors')
|
||||
kIgnoreTrailingSlash,
|
||||
} = require('./mock-symbols');
|
||||
const { MockInterceptor } = require('./mock-interceptor');
|
||||
const Symbols = require('../core/symbols');
|
||||
const { InvalidArgumentError } = require('../core/errors');
|
||||
|
||||
/**
|
||||
* MockPool provides an API that extends the Pool to influence the mockDispatches.
|
||||
*/
|
||||
class MockPool extends Pool {
|
||||
constructor (origin, opts) {
|
||||
constructor(origin, opts) {
|
||||
if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') {
|
||||
throw new InvalidArgumentError('Argument opts.agent must implement Agent')
|
||||
throw new InvalidArgumentError(
|
||||
'Argument opts.agent must implement Agent'
|
||||
);
|
||||
}
|
||||
|
||||
super(origin, opts)
|
||||
super(origin, opts);
|
||||
|
||||
this[kMockAgent] = opts.agent
|
||||
this[kOrigin] = origin
|
||||
this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false
|
||||
this[kDispatches] = []
|
||||
this[kConnected] = 1
|
||||
this[kOriginalDispatch] = this.dispatch
|
||||
this[kOriginalClose] = this.close.bind(this)
|
||||
this[kMockAgent] = opts.agent;
|
||||
this[kOrigin] = origin;
|
||||
this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false;
|
||||
this[kDispatches] = [];
|
||||
this[kConnected] = 1;
|
||||
this[kOriginalDispatch] = this.dispatch;
|
||||
this[kOriginalClose] = this.close.bind(this);
|
||||
|
||||
this.dispatch = buildMockDispatch.call(this)
|
||||
this.close = this[kClose]
|
||||
this.dispatch = buildMockDispatch.call(this);
|
||||
this.close = this[kClose];
|
||||
}
|
||||
|
||||
get [Symbols.kConnected] () {
|
||||
return this[kConnected]
|
||||
get [Symbols.kConnected]() {
|
||||
return this[kConnected];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the base interceptor for mocking replies from undici.
|
||||
*/
|
||||
intercept (opts) {
|
||||
intercept(opts) {
|
||||
return new MockInterceptor(
|
||||
opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts },
|
||||
this[kDispatches]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async [kClose] () {
|
||||
await promisify(this[kOriginalClose])()
|
||||
this[kConnected] = 0
|
||||
this[kMockAgent][Symbols.kClients].delete(this[kOrigin])
|
||||
async [kClose]() {
|
||||
await promisify(this[kOriginalClose])();
|
||||
this[kConnected] = 0;
|
||||
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MockPool
|
||||
module.exports = MockPool;
|
||||
|
14
node_modules/undici/lib/mock/mock-symbols.js
generated
vendored
14
node_modules/undici/lib/mock/mock-symbols.js
generated
vendored
@ -1,4 +1,4 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
kAgent: Symbol('agent'),
|
||||
@ -22,9 +22,13 @@ module.exports = {
|
||||
kGetNetConnect: Symbol('get net connect'),
|
||||
kConnected: Symbol('connected'),
|
||||
kIgnoreTrailingSlash: Symbol('ignore trailing slash'),
|
||||
kMockAgentMockCallHistoryInstance: Symbol('mock agent mock call history name'),
|
||||
kMockAgentRegisterCallHistory: Symbol('mock agent register mock call history'),
|
||||
kMockAgentMockCallHistoryInstance: Symbol(
|
||||
'mock agent mock call history name'
|
||||
),
|
||||
kMockAgentRegisterCallHistory: Symbol(
|
||||
'mock agent register mock call history'
|
||||
),
|
||||
kMockAgentAddCallHistoryLog: Symbol('mock agent add call history log'),
|
||||
kMockAgentIsCallHistoryEnabled: Symbol('mock agent is call history enabled'),
|
||||
kMockCallHistoryAddLog: Symbol('mock call history add log')
|
||||
}
|
||||
kMockCallHistoryAddLog: Symbol('mock call history add log'),
|
||||
};
|
||||
|
407
node_modules/undici/lib/mock/mock-utils.js
generated
vendored
407
node_modules/undici/lib/mock/mock-utils.js
generated
vendored
@ -1,305 +1,353 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
const { MockNotMatchedError } = require('./mock-errors')
|
||||
const { MockNotMatchedError } = require('./mock-errors');
|
||||
const {
|
||||
kDispatches,
|
||||
kMockAgent,
|
||||
kOriginalDispatch,
|
||||
kOrigin,
|
||||
kGetNetConnect
|
||||
} = require('./mock-symbols')
|
||||
const { serializePathWithQuery } = require('../core/util')
|
||||
const { STATUS_CODES } = require('node:http')
|
||||
kGetNetConnect,
|
||||
} = require('./mock-symbols');
|
||||
const { serializePathWithQuery } = require('../core/util');
|
||||
const { STATUS_CODES } = require('node:http');
|
||||
const {
|
||||
types: {
|
||||
isPromise
|
||||
}
|
||||
} = require('node:util')
|
||||
const { InvalidArgumentError } = require('../core/errors')
|
||||
types: { isPromise },
|
||||
} = require('node:util');
|
||||
const { InvalidArgumentError } = require('../core/errors');
|
||||
|
||||
function matchValue (match, value) {
|
||||
function matchValue(match, value) {
|
||||
if (typeof match === 'string') {
|
||||
return match === value
|
||||
return match === value;
|
||||
}
|
||||
if (match instanceof RegExp) {
|
||||
return match.test(value)
|
||||
return match.test(value);
|
||||
}
|
||||
if (typeof match === 'function') {
|
||||
return match(value) === true
|
||||
return match(value) === true;
|
||||
}
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
function lowerCaseEntries (headers) {
|
||||
function lowerCaseEntries(headers) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(headers).map(([headerName, headerValue]) => {
|
||||
return [headerName.toLocaleLowerCase(), headerValue]
|
||||
return [headerName.toLocaleLowerCase(), headerValue];
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../../index').Headers|string[]|Record<string, string>} headers
|
||||
* @param {string} key
|
||||
*/
|
||||
function getHeaderByName (headers, key) {
|
||||
function getHeaderByName(headers, key) {
|
||||
if (Array.isArray(headers)) {
|
||||
for (let i = 0; i < headers.length; i += 2) {
|
||||
if (headers[i].toLocaleLowerCase() === key.toLocaleLowerCase()) {
|
||||
return headers[i + 1]
|
||||
return headers[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
return undefined;
|
||||
} else if (typeof headers.get === 'function') {
|
||||
return headers.get(key)
|
||||
return headers.get(key);
|
||||
} else {
|
||||
return lowerCaseEntries(headers)[key.toLocaleLowerCase()]
|
||||
return lowerCaseEntries(headers)[key.toLocaleLowerCase()];
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {string[]} headers */
|
||||
function buildHeadersFromArray (headers) { // fetch HeadersList
|
||||
const clone = headers.slice()
|
||||
const entries = []
|
||||
function buildHeadersFromArray(headers) {
|
||||
// fetch HeadersList
|
||||
const clone = headers.slice();
|
||||
const entries = [];
|
||||
for (let index = 0; index < clone.length; index += 2) {
|
||||
entries.push([clone[index], clone[index + 1]])
|
||||
entries.push([clone[index], clone[index + 1]]);
|
||||
}
|
||||
return Object.fromEntries(entries)
|
||||
return Object.fromEntries(entries);
|
||||
}
|
||||
|
||||
function matchHeaders (mockDispatch, headers) {
|
||||
function matchHeaders(mockDispatch, headers) {
|
||||
if (typeof mockDispatch.headers === 'function') {
|
||||
if (Array.isArray(headers)) { // fetch HeadersList
|
||||
headers = buildHeadersFromArray(headers)
|
||||
if (Array.isArray(headers)) {
|
||||
// fetch HeadersList
|
||||
headers = buildHeadersFromArray(headers);
|
||||
}
|
||||
return mockDispatch.headers(headers ? lowerCaseEntries(headers) : {})
|
||||
return mockDispatch.headers(headers ? lowerCaseEntries(headers) : {});
|
||||
}
|
||||
if (typeof mockDispatch.headers === 'undefined') {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
if (typeof headers !== 'object' || typeof mockDispatch.headers !== 'object') {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) {
|
||||
const headerValue = getHeaderByName(headers, matchHeaderName)
|
||||
for (const [matchHeaderName, matchHeaderValue] of Object.entries(
|
||||
mockDispatch.headers
|
||||
)) {
|
||||
const headerValue = getHeaderByName(headers, matchHeaderName);
|
||||
|
||||
if (!matchValue(matchHeaderValue, headerValue)) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
function safeUrl (path) {
|
||||
function safeUrl(path) {
|
||||
if (typeof path !== 'string') {
|
||||
return path
|
||||
return path;
|
||||
}
|
||||
|
||||
const pathSegments = path.split('?', 3)
|
||||
const pathSegments = path.split('?', 3);
|
||||
|
||||
if (pathSegments.length !== 2) {
|
||||
return path
|
||||
return path;
|
||||
}
|
||||
|
||||
const qp = new URLSearchParams(pathSegments.pop())
|
||||
qp.sort()
|
||||
return [...pathSegments, qp.toString()].join('?')
|
||||
const qp = new URLSearchParams(pathSegments.pop());
|
||||
qp.sort();
|
||||
return [...pathSegments, qp.toString()].join('?');
|
||||
}
|
||||
|
||||
function matchKey (mockDispatch, { path, method, body, headers }) {
|
||||
const pathMatch = matchValue(mockDispatch.path, path)
|
||||
const methodMatch = matchValue(mockDispatch.method, method)
|
||||
const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true
|
||||
const headersMatch = matchHeaders(mockDispatch, headers)
|
||||
return pathMatch && methodMatch && bodyMatch && headersMatch
|
||||
function matchKey(mockDispatch, { path, method, body, headers }) {
|
||||
const pathMatch = matchValue(mockDispatch.path, path);
|
||||
const methodMatch = matchValue(mockDispatch.method, method);
|
||||
const bodyMatch =
|
||||
typeof mockDispatch.body !== 'undefined' ?
|
||||
matchValue(mockDispatch.body, body)
|
||||
: true;
|
||||
const headersMatch = matchHeaders(mockDispatch, headers);
|
||||
return pathMatch && methodMatch && bodyMatch && headersMatch;
|
||||
}
|
||||
|
||||
function getResponseData (data) {
|
||||
function getResponseData(data) {
|
||||
if (Buffer.isBuffer(data)) {
|
||||
return data
|
||||
return data;
|
||||
} else if (data instanceof Uint8Array) {
|
||||
return data
|
||||
return data;
|
||||
} else if (data instanceof ArrayBuffer) {
|
||||
return data
|
||||
return data;
|
||||
} else if (typeof data === 'object') {
|
||||
return JSON.stringify(data)
|
||||
return JSON.stringify(data);
|
||||
} else if (data) {
|
||||
return data.toString()
|
||||
return data.toString();
|
||||
} else {
|
||||
return ''
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function getMockDispatch (mockDispatches, key) {
|
||||
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path
|
||||
const resolvedPath = typeof basePath === 'string' ? safeUrl(basePath) : basePath
|
||||
function getMockDispatch(mockDispatches, key) {
|
||||
const basePath =
|
||||
key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
||||
const resolvedPath =
|
||||
typeof basePath === 'string' ? safeUrl(basePath) : basePath;
|
||||
|
||||
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath)
|
||||
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
||||
|
||||
// Match path
|
||||
let matchedMockDispatches = mockDispatches
|
||||
.filter(({ consumed }) => !consumed)
|
||||
.filter(({ path, ignoreTrailingSlash }) => {
|
||||
return ignoreTrailingSlash
|
||||
? matchValue(removeTrailingSlash(safeUrl(path)), resolvedPathWithoutTrailingSlash)
|
||||
: matchValue(safeUrl(path), resolvedPath)
|
||||
})
|
||||
return ignoreTrailingSlash ?
|
||||
matchValue(
|
||||
removeTrailingSlash(safeUrl(path)),
|
||||
resolvedPathWithoutTrailingSlash
|
||||
)
|
||||
: matchValue(safeUrl(path), resolvedPath);
|
||||
});
|
||||
if (matchedMockDispatches.length === 0) {
|
||||
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`)
|
||||
throw new MockNotMatchedError(
|
||||
`Mock dispatch not matched for path '${resolvedPath}'`
|
||||
);
|
||||
}
|
||||
|
||||
// Match method
|
||||
matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method))
|
||||
matchedMockDispatches = matchedMockDispatches.filter(({ method }) =>
|
||||
matchValue(method, key.method)
|
||||
);
|
||||
if (matchedMockDispatches.length === 0) {
|
||||
throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}' on path '${resolvedPath}'`)
|
||||
throw new MockNotMatchedError(
|
||||
`Mock dispatch not matched for method '${key.method}' on path '${resolvedPath}'`
|
||||
);
|
||||
}
|
||||
|
||||
// Match body
|
||||
matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true)
|
||||
matchedMockDispatches = matchedMockDispatches.filter(({ body }) =>
|
||||
typeof body !== 'undefined' ? matchValue(body, key.body) : true
|
||||
);
|
||||
if (matchedMockDispatches.length === 0) {
|
||||
throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}' on path '${resolvedPath}'`)
|
||||
throw new MockNotMatchedError(
|
||||
`Mock dispatch not matched for body '${key.body}' on path '${resolvedPath}'`
|
||||
);
|
||||
}
|
||||
|
||||
// Match headers
|
||||
matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers))
|
||||
matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) =>
|
||||
matchHeaders(mockDispatch, key.headers)
|
||||
);
|
||||
if (matchedMockDispatches.length === 0) {
|
||||
const headers = typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers
|
||||
throw new MockNotMatchedError(`Mock dispatch not matched for headers '${headers}' on path '${resolvedPath}'`)
|
||||
const headers =
|
||||
typeof key.headers === 'object' ?
|
||||
JSON.stringify(key.headers)
|
||||
: key.headers;
|
||||
throw new MockNotMatchedError(
|
||||
`Mock dispatch not matched for headers '${headers}' on path '${resolvedPath}'`
|
||||
);
|
||||
}
|
||||
|
||||
return matchedMockDispatches[0]
|
||||
return matchedMockDispatches[0];
|
||||
}
|
||||
|
||||
function addMockDispatch (mockDispatches, key, data, opts) {
|
||||
const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false, ...opts }
|
||||
const replyData = typeof data === 'function' ? { callback: data } : { ...data }
|
||||
const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } }
|
||||
mockDispatches.push(newMockDispatch)
|
||||
return newMockDispatch
|
||||
function addMockDispatch(mockDispatches, key, data, opts) {
|
||||
const baseData = {
|
||||
timesInvoked: 0,
|
||||
times: 1,
|
||||
persist: false,
|
||||
consumed: false,
|
||||
...opts,
|
||||
};
|
||||
const replyData =
|
||||
typeof data === 'function' ? { callback: data } : { ...data };
|
||||
const newMockDispatch = {
|
||||
...baseData,
|
||||
...key,
|
||||
pending: true,
|
||||
data: { error: null, ...replyData },
|
||||
};
|
||||
mockDispatches.push(newMockDispatch);
|
||||
return newMockDispatch;
|
||||
}
|
||||
|
||||
function deleteMockDispatch (mockDispatches, key) {
|
||||
const index = mockDispatches.findIndex(dispatch => {
|
||||
function deleteMockDispatch(mockDispatches, key) {
|
||||
const index = mockDispatches.findIndex((dispatch) => {
|
||||
if (!dispatch.consumed) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
return matchKey(dispatch, key)
|
||||
})
|
||||
return matchKey(dispatch, key);
|
||||
});
|
||||
if (index !== -1) {
|
||||
mockDispatches.splice(index, 1)
|
||||
mockDispatches.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} path Path to remove trailing slash from
|
||||
*/
|
||||
function removeTrailingSlash (path) {
|
||||
function removeTrailingSlash(path) {
|
||||
while (path.endsWith('/')) {
|
||||
path = path.slice(0, -1)
|
||||
path = path.slice(0, -1);
|
||||
}
|
||||
|
||||
if (path.length === 0) {
|
||||
path = '/'
|
||||
path = '/';
|
||||
}
|
||||
|
||||
return path
|
||||
return path;
|
||||
}
|
||||
|
||||
function buildKey (opts) {
|
||||
const { path, method, body, headers, query } = opts
|
||||
function buildKey(opts) {
|
||||
const { path, method, body, headers, query } = opts;
|
||||
|
||||
return {
|
||||
path,
|
||||
method,
|
||||
body,
|
||||
headers,
|
||||
query
|
||||
}
|
||||
query,
|
||||
};
|
||||
}
|
||||
|
||||
function generateKeyValues (data) {
|
||||
const keys = Object.keys(data)
|
||||
const result = []
|
||||
function generateKeyValues(data) {
|
||||
const keys = Object.keys(data);
|
||||
const result = [];
|
||||
for (let i = 0; i < keys.length; ++i) {
|
||||
const key = keys[i]
|
||||
const value = data[key]
|
||||
const name = Buffer.from(`${key}`)
|
||||
const key = keys[i];
|
||||
const value = data[key];
|
||||
const name = Buffer.from(`${key}`);
|
||||
if (Array.isArray(value)) {
|
||||
for (let j = 0; j < value.length; ++j) {
|
||||
result.push(name, Buffer.from(`${value[j]}`))
|
||||
result.push(name, Buffer.from(`${value[j]}`));
|
||||
}
|
||||
} else {
|
||||
result.push(name, Buffer.from(`${value}`))
|
||||
result.push(name, Buffer.from(`${value}`));
|
||||
}
|
||||
}
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
|
||||
* @param {number} statusCode
|
||||
*/
|
||||
function getStatusText (statusCode) {
|
||||
return STATUS_CODES[statusCode] || 'unknown'
|
||||
function getStatusText(statusCode) {
|
||||
return STATUS_CODES[statusCode] || 'unknown';
|
||||
}
|
||||
|
||||
async function getResponse (body) {
|
||||
const buffers = []
|
||||
async function getResponse(body) {
|
||||
const buffers = [];
|
||||
for await (const data of body) {
|
||||
buffers.push(data)
|
||||
buffers.push(data);
|
||||
}
|
||||
return Buffer.concat(buffers).toString('utf8')
|
||||
return Buffer.concat(buffers).toString('utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock dispatch function used to simulate undici dispatches
|
||||
*/
|
||||
function mockDispatch (opts, handler) {
|
||||
function mockDispatch(opts, handler) {
|
||||
// Get mock dispatch from built key
|
||||
const key = buildKey(opts)
|
||||
const mockDispatch = getMockDispatch(this[kDispatches], key)
|
||||
const key = buildKey(opts);
|
||||
const mockDispatch = getMockDispatch(this[kDispatches], key);
|
||||
|
||||
mockDispatch.timesInvoked++
|
||||
mockDispatch.timesInvoked++;
|
||||
|
||||
// Here's where we resolve a callback if a callback is present for the dispatch data.
|
||||
if (mockDispatch.data.callback) {
|
||||
mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) }
|
||||
mockDispatch.data = {
|
||||
...mockDispatch.data,
|
||||
...mockDispatch.data.callback(opts),
|
||||
};
|
||||
}
|
||||
|
||||
// Parse mockDispatch data
|
||||
const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch
|
||||
const { timesInvoked, times } = mockDispatch
|
||||
const {
|
||||
data: { statusCode, data, headers, trailers, error },
|
||||
delay,
|
||||
persist,
|
||||
} = mockDispatch;
|
||||
const { timesInvoked, times } = mockDispatch;
|
||||
|
||||
// If it's used up and not persistent, mark as consumed
|
||||
mockDispatch.consumed = !persist && timesInvoked >= times
|
||||
mockDispatch.pending = timesInvoked < times
|
||||
mockDispatch.consumed = !persist && timesInvoked >= times;
|
||||
mockDispatch.pending = timesInvoked < times;
|
||||
|
||||
// If specified, trigger dispatch error
|
||||
if (error !== null) {
|
||||
deleteMockDispatch(this[kDispatches], key)
|
||||
handler.onError(error)
|
||||
return true
|
||||
deleteMockDispatch(this[kDispatches], key);
|
||||
handler.onError(error);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle the request with a delay if necessary
|
||||
if (typeof delay === 'number' && delay > 0) {
|
||||
setTimeout(() => {
|
||||
handleReply(this[kDispatches])
|
||||
}, delay)
|
||||
handleReply(this[kDispatches]);
|
||||
}, delay);
|
||||
} else {
|
||||
handleReply(this[kDispatches])
|
||||
handleReply(this[kDispatches]);
|
||||
}
|
||||
|
||||
function handleReply (mockDispatches, _data = data) {
|
||||
function handleReply(mockDispatches, _data = data) {
|
||||
// fetch's HeadersList is a 1D string array
|
||||
const optsHeaders = Array.isArray(opts.headers)
|
||||
? buildHeadersFromArray(opts.headers)
|
||||
: opts.headers
|
||||
const body = typeof _data === 'function'
|
||||
? _data({ ...opts, headers: optsHeaders })
|
||||
: _data
|
||||
const optsHeaders =
|
||||
Array.isArray(opts.headers) ?
|
||||
buildHeadersFromArray(opts.headers)
|
||||
: opts.headers;
|
||||
const body =
|
||||
typeof _data === 'function' ?
|
||||
_data({ ...opts, headers: optsHeaders })
|
||||
: _data;
|
||||
|
||||
// util.types.isPromise is likely needed for jest.
|
||||
if (isPromise(body)) {
|
||||
@ -308,75 +356,92 @@ function mockDispatch (opts, handler) {
|
||||
// synchronously throw the error, which breaks some tests.
|
||||
// Rather, we wait for the callback to resolve if it is a
|
||||
// promise, and then re-run handleReply with the new body.
|
||||
body.then((newData) => handleReply(mockDispatches, newData))
|
||||
return
|
||||
body.then((newData) => handleReply(mockDispatches, newData));
|
||||
return;
|
||||
}
|
||||
|
||||
const responseData = getResponseData(body)
|
||||
const responseHeaders = generateKeyValues(headers)
|
||||
const responseTrailers = generateKeyValues(trailers)
|
||||
const responseData = getResponseData(body);
|
||||
const responseHeaders = generateKeyValues(headers);
|
||||
const responseTrailers = generateKeyValues(trailers);
|
||||
|
||||
handler.onConnect?.(err => handler.onError(err), null)
|
||||
handler.onHeaders?.(statusCode, responseHeaders, resume, getStatusText(statusCode))
|
||||
handler.onData?.(Buffer.from(responseData))
|
||||
handler.onComplete?.(responseTrailers)
|
||||
deleteMockDispatch(mockDispatches, key)
|
||||
handler.onConnect?.((err) => handler.onError(err), null);
|
||||
handler.onHeaders?.(
|
||||
statusCode,
|
||||
responseHeaders,
|
||||
resume,
|
||||
getStatusText(statusCode)
|
||||
);
|
||||
handler.onData?.(Buffer.from(responseData));
|
||||
handler.onComplete?.(responseTrailers);
|
||||
deleteMockDispatch(mockDispatches, key);
|
||||
}
|
||||
|
||||
function resume () {}
|
||||
function resume() {}
|
||||
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
function buildMockDispatch () {
|
||||
const agent = this[kMockAgent]
|
||||
const origin = this[kOrigin]
|
||||
const originalDispatch = this[kOriginalDispatch]
|
||||
function buildMockDispatch() {
|
||||
const agent = this[kMockAgent];
|
||||
const origin = this[kOrigin];
|
||||
const originalDispatch = this[kOriginalDispatch];
|
||||
|
||||
return function dispatch (opts, handler) {
|
||||
return function dispatch(opts, handler) {
|
||||
if (agent.isMockActive) {
|
||||
try {
|
||||
mockDispatch.call(this, opts, handler)
|
||||
mockDispatch.call(this, opts, handler);
|
||||
} catch (error) {
|
||||
if (error instanceof MockNotMatchedError) {
|
||||
const netConnect = agent[kGetNetConnect]()
|
||||
const netConnect = agent[kGetNetConnect]();
|
||||
if (netConnect === false) {
|
||||
throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`)
|
||||
throw new MockNotMatchedError(
|
||||
`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`
|
||||
);
|
||||
}
|
||||
if (checkNetConnect(netConnect, origin)) {
|
||||
originalDispatch.call(this, opts, handler)
|
||||
originalDispatch.call(this, opts, handler);
|
||||
} else {
|
||||
throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`)
|
||||
throw new MockNotMatchedError(
|
||||
`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw error
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
originalDispatch.call(this, opts, handler)
|
||||
originalDispatch.call(this, opts, handler);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function checkNetConnect (netConnect, origin) {
|
||||
const url = new URL(origin)
|
||||
function checkNetConnect(netConnect, origin) {
|
||||
const url = new URL(origin);
|
||||
if (netConnect === true) {
|
||||
return true
|
||||
} else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url.host))) {
|
||||
return true
|
||||
return true;
|
||||
} else if (
|
||||
Array.isArray(netConnect) &&
|
||||
netConnect.some((matcher) => matchValue(matcher, url.host))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
function buildAndValidateMockOptions (opts) {
|
||||
function buildAndValidateMockOptions(opts) {
|
||||
if (opts) {
|
||||
const { agent, ...mockOptions } = opts
|
||||
const { agent, ...mockOptions } = opts;
|
||||
|
||||
if ('enableCallHistory' in mockOptions && typeof mockOptions.enableCallHistory !== 'boolean') {
|
||||
throw new InvalidArgumentError('options.enableCallHistory must to be a boolean')
|
||||
if (
|
||||
'enableCallHistory' in mockOptions &&
|
||||
typeof mockOptions.enableCallHistory !== 'boolean'
|
||||
) {
|
||||
throw new InvalidArgumentError(
|
||||
'options.enableCallHistory must to be a boolean'
|
||||
);
|
||||
}
|
||||
|
||||
return mockOptions
|
||||
return mockOptions;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,5 +460,5 @@ module.exports = {
|
||||
checkNetConnect,
|
||||
buildAndValidateMockOptions,
|
||||
getHeaderByName,
|
||||
buildHeadersFromArray
|
||||
}
|
||||
buildHeadersFromArray,
|
||||
};
|
||||
|
49
node_modules/undici/lib/mock/pending-interceptors-formatter.js
generated
vendored
49
node_modules/undici/lib/mock/pending-interceptors-formatter.js
generated
vendored
@ -1,43 +1,52 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
const { Transform } = require('node:stream')
|
||||
const { Console } = require('node:console')
|
||||
const { Transform } = require('node:stream');
|
||||
const { Console } = require('node:console');
|
||||
|
||||
const PERSISTENT = process.versions.icu ? '✅' : 'Y '
|
||||
const NOT_PERSISTENT = process.versions.icu ? '❌' : 'N '
|
||||
const PERSISTENT = process.versions.icu ? '✅' : 'Y ';
|
||||
const NOT_PERSISTENT = process.versions.icu ? '❌' : 'N ';
|
||||
|
||||
/**
|
||||
* Gets the output of `console.table(…)` as a string.
|
||||
*/
|
||||
module.exports = class PendingInterceptorsFormatter {
|
||||
constructor ({ disableColors } = {}) {
|
||||
constructor({ disableColors } = {}) {
|
||||
this.transform = new Transform({
|
||||
transform (chunk, _enc, cb) {
|
||||
cb(null, chunk)
|
||||
}
|
||||
})
|
||||
transform(chunk, _enc, cb) {
|
||||
cb(null, chunk);
|
||||
},
|
||||
});
|
||||
|
||||
this.logger = new Console({
|
||||
stdout: this.transform,
|
||||
inspectOptions: {
|
||||
colors: !disableColors && !process.env.CI
|
||||
}
|
||||
})
|
||||
colors: !disableColors && !process.env.CI,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
format (pendingInterceptors) {
|
||||
format(pendingInterceptors) {
|
||||
const withPrettyHeaders = pendingInterceptors.map(
|
||||
({ method, path, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
||||
({
|
||||
method,
|
||||
path,
|
||||
data: { statusCode },
|
||||
persist,
|
||||
times,
|
||||
timesInvoked,
|
||||
origin,
|
||||
}) => ({
|
||||
Method: method,
|
||||
Origin: origin,
|
||||
Path: path,
|
||||
'Status code': statusCode,
|
||||
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
||||
Invocations: timesInvoked,
|
||||
Remaining: persist ? Infinity : times - timesInvoked
|
||||
}))
|
||||
Remaining: persist ? Infinity : times - timesInvoked,
|
||||
})
|
||||
);
|
||||
|
||||
this.logger.table(withPrettyHeaders)
|
||||
return this.transform.read().toString()
|
||||
this.logger.table(withPrettyHeaders);
|
||||
return this.transform.read().toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user