Skip to content

Commit 59a25c7

Browse files
authored
[bidi][js] Add callback handlers for logging APIs (SeleniumHQ#14120)
1 parent a51ddee commit 59a25c7

File tree

2 files changed

+242
-30
lines changed

2 files changed

+242
-30
lines changed

javascript/node/selenium-webdriver/bidi/logInspector.js

Lines changed: 110 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,31 @@ const { ConsoleLogEntry, JavascriptLogEntry, GenericLogEntry } = require('./logE
2121
const LOG = {
2222
TYPE_CONSOLE: 'console',
2323
TYPE_JS_LOGS: 'javascript',
24+
TYPE_JS_EXCEPTION: 'javascriptException',
25+
TYPE_LOGS: 'logs',
26+
TYPE_CONSOLE_FILTER: 'console_filter',
27+
TYPE_JS_LOGS_FILTER: 'javascript_filter',
28+
TYPE_JS_EXCEPTION_FILTER: 'javascriptException_filter',
29+
TYPE_LOGS_FILTER: 'logs_filter',
2430
}
2531

2632
class LogInspector {
2733
bidi
2834
ws
35+
#callbackId = 0
2936

3037
constructor(driver, browsingContextIds) {
3138
this._driver = driver
3239
this._browsingContextIds = browsingContextIds
33-
this.listener = {}
40+
this.listener = new Map()
41+
this.listener.set(LOG.TYPE_CONSOLE, new Map())
42+
this.listener.set(LOG.TYPE_JS_LOGS, new Map())
43+
this.listener.set(LOG.TYPE_JS_EXCEPTION, new Map())
44+
this.listener.set(LOG.TYPE_LOGS, new Map())
45+
this.listener.set(LOG.TYPE_CONSOLE_FILTER, new Map())
46+
this.listener.set(LOG.TYPE_JS_LOGS_FILTER, new Map())
47+
this.listener.set(LOG.TYPE_JS_EXCEPTION_FILTER, new Map())
48+
this.listener.set(LOG.TYPE_LOGS_FILTER, new Map())
3449
}
3550

3651
/**
@@ -42,26 +57,63 @@ class LogInspector {
4257
await this.bidi.subscribe('log.entryAdded', this._browsingContextIds)
4358
}
4459

45-
/**
46-
* @param kind
47-
*/
48-
logListener(kind) {
49-
if (!(kind in this.listener)) {
50-
this.listener[kind] = []
60+
addCallback(eventType, callback) {
61+
const id = ++this.#callbackId
62+
63+
const eventCallbackMap = this.listener.get(eventType)
64+
eventCallbackMap.set(id, callback)
65+
return id
66+
}
67+
68+
removeCallback(id) {
69+
for (const [, callbacks] of this.listener) {
70+
if (callbacks.has(id)) {
71+
callbacks.delete(id)
72+
}
73+
}
74+
}
75+
76+
invokeCallbacks(eventType, data) {
77+
const callbacks = this.listener.get(eventType)
78+
if (callbacks) {
79+
for (const [, callback] of callbacks) {
80+
callback(data)
81+
}
82+
}
83+
}
84+
85+
invokeCallbacksWithFilter(eventType, data, filterLevel) {
86+
const callbacks = this.listener.get(eventType)
87+
if (callbacks) {
88+
for (const [, value] of callbacks) {
89+
const callback = value.callback
90+
const filter = value.filter
91+
if (filterLevel === filter.getLevel()) {
92+
callback(data)
93+
}
94+
}
5195
}
5296
}
5397

5498
/**
5599
* Listen to Console logs
56100
* @param callback
57101
* @param filterBy
58-
* @returns {Promise<void>}
102+
* @returns {Promise<number>}
59103
*/
60104
async onConsoleEntry(callback, filterBy = undefined) {
61105
if (filterBy !== undefined && !(filterBy instanceof FilterBy)) {
62106
throw Error(`Pass valid FilterBy object. Received: ${filterBy}`)
63107
}
64108

109+
let id
110+
111+
if (filterBy !== undefined) {
112+
id = this.addCallback(LOG.TYPE_CONSOLE_FILTER, { callback: callback, filter: filterBy })
113+
} else {
114+
id = this.addCallback(LOG.TYPE_CONSOLE, callback)
115+
}
116+
65117
this.ws = await this.bidi.socket
66118

67119
this.ws.on('message', (event) => {
@@ -81,27 +133,37 @@ class LogInspector {
81133

82134
if (filterBy !== undefined) {
83135
if (params?.level === filterBy.getLevel()) {
84-
callback(consoleEntry)
136+
this.invokeCallbacksWithFilter(LOG.TYPE_CONSOLE_FILTER, consoleEntry, filterBy.getLevel())
85137
}
86138
return
87139
}
88140

89-
callback(consoleEntry)
141+
this.invokeCallbacks(LOG.TYPE_CONSOLE, consoleEntry)
90142
}
91143
})
144+
145+
return id
92146
}
93147

94148
/**
95149
* Listen to JS logs
96150
* @param callback
97151
* @param filterBy
98-
* @returns {Promise<void>}
152+
* @returns {Promise<number>}
99153
*/
100154
async onJavascriptLog(callback, filterBy = undefined) {
101155
if (filterBy !== undefined && !(filterBy instanceof FilterBy)) {
102156
throw Error(`Pass valid FilterBy object. Received: ${filterBy}`)
103157
}
104158

159+
let id
160+
161+
if (filterBy !== undefined) {
162+
id = this.addCallback(LOG.TYPE_JS_LOGS_FILTER, { callback: callback, filter: filterBy })
163+
} else {
164+
id = this.addCallback(LOG.TYPE_JS_LOGS, callback)
165+
}
166+
105167
this.ws = await this.bidi.socket
106168

107169
this.ws.on('message', (event) => {
@@ -118,29 +180,26 @@ class LogInspector {
118180

119181
if (filterBy !== undefined) {
120182
if (params?.level === filterBy.getLevel()) {
121-
callback(jsEntry)
183+
this.invokeCallbacksWithFilter(LOG.TYPE_JS_LOGS_FILTER, jsEntry, filterBy.getLevel())
122184
}
123185
return
124186
}
125187

126-
callback(jsEntry)
188+
this.invokeCallbacks(LOG.TYPE_JS_LOGS, jsEntry)
127189
}
128190
})
191+
192+
return id
129193
}
130194

131195
/**
132196
* Listen to JS Exceptions
133197
* @param callback
134-
* @returns {Promise<void>}
198+
* @returns {Promise<number>}
135199
*/
136200
async onJavascriptException(callback) {
201+
const id = this.addCallback(LOG.TYPE_JS_EXCEPTION, callback)
137202
this.ws = await this.bidi.socket
138-
let enabled = LOG.TYPE_JS_EXCEPTION in this.listener || this.logListener(LOG.TYPE_JS_EXCEPTION)
139-
this.listener[LOG.TYPE_JS_EXCEPTION].push(callback)
140-
141-
if (enabled) {
142-
return
143-
}
144203

145204
this.ws.on('message', (event) => {
146205
const { params } = JSON.parse(Buffer.from(event.toString()))
@@ -153,24 +212,31 @@ class LogInspector {
153212
params.stackTrace,
154213
)
155214

156-
this.listener[LOG.TYPE_JS_EXCEPTION].forEach((listener) => {
157-
listener(jsErrorEntry)
158-
})
215+
this.invokeCallbacks(LOG.TYPE_JS_EXCEPTION, jsErrorEntry)
159216
}
160217
})
218+
219+
return id
161220
}
162221

163222
/**
164223
* Listen to any logs
165224
* @param callback
166225
* @param filterBy
167-
* @returns {Promise<void>}
226+
* @returns {Promise<number>}
168227
*/
169228
async onLog(callback, filterBy = undefined) {
170229
if (filterBy !== undefined && !(filterBy instanceof FilterBy)) {
171230
throw Error(`Pass valid FilterBy object. Received: ${filterBy}`)
172231
}
173232

233+
let id
234+
if (filterBy !== undefined) {
235+
id = this.addCallback(LOG.TYPE_LOGS_FILTER, { callback: callback, filter: filterBy })
236+
} else {
237+
id = this.addCallback(LOG.TYPE_LOGS, callback)
238+
}
239+
174240
this.ws = await this.bidi.socket
175241

176242
this.ws.on('message', (event) => {
@@ -191,7 +257,16 @@ class LogInspector {
191257
return
192258
}
193259

194-
callback(jsEntry)
260+
if (filterBy !== undefined) {
261+
if (params?.level === filterBy.getLevel()) {
262+
{
263+
this.invokeCallbacksWithFilter(LOG.TYPE_LOGS_FILTER, jsEntry, filterBy.getLevel())
264+
}
265+
return
266+
}
267+
}
268+
269+
this.invokeCallbacks(LOG.TYPE_LOGS, jsEntry)
195270
return
196271
}
197272

@@ -209,12 +284,12 @@ class LogInspector {
209284

210285
if (filterBy !== undefined) {
211286
if (params?.level === filterBy.getLevel()) {
212-
callback(consoleEntry)
287+
this.invokeCallbacksWithFilter(LOG.TYPE_LOGS_FILTER, consoleEntry, filterBy.getLevel())
213288
}
214289
return
215290
}
216291

217-
callback(consoleEntry)
292+
this.invokeCallbacks(LOG.TYPE_LOGS, consoleEntry)
218293
return
219294
}
220295

@@ -229,14 +304,19 @@ class LogInspector {
229304

230305
if (filterBy !== undefined) {
231306
if (params?.level === filterBy.getLevel()) {
232-
callback(genericEntry)
307+
{
308+
this.invokeCallbacksWithFilter(LOG.TYPE_LOGS_FILTER, genericEntry, filterBy.getLevel())
309+
}
310+
return
233311
}
234-
return
235312
}
236313

237-
callback(genericEntry)
314+
this.invokeCallbacks(LOG.TYPE_LOGS, genericEntry)
315+
return
238316
}
239317
})
318+
319+
return id
240320
}
241321

242322
/**

0 commit comments

Comments
 (0)