How to return and parse this specific information from Chrome Browser console?

We have some page-internal javascript that runs behind the scenes and collects various page metrics values, etc that we return to a database for collection and analysis.

I’m trying to capture this data “live” as my Katalon browser script runs so that I can perform the same calculations that the database is supposed to be doing and validate that the results are the same from both places.

I know how to execute console javascript commands from within Katalon, but this particular example has me stumped, as a basic return won’t work; nor am I immediately certain of the variable format this return data would get parsed into within Katalon for me to retrieve selected values, any of you forum gurus have any ideas on the how to retrieve and what result type will come back for the below console query snippet?

1 Like

No. Katalon Studio v9.x does not support communicating with browser’s JavaScript console. KS v9 works on Selenium3, not Selenium4.

WebDriver BiDirectional API seems to be the future for selenium users. You should look at

Why not you try the example at seleniumhq.github.io/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java at trunk · SeleniumHQ/seleniumhq.github.io · GitHub. This seems to be exactly what you want.

1 Like

So I was able to get it working using a JavaScript call to the console:

def data_value = WebUI.executeJavaScript("var consoleResponse =_bttUtil.consoleResponse; return consoleResponse;", null)
KeywordUtil.logInfo ('consoleResponse: ' + data_value)

with the response being of the format

consoleResponse: [firstPaint:1424, pageValue:0, tul:0, CLS:, ssl:65, redirectStart:0, requestStart:1712278403926, wcd:0, cartValue:0]

However I’m not quite sure how to parse this information from within the variable.

I recall seeing an example of this type of two dimensional array in Katalon, and how to reference the value by the key, but can’t recall exactly what Katalon calls it, any thoughts?

1 Like

Sample TestCase script

import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

import groovy.json.JsonSlurper

WebUI.openBrowser("https://katalon-demo-cura.herokuapp.com/")
WebUI.waitForPageLoad(10)

String js = """const obj = {
  "firstPaint":1424, 
  "pageValue":0, 
  "tul":0, 
  "CLS":null, 
  "ssl":65, 
  "redirectStart":0, 
  "requestStart":1712278403926, 
  "wcd":0, 
  "cartValue":0
};
return JSON.stringify(obj);
"""

def data_value = WebUI.executeJavaScript(js, null)
println data_value
println "------------------------"

def slurper = new JsonSlurper() 
def result = slurper.parseText(data_value)

println "firstPaint: ${result.firstPaint}"
println "pageValue: ${result.pageValue}"
println "tul: ${result.tul}"
println "CLS: ${result.CLS}"
println "ssl: ${result.ssl}"
println "redirectStart: ${result.redirectStart}"
println "requestStart: ${result.requestStart}"
println "wcd: ${result.wcd}"
println "cartValue: ${result.cartValue}"

WebUI.closeBrowser()

Output

