Skip to content

Commit

Permalink
[bidi][js] Add callback handlers for logging APIs (#14120)
Browse files Browse the repository at this point in the history
  • Loading branch information
pujagani authored Jun 13, 2024
1 parent a51ddee commit 59a25c7
Show file tree
Hide file tree
Showing 2 changed files with 242 additions and 30 deletions.
140 changes: 110 additions & 30 deletions javascript/node/selenium-webdriver/bidi/logInspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,31 @@ const { ConsoleLogEntry, JavascriptLogEntry, GenericLogEntry } = require('./logE
const LOG = {
TYPE_CONSOLE: 'console',
TYPE_JS_LOGS: 'javascript',
TYPE_JS_EXCEPTION: 'javascriptException',
TYPE_LOGS: 'logs',
TYPE_CONSOLE_FILTER: 'console_filter',
TYPE_JS_LOGS_FILTER: 'javascript_filter',
TYPE_JS_EXCEPTION_FILTER: 'javascriptException_filter',
TYPE_LOGS_FILTER: 'logs_filter',
}

class LogInspector {
bidi
ws
#callbackId = 0

constructor(driver, browsingContextIds) {
this._driver = driver
this._browsingContextIds = browsingContextIds
this.listener = {}
this.listener = new Map()
this.listener.set(LOG.TYPE_CONSOLE, new Map())
this.listener.set(LOG.TYPE_JS_LOGS, new Map())
this.listener.set(LOG.TYPE_JS_EXCEPTION, new Map())
this.listener.set(LOG.TYPE_LOGS, new Map())
this.listener.set(LOG.TYPE_CONSOLE_FILTER, new Map())
this.listener.set(LOG.TYPE_JS_LOGS_FILTER, new Map())
this.listener.set(LOG.TYPE_JS_EXCEPTION_FILTER, new Map())
this.listener.set(LOG.TYPE_LOGS_FILTER, new Map())
}

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

/**
* @param kind
*/
logListener(kind) {
if (!(kind in this.listener)) {
this.listener[kind] = []
addCallback(eventType, callback) {
const id = ++this.#callbackId

const eventCallbackMap = this.listener.get(eventType)
eventCallbackMap.set(id, callback)
return id
}

removeCallback(id) {
for (const [, callbacks] of this.listener) {
if (callbacks.has(id)) {
callbacks.delete(id)
}
}
}

invokeCallbacks(eventType, data) {
const callbacks = this.listener.get(eventType)
if (callbacks) {
for (const [, callback] of callbacks) {
callback(data)
}
}
}

invokeCallbacksWithFilter(eventType, data, filterLevel) {
const callbacks = this.listener.get(eventType)
if (callbacks) {
for (const [, value] of callbacks) {
const callback = value.callback
const filter = value.filter
if (filterLevel === filter.getLevel()) {
callback(data)
}
}
}
}

/**
* Listen to Console logs
* @param callback
* @param filterBy
* @returns {Promise<void>}
* @returns {Promise<number>}
*/
async onConsoleEntry(callback, filterBy = undefined) {
if (filterBy !== undefined && !(filterBy instanceof FilterBy)) {
throw Error(`Pass valid FilterBy object. Received: ${filterBy}`)
}

let id

if (filterBy !== undefined) {
id = this.addCallback(LOG.TYPE_CONSOLE_FILTER, { callback: callback, filter: filterBy })
} else {
id = this.addCallback(LOG.TYPE_CONSOLE, callback)
}

this.ws = await this.bidi.socket

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

if (filterBy !== undefined) {
if (params?.level === filterBy.getLevel()) {
callback(consoleEntry)
this.invokeCallbacksWithFilter(LOG.TYPE_CONSOLE_FILTER, consoleEntry, filterBy.getLevel())
}
return
}

callback(consoleEntry)
this.invokeCallbacks(LOG.TYPE_CONSOLE, consoleEntry)
}
})

return id
}

/**
* Listen to JS logs
* @param callback
* @param filterBy
* @returns {Promise<void>}
* @returns {Promise<number>}
*/
async onJavascriptLog(callback, filterBy = undefined) {
if (filterBy !== undefined && !(filterBy instanceof FilterBy)) {
throw Error(`Pass valid FilterBy object. Received: ${filterBy}`)
}

let id

if (filterBy !== undefined) {
id = this.addCallback(LOG.TYPE_JS_LOGS_FILTER, { callback: callback, filter: filterBy })
} else {
id = this.addCallback(LOG.TYPE_JS_LOGS, callback)
}

this.ws = await this.bidi.socket

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

if (filterBy !== undefined) {
if (params?.level === filterBy.getLevel()) {
callback(jsEntry)
this.invokeCallbacksWithFilter(LOG.TYPE_JS_LOGS_FILTER, jsEntry, filterBy.getLevel())
}
return
}

callback(jsEntry)
this.invokeCallbacks(LOG.TYPE_JS_LOGS, jsEntry)
}
})

