source: node_modules/undici/lib/mock/mock-agent.js

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 4.6 KB
Line 
1'use strict'
2
3const { kClients } = require('../core/symbols')
4const Agent = require('../agent')
5const {
6 kAgent,
7 kMockAgentSet,
8 kMockAgentGet,
9 kDispatches,
10 kIsMockActive,
11 kNetConnect,
12 kGetNetConnect,
13 kOptions,
14 kFactory
15} = require('./mock-symbols')
16const MockClient = require('./mock-client')
17const MockPool = require('./mock-pool')
18const { matchValue, buildMockOptions } = require('./mock-utils')
19const { InvalidArgumentError, UndiciError } = require('../core/errors')
20const Dispatcher = require('../dispatcher')
21const Pluralizer = require('./pluralizer')
22const PendingInterceptorsFormatter = require('./pending-interceptors-formatter')
23
24class FakeWeakRef {
25 constructor (value) {
26 this.value = value
27 }
28
29 deref () {
30 return this.value
31 }
32}
33
34class MockAgent extends Dispatcher {
35 constructor (opts) {
36 super(opts)
37
38 this[kNetConnect] = true
39 this[kIsMockActive] = true
40
41 // Instantiate Agent and encapsulate
42 if ((opts && opts.agent && typeof opts.agent.dispatch !== 'function')) {
43 throw new InvalidArgumentError('Argument opts.agent must implement Agent')
44 }
45 const agent = opts && opts.agent ? opts.agent : new Agent(opts)
46 this[kAgent] = agent
47
48 this[kClients] = agent[kClients]
49 this[kOptions] = buildMockOptions(opts)
50 }
51
52 get (origin) {
53 let dispatcher = this[kMockAgentGet](origin)
54
55 if (!dispatcher) {
56 dispatcher = this[kFactory](origin)
57 this[kMockAgentSet](origin, dispatcher)
58 }
59 return dispatcher
60 }
61
62 dispatch (opts, handler) {
63 // Call MockAgent.get to perform additional setup before dispatching as normal
64 this.get(opts.origin)
65 return this[kAgent].dispatch(opts, handler)
66 }
67
68 async close () {
69 await this[kAgent].close()
70 this[kClients].clear()
71 }
72
73 deactivate () {
74 this[kIsMockActive] = false
75 }
76
77 activate () {
78 this[kIsMockActive] = true
79 }
80
81 enableNetConnect (matcher) {
82 if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) {
83 if (Array.isArray(this[kNetConnect])) {
84 this[kNetConnect].push(matcher)
85 } else {
86 this[kNetConnect] = [matcher]
87 }
88 } else if (typeof matcher === 'undefined') {
89 this[kNetConnect] = true
90 } else {
91 throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.')
92 }
93 }
94
95 disableNetConnect () {
96 this[kNetConnect] = false
97 }
98
99 // This is required to bypass issues caused by using global symbols - see:
100 // https://github.com/nodejs/undici/issues/1447
101 get isMockActive () {
102 return this[kIsMockActive]
103 }
104
105 [kMockAgentSet] (origin, dispatcher) {
106 this[kClients].set(origin, new FakeWeakRef(dispatcher))
107 }
108
109 [kFactory] (origin) {
110 const mockOptions = Object.assign({ agent: this }, this[kOptions])
111 return this[kOptions] && this[kOptions].connections === 1
112 ? new MockClient(origin, mockOptions)
113 : new MockPool(origin, mockOptions)
114 }
115
116 [kMockAgentGet] (origin) {
117 // First check if we can immediately find it
118 const ref = this[kClients].get(origin)
119 if (ref) {
120 return ref.deref()
121 }
122
123 // If the origin is not a string create a dummy parent pool and return to user
124 if (typeof origin !== 'string') {
125 const dispatcher = this[kFactory]('http://localhost:9999')
126 this[kMockAgentSet](origin, dispatcher)
127 return dispatcher
128 }
129
130 // If we match, create a pool and assign the same dispatches
131 for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) {
132 const nonExplicitDispatcher = nonExplicitRef.deref()
133 if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) {
134 const dispatcher = this[kFactory](origin)
135 this[kMockAgentSet](origin, dispatcher)
136 dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches]
137 return dispatcher
138 }
139 }
140 }
141
142 [kGetNetConnect] () {
143 return this[kNetConnect]
144 }
145
146 pendingInterceptors () {
147 const mockAgentClients = this[kClients]
148
149 return Array.from(mockAgentClients.entries())
150 .flatMap(([origin, scope]) => scope.deref()[kDispatches].map(dispatch => ({ ...dispatch, origin })))
151 .filter(({ pending }) => pending)
152 }
153
154 assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) {
155 const pending = this.pendingInterceptors()
156
157 if (pending.length === 0) {
158 return
159 }
160
161 const pluralizer = new Pluralizer('interceptor', 'interceptors').pluralize(pending.length)
162
163 throw new UndiciError(`
164${pluralizer.count} ${pluralizer.noun} ${pluralizer.is} pending:
165
166${pendingInterceptorsFormatter.format(pending)}
167`.trim())
168 }
169}
170
171module.exports = MockAgent
Note: See TracBrowser for help on using the repository browser.