2024-04-05 16:47:01.358 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2024-04-05 16:47:01.362 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/TC2
2024-04-05 16:47:02.403 INFO  c.k.k.core.webui.driver.DriverFactory    - Starting 'Chrome' driver
4月 05, 2024 4:47:02 午後 org.openqa.selenium.remote.DesiredCapabilities chrome
情報: Using `new ChromeOptions()` is preferred to `DesiredCapabilities.chrome()`
2024-04-05 16:47:02.466 INFO  c.k.k.core.webui.driver.DriverFactory    - Action delay is set to 0 milliseconds
Starting ChromeDriver 123.0.6312.105 (399174dbe6eff0f59de9a6096129c0c827002b3a-refs/branch-heads/6312@{#761}) on port 39948
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
4月 05, 2024 4:47:06 午後 org.openqa.selenium.remote.ProtocolHandshake createSession
情報: Detected dialect: W3C
2024-04-05 16:47:06.534 INFO  c.k.k.core.webui.driver.DriverFactory    - sessionId = 1e2f4b144d447f458633a342ddd1e68c
2024-04-05 16:47:06.572 INFO  c.k.k.core.webui.driver.DriverFactory    - browser = Chrome 123.0.0.0
2024-04-05 16:47:06.583 INFO  c.k.k.core.webui.driver.DriverFactory    - platform = Mac OS X
2024-04-05 16:47:06.604 INFO  c.k.k.core.webui.driver.DriverFactory    - seleniumVersion = 3.141.59
2024-04-05 16:47:06.626 INFO  c.k.k.core.webui.driver.DriverFactory    - proxyInformation = ProxyInformation { proxyOption=NO_PROXY, proxyServerType=HTTP, username=, password=********, proxyServerAddress=, proxyServerPort=0, executionList="", isApplyToDesiredCapabilities=true }
{"firstPaint":1424,"pageValue":0,"tul":0,"CLS":null,"ssl":65,"redirectStart":0,"requestStart":1712278403926,"wcd":0,"cartValue":0}
------------------------
firstPaint: 1424
pageValue: 0
tul: 0
CLS: null
ssl: 65
redirectStart: 0
requestStart: 1712278403926
wcd: 0
cartValue: 0
2024-04-05 16:47:10.392 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/TC2

1 Like

Trying the above, but getting the below error message, could the formatting be getting interpreted as something other than JSON?

I did observe that in your example above the “JSON” is delineated with curly brackets, whereas the data I’m retrieving is returning with square brackets, could this be causing Katalon to interpret the return as a different data type (perhaps a map?)

Code:

def consoleResponse_body= WebUI.executeJavaScript("var consoleResponse=_bttUtil.consoleResponse; return consoleResponse_body;", null)
KeywordUtil.logInfo ('consoleResponse: ' + consoleResponse_body)
def slurper = new JsonSlurper()
 def parsedJson = slurper.parseText(consoleResponse_body)

Error:

groovy.lang.MissingMethodException: No signature of method: groovy.json.JsonSlurper.parseText() is applicable for argument types: (java.util.HashMap) values: [[firstPaint:1178, pageValue:0, tul:0, CLS:, ssl:63, redirectStart:0, ...]]
1 Like

Was able to get it working as a map (finally found the array type name I was looking for under the groovy array article):

def consoleResponse_body = WebUI.executeJavaScript("var consoleResponse=_bttUtil.consoleResponse; return consoleResponse;", null)
KeywordUtil.logInfo ('consoleResponse: ' + consoleResponse_body )
KeywordUtil.logInfo ("Map Try - firstpaint: " + consoleResponse_body ["firstPaint"])

Results:
Map Try - firstpaint: 1840

1 Like

Interesting.

This message was raised at the line:

def parsedJson = slurper.parseText(consoleResponse_body)

How is the variable consoleRespose_body is set? It is done by this line:

def consoleResponse_body= WebUI.executeJavaScript("var consoleResponse=_bttUtil.consoleResponse; return consoleResponse_body;", null)

The message reveals that the WebUI.executeJavaScript() returned an instance of type java.util.HashMap in Groovy with value [firstPaint:1178, pageValue:0, tul:0, CLS:, ssl:63, redirectStart:0, ...].

On the other hand, the javascript in the the browser returned an instance of javascript object with value:

that could be illustrated like

{thisURL: 'https://________com/', pageName: 'home', nst: '1712253500029', unloadEventStart: '0', redirectStart: 

We can find a slight but significant difference between the 2 strings. In JavaScript, an object is stringified as { key: value, ... } guarded by a pair of curly braces { ... }, but in Groovy a Map instance is stringified as [ key: value, ... ] guarded by a pair of square brackets [ ... ].

This phenomenon revealed an automatic data-type conversion between JavaScript object and Groovy Map:

[Browser, JavaScript]                                [Katalon TestCase, Groovy]
Object ---------------(Selenium3,JSON Wire Protocol)-----> Map

The following article explains what’s going on in the Selenium3 JSON Wire Protocol.

I quoted this figure from Selenium 4 Is Now W3C Compliant: All You Need To Know | LambdaTest

My sample code above does an explicit conversion of data types: JavaScript object --(JSON.strigify)–> JSON text --(JsonSlurper.parseText)–> Groovy Map.

@kevin.jackey 's experiment revealed that my explict data type conversion was not necessary. The same serialization and deserialization will be done automatically by Selenium3 JSON WIRE PROTOCOL.

Interesting.


The data type conversion between browser and clients (of WebDriver API) has changed historically and will change in future.

  1. Selenium3 does a data type conversion by JSON WIRE PROTOCL.
  2. Selenium4 does the same by the W3C WebDriver API.
  3. WebDriver BiDirectional API in future will carry out in a different API.

The automatic data type conversion will continue evolving, will present technical challenges on and on.

I guess, the explicit (foolish) data-type conversion via JSON-text as I did above is robust. It will stay operational in future on top of whichever underlying protocols.