初始化
This commit is contained in:
248
node_modules/undici/lib/mock/mock-call-history.js
generated
vendored
Normal file
248
node_modules/undici/lib/mock/mock-call-history.js
generated
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
'use strict'
|
||||
|
||||
const { kMockCallHistoryAddLog } = require('./mock-symbols')
|
||||
const { InvalidArgumentError } = require('../core/errors')
|
||||
|
||||
function handleFilterCallsWithOptions (criteria, options, handler, store) {
|
||||
switch (options.operator) {
|
||||
case 'OR':
|
||||
store.push(...handler(criteria))
|
||||
|
||||
return store
|
||||
case 'AND':
|
||||
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\'')
|
||||
}
|
||||
}
|
||||
|
||||
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\'')
|
||||
}
|
||||
|
||||
return {
|
||||
...finalOptions,
|
||||
operator: options.operator.toUpperCase()
|
||||
}
|
||||
}
|
||||
|
||||
return finalOptions
|
||||
}
|
||||
|
||||
function makeFilterCalls (parameterName) {
|
||||
return (parameterValue) => {
|
||||
if (typeof parameterValue === 'string' || parameterValue == null) {
|
||||
return this.logs.filter((log) => {
|
||||
return log[parameterName] === parameterValue
|
||||
})
|
||||
}
|
||||
if (parameterValue instanceof RegExp) {
|
||||
return this.logs.filter((log) => {
|
||||
return parameterValue.test(log[parameterName])
|
||||
})
|
||||
}
|
||||
|
||||
throw new InvalidArgumentError(`${parameterName} parameter should be one of string, regexp, undefined or null`)
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
||||
// requestInit.path contains query url parameters
|
||||
// requestInit.query is then undefined
|
||||
if (url.search.length !== 0) {
|
||||
return url
|
||||
}
|
||||
|
||||
// requestInit.query can be populated here
|
||||
url.search = new URLSearchParams(requestInit.query).toString()
|
||||
|
||||
return url
|
||||
} catch (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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
toMap () {
|
||||
return new Map([
|
||||
['protocol', this.protocol],
|
||||
['host', this.host],
|
||||
['port', this.port],
|
||||
['origin', this.origin],
|
||||
['path', this.path],
|
||||
['hash', this.hash],
|
||||
['searchParams', this.searchParams],
|
||||
['fullUrl', this.fullUrl],
|
||||
['method', this.method],
|
||||
['body', this.body],
|
||||
['headers', this.headers]]
|
||||
)
|
||||
}
|
||||
|
||||
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}`
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
class MockCallHistory {
|
||||
logs = []
|
||||
|
||||
calls () {
|
||||
return this.logs
|
||||
}
|
||||
|
||||
firstCall () {
|
||||
return this.logs.at(0)
|
||||
}
|
||||
|
||||
lastCall () {
|
||||
return this.logs.at(-1)
|
||||
}
|
||||
|
||||
nthCall (number) {
|
||||
if (typeof number !== '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')
|
||||
}
|
||||
if (Math.sign(number) !== 1) {
|
||||
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)
|
||||
}
|
||||
|
||||
filterCalls (criteria, options) {
|
||||
// perf
|
||||
if (this.logs.length === 0) {
|
||||
return this.logs
|
||||
}
|
||||
if (typeof criteria === 'function') {
|
||||
return this.logs.filter(criteria)
|
||||
}
|
||||
if (criteria instanceof RegExp) {
|
||||
return this.logs.filter((log) => {
|
||||
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
|
||||
}
|
||||
|
||||
const finalOptions = { operator: 'OR', ...buildAndValidateFilterCallsOptions(options) }
|
||||
|
||||
let maybeDuplicatedLogsFiltered = []
|
||||
if ('protocol' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered)
|
||||
}
|
||||
if ('host' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered)
|
||||
}
|
||||
if ('port' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered)
|
||||
}
|
||||
if ('origin' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered)
|
||||
}
|
||||
if ('path' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered)
|
||||
}
|
||||
if ('hash' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered)
|
||||
}
|
||||
if ('fullUrl' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered)
|
||||
}
|
||||
if ('method' in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered)
|
||||
}
|
||||
|
||||
const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)]
|
||||
|
||||
return uniqLogsFiltered
|
||||
}
|
||||
|
||||
throw new InvalidArgumentError('criteria parameter should be one of function, regexp, or object')
|
||||
}
|
||||
|
||||
filterCallsByProtocol = makeFilterCalls.call(this, 'protocol')
|
||||
|
||||
filterCallsByHost = makeFilterCalls.call(this, 'host')
|
||||
|
||||
filterCallsByPort = makeFilterCalls.call(this, 'port')
|
||||
|
||||
filterCallsByOrigin = makeFilterCalls.call(this, 'origin')
|
||||
|
||||
filterCallsByPath = makeFilterCalls.call(this, 'path')
|
||||
|
||||
filterCallsByHash = makeFilterCalls.call(this, 'hash')
|
||||
|
||||
filterCallsByFullUrl = makeFilterCalls.call(this, 'fullUrl')
|
||||
|
||||
filterCallsByMethod = makeFilterCalls.call(this, 'method')
|
||||
|
||||
clear () {
|
||||
this.logs = []
|
||||
}
|
||||
|
||||
[kMockCallHistoryAddLog] (requestInit) {
|
||||
const log = new MockCallHistoryLog(requestInit)
|
||||
|
||||
this.logs.push(log)
|
||||
|
||||
return log
|
||||
}
|
||||
|
||||
* [Symbol.iterator] () {
|
||||
for (const log of this.calls()) {
|
||||
yield log
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.MockCallHistory = MockCallHistory
|
||||
module.exports.MockCallHistoryLog = MockCallHistoryLog
|
||||
Reference in New Issue
Block a user