11cb0ef41Sopenharmony_ci'use strict' 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { kClients } = require('../core/symbols') 41cb0ef41Sopenharmony_ciconst Agent = require('../agent') 51cb0ef41Sopenharmony_ciconst { 61cb0ef41Sopenharmony_ci kAgent, 71cb0ef41Sopenharmony_ci kMockAgentSet, 81cb0ef41Sopenharmony_ci kMockAgentGet, 91cb0ef41Sopenharmony_ci kDispatches, 101cb0ef41Sopenharmony_ci kIsMockActive, 111cb0ef41Sopenharmony_ci kNetConnect, 121cb0ef41Sopenharmony_ci kGetNetConnect, 131cb0ef41Sopenharmony_ci kOptions, 141cb0ef41Sopenharmony_ci kFactory 151cb0ef41Sopenharmony_ci} = require('./mock-symbols') 161cb0ef41Sopenharmony_ciconst MockClient = require('./mock-client') 171cb0ef41Sopenharmony_ciconst MockPool = require('./mock-pool') 181cb0ef41Sopenharmony_ciconst { matchValue, buildMockOptions } = require('./mock-utils') 191cb0ef41Sopenharmony_ciconst { InvalidArgumentError, UndiciError } = require('../core/errors') 201cb0ef41Sopenharmony_ciconst Dispatcher = require('../dispatcher') 211cb0ef41Sopenharmony_ciconst Pluralizer = require('./pluralizer') 221cb0ef41Sopenharmony_ciconst PendingInterceptorsFormatter = require('./pending-interceptors-formatter') 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ciclass FakeWeakRef { 251cb0ef41Sopenharmony_ci constructor (value) { 261cb0ef41Sopenharmony_ci this.value = value 271cb0ef41Sopenharmony_ci } 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci deref () { 301cb0ef41Sopenharmony_ci return this.value 311cb0ef41Sopenharmony_ci } 321cb0ef41Sopenharmony_ci} 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciclass MockAgent extends Dispatcher { 351cb0ef41Sopenharmony_ci constructor (opts) { 361cb0ef41Sopenharmony_ci super(opts) 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci this[kNetConnect] = true 391cb0ef41Sopenharmony_ci this[kIsMockActive] = true 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci // Instantiate Agent and encapsulate 421cb0ef41Sopenharmony_ci if ((opts && opts.agent && typeof opts.agent.dispatch !== 'function')) { 431cb0ef41Sopenharmony_ci throw new InvalidArgumentError('Argument opts.agent must implement Agent') 441cb0ef41Sopenharmony_ci } 451cb0ef41Sopenharmony_ci const agent = opts && opts.agent ? opts.agent : new Agent(opts) 461cb0ef41Sopenharmony_ci this[kAgent] = agent 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci this[kClients] = agent[kClients] 491cb0ef41Sopenharmony_ci this[kOptions] = buildMockOptions(opts) 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci get (origin) { 531cb0ef41Sopenharmony_ci let dispatcher = this[kMockAgentGet](origin) 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci if (!dispatcher) { 561cb0ef41Sopenharmony_ci dispatcher = this[kFactory](origin) 571cb0ef41Sopenharmony_ci this[kMockAgentSet](origin, dispatcher) 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci return dispatcher 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci dispatch (opts, handler) { 631cb0ef41Sopenharmony_ci // Call MockAgent.get to perform additional setup before dispatching as normal 641cb0ef41Sopenharmony_ci this.get(opts.origin) 651cb0ef41Sopenharmony_ci return this[kAgent].dispatch(opts, handler) 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci async close () { 691cb0ef41Sopenharmony_ci await this[kAgent].close() 701cb0ef41Sopenharmony_ci this[kClients].clear() 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci deactivate () { 741cb0ef41Sopenharmony_ci this[kIsMockActive] = false 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci activate () { 781cb0ef41Sopenharmony_ci this[kIsMockActive] = true 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci enableNetConnect (matcher) { 821cb0ef41Sopenharmony_ci if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) { 831cb0ef41Sopenharmony_ci if (Array.isArray(this[kNetConnect])) { 841cb0ef41Sopenharmony_ci this[kNetConnect].push(matcher) 851cb0ef41Sopenharmony_ci } else { 861cb0ef41Sopenharmony_ci this[kNetConnect] = [matcher] 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci } else if (typeof matcher === 'undefined') { 891cb0ef41Sopenharmony_ci this[kNetConnect] = true 901cb0ef41Sopenharmony_ci } else { 911cb0ef41Sopenharmony_ci throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.') 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci disableNetConnect () { 961cb0ef41Sopenharmony_ci this[kNetConnect] = false 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci // This is required to bypass issues caused by using global symbols - see: 1001cb0ef41Sopenharmony_ci // https://github.com/nodejs/undici/issues/1447 1011cb0ef41Sopenharmony_ci get isMockActive () { 1021cb0ef41Sopenharmony_ci return this[kIsMockActive] 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci [kMockAgentSet] (origin, dispatcher) { 1061cb0ef41Sopenharmony_ci this[kClients].set(origin, new FakeWeakRef(dispatcher)) 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci [kFactory] (origin) { 1101cb0ef41Sopenharmony_ci const mockOptions = Object.assign({ agent: this }, this[kOptions]) 1111cb0ef41Sopenharmony_ci return this[kOptions] && this[kOptions].connections === 1 1121cb0ef41Sopenharmony_ci ? new MockClient(origin, mockOptions) 1131cb0ef41Sopenharmony_ci : new MockPool(origin, mockOptions) 1141cb0ef41Sopenharmony_ci } 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci [kMockAgentGet] (origin) { 1171cb0ef41Sopenharmony_ci // First check if we can immediately find it 1181cb0ef41Sopenharmony_ci const ref = this[kClients].get(origin) 1191cb0ef41Sopenharmony_ci if (ref) { 1201cb0ef41Sopenharmony_ci return ref.deref() 1211cb0ef41Sopenharmony_ci } 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci // If the origin is not a string create a dummy parent pool and return to user 1241cb0ef41Sopenharmony_ci if (typeof origin !== 'string') { 1251cb0ef41Sopenharmony_ci const dispatcher = this[kFactory]('http://localhost:9999') 1261cb0ef41Sopenharmony_ci this[kMockAgentSet](origin, dispatcher) 1271cb0ef41Sopenharmony_ci return dispatcher 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci // If we match, create a pool and assign the same dispatches 1311cb0ef41Sopenharmony_ci for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) { 1321cb0ef41Sopenharmony_ci const nonExplicitDispatcher = nonExplicitRef.deref() 1331cb0ef41Sopenharmony_ci if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) { 1341cb0ef41Sopenharmony_ci const dispatcher = this[kFactory](origin) 1351cb0ef41Sopenharmony_ci this[kMockAgentSet](origin, dispatcher) 1361cb0ef41Sopenharmony_ci dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches] 1371cb0ef41Sopenharmony_ci return dispatcher 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci } 1401cb0ef41Sopenharmony_ci } 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci [kGetNetConnect] () { 1431cb0ef41Sopenharmony_ci return this[kNetConnect] 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci pendingInterceptors () { 1471cb0ef41Sopenharmony_ci const mockAgentClients = this[kClients] 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci return Array.from(mockAgentClients.entries()) 1501cb0ef41Sopenharmony_ci .flatMap(([origin, scope]) => scope.deref()[kDispatches].map(dispatch => ({ ...dispatch, origin }))) 1511cb0ef41Sopenharmony_ci .filter(({ pending }) => pending) 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { 1551cb0ef41Sopenharmony_ci const pending = this.pendingInterceptors() 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci if (pending.length === 0) { 1581cb0ef41Sopenharmony_ci return 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci const pluralizer = new Pluralizer('interceptor', 'interceptors').pluralize(pending.length) 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci throw new UndiciError(` 1641cb0ef41Sopenharmony_ci${pluralizer.count} ${pluralizer.noun} ${pluralizer.is} pending: 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci${pendingInterceptorsFormatter.format(pending)} 1671cb0ef41Sopenharmony_ci`.trim()) 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci} 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_cimodule.exports = MockAgent 172