Skip to content

Commit aa0e922

Browse files
committed
Implemented JavaScriptHandling with logging, add functions to collect Performance metrics
1 parent d9b148b commit aa0e922

File tree

7 files changed

+248
-39
lines changed

7 files changed

+248
-39
lines changed

src/main/java/aquality/selenium/browser/Browser.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package aquality.selenium.browser;
22

33
import aquality.selenium.browser.devtools.DevToolsHandling;
4+
import aquality.selenium.browser.devtools.JavaScriptHandling;
45
import aquality.selenium.browser.devtools.NetworkHandling;
56
import aquality.selenium.configuration.IBrowserProfile;
67
import aquality.selenium.configuration.ITimeoutConfiguration;
@@ -399,4 +400,12 @@ public DevToolsHandling devTools() {
399400
public NetworkHandling network() {
400401
return devTools().network();
401402
}
403+
404+
/**
405+
* Provides JavaScript Monitoring functionality.
406+
* @return an instance of {@link JavaScriptHandling}
407+
*/
408+
public JavaScriptHandling javaScriptEngine() {
409+
return devTools().javaScript();
410+
}
402411
}

src/main/java/aquality/selenium/browser/devtools/DevToolsHandling.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@
88
import org.openqa.selenium.devtools.DevTools;
99
import org.openqa.selenium.devtools.Event;
1010
import org.openqa.selenium.devtools.HasDevTools;
11+
import org.openqa.selenium.devtools.v85.performance.Performance;
12+
import org.openqa.selenium.devtools.v85.performance.model.Metric;
1113

14+
import java.util.List;
1215
import java.util.Map;
16+
import java.util.Optional;
1317
import java.util.function.Consumer;
18+
import java.util.stream.Collectors;
1419

1520
/**
1621
* Wrapper for Selenium {@link DevTools} functionality.
@@ -171,10 +176,46 @@ public NetworkHandling network() {
171176
return network;
172177
}
173178

179+
/**
180+
* Provides JavaScript Monitoring functionality.
181+
* @return an instance of {@link JavaScriptHandling}
182+
*/
174183
public JavaScriptHandling javaScript() {
175184
if (javaScript == null) {
176185
javaScript = new JavaScriptHandling(this);
177186
}
178187
return javaScript;
179188
}
189+
190+
/**
191+
* Disable collecting and reporting metrics.
192+
*/
193+
public void disablePerformanceMonitoring() {
194+
sendCommand(Performance.disable());
195+
}
196+
197+
/**
198+
* Enable collecting and reporting metrics.
199+
* @param timeDomain Time domain to use for collecting and reporting duration metrics.
200+
* Allowed Values: timeTicks, threadTicks.
201+
*/
202+
public void enablePerformanceMonitoring(String timeDomain) {
203+
sendCommand(Performance.enable(Optional.of(Performance.EnableTimeDomain.fromString(timeDomain))));
204+
}
205+
206+
/**
207+
* Enable collecting and reporting metrics.
208+
*/
209+
public void enablePerformanceMonitoring() {
210+
sendCommand(Performance.enable(Optional.empty()));
211+
}
212+
213+
/**
214+
* Retrieve current values of run-time metrics.
215+
* @return Current values for run-time metrics
216+
*/
217+
public Map<String, Number> getPerformanceMetrics() {
218+
List<Metric> metrics = sendCommand(Performance.getMetrics());
219+
return metrics.stream().collect(Collectors.toMap(Metric::getName, Metric::getValue));
220+
}
180221
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package aquality.selenium.browser.devtools;
2+
3+
import org.openqa.selenium.devtools.idealized.ScriptId;
4+
5+
/**
6+
* Represents a JavaScript script that is loaded and run on every document load.
7+
*/
8+
public class InitializationScript {
9+
private final ScriptId scriptId;
10+
private final String scriptName;
11+
private final String scriptSource;
12+
13+
/**
14+
* Initializes a new instance of initialization script.
15+
* @param scriptId the internal ID of the initialization script.
16+
* @param scriptName the friendly name of the initialization script.
17+
* @param scriptSource the JavaScript source of the initialization script.
18+
*/
19+
public InitializationScript(ScriptId scriptId, String scriptName, String scriptSource) {
20+
this.scriptId = scriptId;
21+
this.scriptName = scriptName;
22+
this.scriptSource = scriptSource;
23+
}
24+
25+
/**
26+
* Gets the internal ID of the initialization script.
27+
* @return the internal ID of the initialization script.
28+
*/
29+
public ScriptId getScriptId() {
30+
return scriptId;
31+
}
32+
33+
/**
34+
* Gets the friendly name of the initialization script.
35+
* @return the friendly name of the initialization script.
36+
*/
37+
public String getScriptName() {
38+
return scriptName;
39+
}
40+
41+
/**
42+
* Gets the JavaScript source of the initialization script
43+
* @return the JavaScript source of the initialization script
44+
*/
45+
public String getScriptSource() {
46+
return scriptSource;
47+
}
48+
}