return id
}

/**
* Listen to JS Exceptions
* @param callback
* @returns {Promise<void>}
* @returns {Promise<number>}
*/
async onJavascriptException(callback) {
const id = this.addCallback(LOG.TYPE_JS_EXCEPTION, callback)
this.ws = await this.bidi.socket
let enabled = LOG.TYPE_JS_EXCEPTION in this.listener || this.logListener(LOG.TYPE_JS_EXCEPTION)
this.listener[LOG.TYPE_JS_EXCEPTION].push(callback)

if (enabled) {
return
}

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

this.listener[LOG.TYPE_JS_EXCEPTION].forEach((listener) => {
listener(jsErrorEntry)
})
this.invokeCallbacks(LOG.TYPE_JS_EXCEPTION, jsErrorEntry)
}
})

return id
}

/**
* Listen to any logs
* @param callback
* @param filterBy
* @returns {Promise<void>}
* @returns {Promise<number>}
*/
async onLog(callback, filterBy = undefined) {
if (filterBy !== undefined && !(filterBy instanceof FilterBy)) {
throw Error(`Pass valid FilterBy object. Received: ${filterBy}`)
}

let id
if (filterBy !== undefined) {
id = this.addCallback(LOG.TYPE_LOGS_FILTER, { callback: callback, filter: filterBy })
} else {
id = this.addCallback(LOG.TYPE_LOGS, callback)
}

this.ws = await this.bidi.socket

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

callback(jsEntry)
if (filterBy !== undefined) {
if (params?.level === filterBy.getLevel()) {
{
this.invokeCallbacksWithFilter(LOG.TYPE_LOGS_FILTER, jsEntry, filterBy.getLevel())
}
return
}
}

this.invokeCallbacks(LOG.TYPE_LOGS, jsEntry)
return
}

Expand All @@ -209,12 +284,12 @@ class LogInspector {

if (filterBy !== undefined) {
if (params?.level === filterBy.getLevel()) {
callback(consoleEntry)
this.invokeCallbacksWithFilter(LOG.TYPE_LOGS_FILTER, consoleEntry, filterBy.getLevel())
}
return
}

callback(consoleEntry)
this.invokeCallbacks(LOG.TYPE_LOGS, consoleEntry)
return
}

Expand All @@ -229,14 +304,19 @@ class LogInspector {

if (filterBy !== undefined) {
if (params?.level === filterBy.getLevel()) {
callback(genericEntry)
{
this.invokeCallbacksWithFilter(LOG.TYPE_LOGS_FILTER, genericEntry, filterBy.getLevel())
}
return
}
return
}

callback(genericEntry)
this.invokeCallbacks(LOG.TYPE_LOGS, genericEntry)
return
}
})

return id
}

/**
Expand Down
Loading

0 comments on commit 59a25c7

Please sign in to comment.