src/main/java/aquality/selenium/browser/devtools/JavaScriptHandling.java

Lines changed: 102 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@
1010
import org.openqa.selenium.devtools.idealized.Events;
1111
import org.openqa.selenium.devtools.idealized.Javascript;
1212
import org.openqa.selenium.devtools.idealized.ScriptId;
13+
import org.openqa.selenium.devtools.v85.page.Page;
14+
import org.openqa.selenium.devtools.v85.runtime.Runtime;
1315
import org.openqa.selenium.logging.EventType;
1416
import org.openqa.selenium.logging.HasLogEvents;
1517
import org.openqa.selenium.remote.Augmenter;
1618

17-
import java.util.ArrayList;
18-
import java.util.HashSet;
19-
import java.util.List;
20-
import java.util.Set;
19+
import java.util.*;
2120
import java.util.function.Consumer;
2221

2322
import static org.openqa.selenium.devtools.events.CdpEventTypes.consoleEvent;
@@ -33,6 +32,7 @@ public class JavaScriptHandling {
3332
private final Events<?, ?> events;
3433
private final ILocalizedLogger logger = AqualityServices.getLocalizedLogger();
3534
private final Set<String> bindings = new HashSet<>();
35+
private final Set<InitializationScript> initializationScripts = new HashSet<>();
3636

3737
/**
3838
* Initializes a new instance of the {@link JavaScriptHandling} class.
@@ -44,37 +44,95 @@ public JavaScriptHandling(DevToolsHandling tools) {
4444
this.events = tools.getDevToolsSession().getDomains().events();
4545
}
4646

47+
/**
48+
* Adds a binding to a callback method that will raise an event when the named binding is called by JavaScript
49+
* executing in the browser.
50+
* @param scriptName The name of the callback that will trigger events.
51+
*/
52+
public void addScriptCallbackBinding(String scriptName) {
53+
logger.info("loc.browser.javascript.scriptcallbackbinding.add", scriptName);
54+
bindings.add(scriptName);
55+
tools.sendCommand(Runtime.addBinding(scriptName, Optional.empty()));
56+
}
57+
58+
/**
59+
* Removes a binding to a JavaScript callback.
60+
* @param scriptName The name of the callback to be removed.
61+
*/
62+
public void removeScriptCallbackBinding(String scriptName) {
63+
logger.info("loc.browser.javascript.scriptcallbackbinding.remove", scriptName);
64+
bindings.remove(scriptName);
65+
tools.sendCommand(Runtime.removeBinding(scriptName));
66+
}
67+
4768
/**
4869
* Gets the read-only list of binding callbacks added for this JavaScript engine.
4970
* @return list of binding callbacks added for this JavaScript engine.
5071
*/
51-
public List<String> getBindings() {
72+
public List<String> getScriptCallbackBindings() {
5273
logger.info("loc.browser.javascript.scriptcallbackbindings.get");
5374
return new ArrayList<>(bindings);
5475
}
5576

5677
/**
57-
* Removes all initialization scripts from being loaded for each document, and stops listening for events.
78+
* Removes all bindings to JavaScript callbacks.
5879
*/
59-
public void disable() {
60-
logger.info("loc.browser.javascript.reset");
61-
engine.disable();
62-
bindings.clear();
80+
public void clearScriptCallbackBindings() {
81+
logger.info("loc.browser.javascript.scriptcallbackbindings.clear");
82+
bindings.forEach(scriptName -> {
83+
bindings.remove(scriptName);
84+
tools.sendCommand(Runtime.removeBinding(scriptName));
85+
});
86+
}
87+
88+
/**
89+
* Adds JavaScript to be loaded on every document load, and adds a binding to a callback method
90+
* that will raise an event when the script with that name is called.
91+
* @param scriptName The friendly name by which to refer to this initialization script.
92+
* @param script The JavaScript to be loaded on every page.
93+
* @return Initialization script.
94+
*/
95+
public InitializationScript addInitializationScript(String scriptName, String script) {
96+
logger.info("loc.browser.javascript.initializationscript.add", scriptName);
97+
logger.info("loc.browser.javascript.scriptcallbackbinding.add", scriptName);
98+
ScriptId scriptId = engine.pin(scriptName, script);
99+
InitializationScript initializationScript = new InitializationScript(scriptId, scriptName, script);
100+
bindings.add(scriptName);
101+
initializationScripts.add(initializationScript);
102+
return initializationScript;
103+
}
104+
105+
/**
106+
* Removes JavaScript from being loaded on every document load, and removes a callback binding for it.
107+
* @param script an instance of script to be removed.
108+
*/
109+
public void removeInitializationScript(InitializationScript script) {
110+
logger.info("loc.browser.javascript.initializationscript.remove", script.getScriptName());
111+
tools.sendCommand(Page.removeScriptToEvaluateOnNewDocument(script.getScriptId().getActualId()));
112+
initializationScripts.remove(script);
113+
removeScriptCallbackBinding(script.getScriptName());
114+
}
115+
116+
/**
117+
* Gets the read-only list of initialization scripts added for this JavaScript engine.
118+
* @return the list of added initialization scripts.
119+
*/
120+
public List<InitializationScript> getInitializationScripts() {
121+
logger.info("loc.browser.javascript.initializationscripts.get");
122+
return new ArrayList<>(initializationScripts);
63123
}
64124

65125
/**
66-
* Pins a JavaScript snippet for execution in the browser without transmitting the entire script across the wire
67-
* for every execution.
68-
* @param exposeScriptAs The name of the callback that will trigger events when the named binding is called by
69-
* JavaScript executing in the browser.
70-
* @param script The JavaScript to pin.
71-
* @return a {@link ScriptId} object to use to execute the script.
126+
* Removes all initialization scripts from being loaded on every document load.
72127
*/
73-
public ScriptId pin(String exposeScriptAs, String script) {
74-
logger.info("loc.browser.javascript.snippet.pin");
75-
logger.info("loc.browser.javascript.scriptcallbackbinding.add", exposeScriptAs);
76-
bindings.add(exposeScriptAs);
77-
return engine.pin(exposeScriptAs, script);
128+
public void clearInitializationScripts() {
129+
logger.info("loc.browser.javascript.initializationscripts.clear");
130+
initializationScripts.forEach(script -> {
131+
Page.removeScriptToEvaluateOnNewDocument(script.getScriptId().getActualId());
132+
initializationScripts.remove(script);
133+
tools.sendCommand(Runtime.removeBinding(script.getScriptName()));
134+
bindings.remove(script.getScriptName());
135+
});
78136
}
79137

80138
/**
@@ -119,16 +177,17 @@ public void addDomMutatedListener(Consumer<DomMutationEvent> listener) {
119177
* Adds a listener for events that occur when methods on the JavaScript console are called.
120178
* @param listener a listener to add, consuming a javascript exception.
121179
*/
122-
public void addConsoleEventListener(Consumer<ConsoleEvent> listener) {
180+
public void addJavaScriptConsoleApiListener(Consumer<ConsoleEvent> listener) {
123181
logger.info("loc.browser.javascript.event.consoleapicalled.add");
124182
getDriverThatHasLogEvents().onLogEvent(consoleEvent(listener));
125183
}
126184

127185
/**
128186
* Adds a listener for events that occur when methods on the JavaScript console are called.
187+
* Consider using a method {@link this.addJavaScriptConsoleApiListener} instead.
129188
* @param listener a listener to add, consuming a javascript exception.
130189
*/
131-
public void addJavaScriptConsoleApiListener(Consumer<ConsoleEvent> listener) {
190+
public void addConsoleEventListener(Consumer<ConsoleEvent> listener) {
132191
logger.info("loc.browser.javascript.event.consoleapicalled.add");
133192
events.addConsoleListener(listener);
134193
}
@@ -143,23 +202,30 @@ public void addJavaScriptExceptionThrownListener(Consumer<JavascriptException> l
143202
}
144203

145204
/**
146-
* Adds a binding to a callback method that will raise an event when the named binding is called by JavaScript
147-
* executing in the browser.
148-
* @param scriptName The name of the callback that will trigger events.
205+
* Disables console event listener and JavaScript event listener (disables the runtime).
149206
*/
150-
public void addJsBinding(String scriptName) {
151-
logger.info("loc.browser.javascript.scriptcallbackbinding.add", scriptName);
152-
engine.addJsBinding(scriptName);
153-
bindings.add(scriptName);
207+
public void disableConsoleEventListeners() {
208+
logger.info("loc.browser.javascript.event.consoleapicalled.disable");
209+
events.disable();
154210
}
155211

156212
/**
157-
* Removes a binding to a JavaScript callback.
158-
* @param scriptName The name of the callback to be removed.
213+
* Removes all bindings to JavaScript callbacks and all initialization scripts from being loaded for each document.
159214
*/
160-
public void removeJsBinding(String scriptName) {
161-
logger.info("loc.browser.javascript.scriptcallbackbinding.remove", scriptName);
162-
engine.removeJsBinding(scriptName);
163-
bindings.remove(scriptName);
215+
public void clearAll() {
216+
logger.info("loc.browser.javascript.clearall");
217+
clearInitializationScripts();
218+
clearScriptCallbackBindings();
219+
}
220+
221+
/**
222+
* Removes all bindings to JavaScript callbacks and all initialization scripts from being loaded for each document,
223+
* and stops listening for events.
224+
*/
225+
public void reset() {
226+
logger.info("loc.browser.javascript.reset");
227+
engine.disable();
228+
clearInitializationScripts();
229+
clearScriptCallbackBindings();
164230
}
165231
}

src/main/resources/localization/be.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,20 @@
9595
"loc.browser.network.filter.set": "Задаем фільтр сеткавых падзеяў",
9696
"loc.browser.network.event.requestsent.add": "Падпісваемся на падзею адпраўкі сеткавага запыта",
9797
"loc.browser.network.event.responsereceived.add": "Падпісваемся на падзею атрымання сеткавага адказа",
98-
"loc.browser.network.interceptor.start": "Пачынаем перахоп сеткавых падзеяў"
98+
"loc.browser.network.interceptor.start": "Пачынаем перахоп сеткавых падзеяў",
99+
"loc.browser.javascript.initializationscripts.get": "Атрымліваем ініцыялізацыйныя скрыпты",
100+
"loc.browser.javascript.scriptcallbackbindings.get": "Атрымліваем прывязкі зваротнага выкліку JavaScript",
101+
"loc.browser.javascript.event.callbackexecuted.add": "Падпісваемся на падзею выканання іменаванай прывязкі зваротнага выкліку JavaScript",
102+
"loc.browser.javascript.event.exceptionthrown.add": "Падпісваемся на падзею падзення памылкі JavaScript",
103+
"loc.browser.javascript.event.consoleapicalled.add": "Падпісваемся на падзею выкліку API кансолі JavaScript",
104+
"loc.browser.javascript.event.consoleapicalled.disable": "Адпісваемся ад падзеяў кансолі JavaScript",
105+
"loc.browser.javascript.event.dommutated.add": "Падпісваемся на падзею зменаў у DOM",
106+
"loc.browser.javascript.initializationscript.add": "Дадаем ініцыялізацыйны JavaScript з прыязным іменем '%1$s'",
107+
"loc.browser.javascript.initializationscript.remove": "Выдаляем ініцыялізацыйны JavaScript з прыязным іменем '%1$s'",
108+
"loc.browser.javascript.initializationscripts.clear": "Выдаляем усе ініцыялізацыйныя скрыпты",
109+
"loc.browser.javascript.scriptcallbackbinding.add": "Дадаем прывязку зваротнага выкліку JavaScript з іменем '%1$s'",
110+
"loc.browser.javascript.scriptcallbackbinding.remove": "Выдаляем прывязку зваротнага выкліку JavaScript з іменем '%1$s'",
111+
"loc.browser.javascript.scriptcallbackbindings.clear": "Выдаляем усе прывязкі зваротнага выкліку JavaScript",
112+
"loc.browser.javascript.clearall": "Выдаляем усе прывязкі зваротнага выкліку JavaScript і ініцыялізацыйныя скрыпты",
113+
"loc.browser.javascript.reset": "Выдаляем усе прывязкі зваротнага выкліку JavaScript і ініцыялізацыйныя скрыпты, і спыняем чаканне падзеяў"
99114
}

src/main/resources/localization/en.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,20 @@
9595
"loc.browser.network.filter.set": "Setting the network events filter",
9696
"loc.browser.network.event.requestsent.add": "Subscribing to Network Request Sent event",
9797
"loc.browser.network.event.responsereceived.add": "Subscribing to Network Response Received event",
98-
"loc.browser.network.interceptor.start": "Starting network events interception"
98+
"loc.browser.network.interceptor.start": "Starting network events interception",
99+
"loc.browser.javascript.initializationscripts.get": "Getting initialization JavaScripts",
100+
"loc.browser.javascript.scriptcallbackbindings.get": "Getting JavaScript callback bindings",
101+
"loc.browser.javascript.event.callbackexecuted.add": "Subscribing to JavaScript Callback With A Named Binding Is Executed event",
102+
"loc.browser.javascript.event.exceptionthrown.add": "Subscribing to JavaScript Exception Is Thrown event",
103+
"loc.browser.javascript.event.consoleapicalled.add": "Subscribing to JavaScript Console API Is Called event",
104+
"loc.browser.javascript.event.consoleapicalled.disable": "Unsubscribing from JavaScript Console events",
105+
"loc.browser.javascript.event.dommutated.add": "Subscribing to DOM mutated event",
106+
"loc.browser.javascript.initializationscript.add": "Adding initialization JavaScript with friendly name '%1$s'",
107+
"loc.browser.javascript.initializationscript.remove": "Removing initialization JavaScript by friendly name '%1$s'",
108+
"loc.browser.javascript.initializationscripts.clear": "Removing all initialization JavaScripts",
109+
"loc.browser.javascript.scriptcallbackbinding.add": "Adding JavaScript callback binding with the name '%1$s'",
110+
"loc.browser.javascript.scriptcallbackbinding.remove": "Removing JavaScript callback binding with the name '%1$s'",
111+
"loc.browser.javascript.scriptcallbackbindings.clear": "Removing all JavaScript callback bindings",
112+
"loc.browser.javascript.clearall": "Removing all JavaScript callback bindings and initialization JavaScripts",
113+
"loc.browser.javascript.reset": "Removing all JavaScript callback bindings and initialization JavaScripts, and stopping listening for events"
99114
}

0 commit comments

Comments
 (0)