0
# Event Handling
1
2
Browser event monitoring including console messages, JavaScript exceptions, and runtime events for debugging and monitoring. Provides comprehensive access to browser-side events for testing and debugging purposes.
3
4
## Core Imports
5
6
```java
7
import org.openqa.selenium.devtools.v99.V99Events;
8
import org.openqa.selenium.devtools.DevTools;
9
import org.openqa.selenium.devtools.Command;
10
import org.openqa.selenium.devtools.Event;
11
import org.openqa.selenium.devtools.events.ConsoleEvent;
12
import org.openqa.selenium.JavascriptException;
13
import java.util.function.Consumer;
14
```
15
16
## Capabilities
17
18
### Events Handler
19
20
Creates an event monitoring handler for Chrome DevTools Protocol v99.
21
22
```java { .api }
23
/**
24
* Creates event monitoring handler for CDP v99
25
* @param devtools - DevTools client instance
26
*/
27
public V99Events(DevTools devtools);
28
```
29
30
### Runtime Domain Control
31
32
Enable and disable the JavaScript runtime domain for event collection.
33
34
```java { .api }
35
/**
36
* Enable JavaScript runtime domain for event monitoring
37
* @return Command to enable runtime
38
*/
39
protected Command<Void> enableRuntime();
40
41
/**
42
* Disable JavaScript runtime domain
43
* @return Command to disable runtime
44
*/
45
protected Command<Void> disableRuntime();
46
```
47
48
### High-level Event Listeners
49
50
Convenient methods for adding event listeners with automatic event conversion.
51
52
```java { .api }
53
/**
54
* Add listener for console events (console.log, console.error, etc.)
55
* @param listener - Consumer that receives console events
56
*/
57
public void addConsoleListener(Consumer<ConsoleEvent> listener);
58
59
/**
60
* Add listener for JavaScript exceptions
61
* @param listener - Consumer that receives JavaScript exception events
62
*/
63
public void addJavascriptExceptionListener(Consumer<JavascriptException> listener);
64
65
/**
66
* Disable event monitoring and clean up listeners
67
*/
68
public void disable();
69
```
70
71
### Low-level Console Event Monitoring
72
73
Monitor browser console API calls (console.log, console.error, etc.).
74
75
```java { .api }
76
/**
77
* Get event handler for console API calls
78
* @return Event for console messages
79
*/
80
protected Event<ConsoleAPICalled> consoleEvent();
81
82
/**
83
* Convert CDP console event to Selenium console event
84
* @param event - CDP console API called event
85
* @return Selenium console event
86
*/
87
protected ConsoleEvent toConsoleEvent(ConsoleAPICalled event);
88
```
89
90
### JavaScript Exception Monitoring
91
92
Monitor JavaScript exceptions thrown in the browser.
93
94
```java { .api }
95
/**
96
* Get event handler for JavaScript exceptions
97
* @return Event for JavaScript exceptions
98
*/
99
protected Event<ExceptionThrown> exceptionThrownEvent();
100
101
/**
102
* Convert CDP exception event to JavaScript exception
103
* @param event - CDP exception thrown event
104
* @return JavascriptException with stack trace
105
*/
106
protected JavascriptException toJsException(ExceptionThrown event);
107
```
108
109
## Protocol Types
110
111
### Console Events
112
113
```java { .api }
114
/**
115
* Console API called event from CDP
116
*/
117
public class ConsoleAPICalled {
118
/**
119
* Get console call type (log, error, warn, etc.)
120
* @return Console API type
121
*/
122
public ConsoleAPIType getType();
123
124
/**
125
* Get console message arguments
126
* @return List of remote objects representing arguments
127
*/
128
public List<RemoteObject> getArgs();
129
130
/**
131
* Get timestamp of console call
132
* @return Timestamp
133
*/
134
public Timestamp getTimestamp();
135
136
/**
137
* Get execution context ID where console was called
138
* @return Context ID
139
*/
140
public ExecutionContextId getExecutionContextId();
141
142
/**
143
* Get stack trace if available
144
* @return Optional stack trace
145
*/
146
public Optional<StackTrace> getStackTrace();
147
}
148
149
/**
150
* Console API call types
151
*/
152
public enum ConsoleAPIType {
153
LOG("log"),
154
DEBUG("debug"),
155
INFO("info"),
156
ERROR("error"),
157
WARNING("warning"),
158
CLEAR("clear"),
159
DIR("dir"),
160
DIRXML("dirxml"),
161
TABLE("table"),
162
TRACE("trace"),
163
STARTGROUP("startGroup"),
164
STARTGROUPCOLLAPSED("startGroupCollapsed"),
165
ENDGROUP("endGroup"),
166
ASSERT("assert"),
167
PROFILE("profile"),
168
PROFILEEND("profileEnd"),
169
COUNT("count"),
170
TIMEEND("timeEnd");
171
}
172
173
/**
174
* Selenium console event (converted from CDP)
175
*/
176
public class ConsoleEvent {
177
public ConsoleEvent(String type, Instant timestamp, List<Object> messages);
178
179
public String getType();
180
public Instant getTimestamp();
181
public List<Object> getMessages();
182
}
183
```
184
185
### Exception Events
186
187
```java { .api }
188
/**
189
* JavaScript exception thrown event from CDP
190
*/
191
public class ExceptionThrown {
192
/**
193
* Get exception details
194
* @return Exception details
195
*/
196
public ExceptionDetails getExceptionDetails();
197
198
/**
199
* Get timestamp when exception occurred
200
* @return Timestamp
201
*/
202
public Timestamp getTimestamp();
203
}
204
205
/**
206
* Detailed exception information
207
*/
208
public class ExceptionDetails {
209
/**
210
* Get exception ID
211
* @return Exception ID
212
*/
213
public ExceptionId getExceptionId();
214
215
/**
216
* Get exception text/message
217
* @return Exception message
218
*/
219
public String getText();
220
221
/**
222
* Get line number where exception occurred
223
* @return Line number
224
*/
225
public Integer getLineNumber();
226
227
/**
228
* Get column number where exception occurred
229
* @return Column number
230
*/
231
public Integer getColumnNumber();
232
233
/**
234
* Get URL/script where exception occurred
235
* @return Optional URL
236
*/
237
public Optional<String> getUrl();
238
239
/**
240
* Get stack trace if available
241
* @return Optional stack trace
242
*/
243
public Optional<StackTrace> getStackTrace();
244
245
/**
246
* Get exception object details
247
* @return Optional remote object representing the exception
248
*/
249
public Optional<RemoteObject> getException();
250
251
/**
252
* Get execution context ID where exception occurred
253
* @return Optional context ID
254
*/
255
public Optional<ExecutionContextId> getExecutionContextId();
256
}
257
```
258
259
### Common Types
260
261
```java { .api }
262
/**
263
* Remote JavaScript object representation
264
*/
265
public class RemoteObject {
266
/**
267
* Get object type (string, number, boolean, object, etc.)
268
* @return Object type
269
*/
270
public RemoteObjectType getType();
271
272
/**
273
* Get object value if primitive
274
* @return Optional value
275
*/
276
public Optional<Object> getValue();
277
278
/**
279
* Get object description
280
* @return Optional description string
281
*/
282
public Optional<String> getDescription();
283
}
284
285
/**
286
* JavaScript stack trace information
287
*/
288
public class StackTrace {
289
/**
290
* Get description of the stack trace
291
* @return Optional description
292
*/
293
public Optional<String> getDescription();
294
295
/**
296
* Get call frames in the stack trace
297
* @return List of call frames
298
*/
299
public List<CallFrame> getCallFrames();
300
301
/**
302
* Get parent stack trace if available
303
* @return Optional parent stack trace
304
*/
305
public Optional<StackTrace> getParent();
306
}
307
308
/**
309
* Individual call frame in stack trace
310
*/
311
public class CallFrame {
312
/**
313
* Get function name
314
* @return Function name
315
*/
316
public String getFunctionName();
317
318
/**
319
* Get script URL
320
* @return Script URL
321
*/
322
public String getUrl();
323
324
/**
325
* Get line number in script
326
* @return Line number (0-based)
327
*/
328
public Integer getLineNumber();
329
330
/**
331
* Get column number in line
332
* @return Column number (0-based)
333
*/
334
public Integer getColumnNumber();
335
}
336
337
/**
338
* CDP timestamp representation
339
*/
340
public class Timestamp {
341
/**
342
* Convert timestamp to JSON number
343
* @return JSON representation
344
*/
345
public JsonInput toJson();
346
347
/**
348
* Convert to string representation
349
* @return String representation
350
*/
351
public String toString();
352
}
353
```
354
355
## Usage Examples
356
357
### Basic Console Monitoring
358
359
```java
360
import org.openqa.selenium.devtools.DevTools;
361
import org.openqa.selenium.devtools.v99.V99Domains;
362
import org.openqa.selenium.devtools.events.ConsoleEvent;
363
364
DevTools devTools = ...; // from ChromeDriver
365
V99Domains domains = new V99Domains(devTools);
366
367
// Add console listener using high-level API
368
domains.events().addConsoleListener(consoleEvent -> {
369
System.out.printf("[%s] %s: %s%n",
370
consoleEvent.getTimestamp(),
371
consoleEvent.getType(),
372
consoleEvent.getMessages()
373
);
374
});
375
376
// Now navigate to page - console messages will be captured
377
driver.get("https://example.com");
378
```
379
380
### Exception Monitoring
381
382
```java
383
// Add JavaScript exception listener using high-level API
384
domains.events().addJavascriptExceptionListener(jsException -> {
385
System.err.println("JavaScript Exception: " + jsException.getMessage());
386
387
// Print stack trace
388
for (StackTraceElement element : jsException.getStackTrace()) {
389
System.err.println(" at " + element.toString());
390
}
391
});
392
393
// This will trigger exception monitoring for any JavaScript errors
394
driver.executeScript("throw new Error('Test exception');");
395
```
396
397
### Combined Event Monitoring
398
399
```java
400
// Set up both console and exception monitoring together
401
domains.events().addConsoleListener(consoleEvent -> {
402
// Handle console messages based on type
403
switch (consoleEvent.getType()) {
404
case "error":
405
System.err.println("Console Error: " + consoleEvent.getMessages());
406
break;
407
case "warning":
408
System.out.println("Console Warning: " + consoleEvent.getMessages());
409
break;
410
default:
411
System.out.println("Console " + consoleEvent.getType() + ": " + consoleEvent.getMessages());
412
}
413
});
414
415
domains.events().addJavascriptExceptionListener(jsException -> {
416
System.err.println("JavaScript Exception: " + jsException.getMessage());
417
logExceptionToTestResults(jsException);
418
});
419
420
// Execute test operations - both console and exception events will be captured
421
422
// Cleanup when done
423
domains.events().disable(); // Disables runtime and cleans up listeners
424
```
425
426
### Advanced Console Event Processing (Low-level API)
427
428
```java
429
devTools.send(domains.events().enableRuntime());
430
431
devTools.addListener(domains.events().consoleEvent(), consoleApiEvent -> {
432
String type = consoleApiEvent.getType().toString();
433
List<RemoteObject> args = consoleApiEvent.getArgs();
434
435
// Process different console types differently
436
switch (type) {
437
case "error":
438
handleConsoleError(args);
439
break;
440
case "warning":
441
handleConsoleWarning(args);
442
break;
443
case "log":
444
case "info":
445
handleConsoleInfo(args);
446
break;
447
case "table":
448
handleConsoleTable(args);
449
break;
450
default:
451
handleGenericConsole(type, args);
452
}
453
});
454
455
private void handleConsoleError(List<RemoteObject> args) {
456
// Convert remote objects to meaningful error data
457
args.forEach(arg -> {
458
if (arg.getType() == RemoteObjectType.STRING && arg.getValue().isPresent()) {
459
System.err.println("Console Error: " + arg.getValue().get());
460
}
461
});
462
}
463
```
464
465
### Filtering Events by Context
466
467
```java
468
// Store execution contexts for filtering
469
Set<ExecutionContextId> monitoredContexts = new HashSet<>();
470
471
devTools.addListener(domains.events().consoleEvent(), consoleEvent -> {
472
ExecutionContextId contextId = consoleEvent.getExecutionContextId();
473
474
// Only process events from specific contexts
475
if (monitoredContexts.contains(contextId)) {
476
ConsoleEvent seleniumEvent = domains.events().toConsoleEvent(consoleEvent);
477
processConsoleEvent(seleniumEvent);
478
}
479
});
480
481
// Add context to monitoring set when needed
482
// (typically done through other DevTools events or direct context creation)
483
```
484
485
### Exception Details Extraction
486
487
```java
488
devTools.addListener(domains.events().exceptionThrownEvent(), exceptionEvent -> {
489
ExceptionDetails details = exceptionEvent.getExceptionDetails();
490
491
System.err.println("Exception Details:");
492
System.err.println(" Message: " + details.getText());
493
System.err.println(" Line: " + details.getLineNumber());
494
System.err.println(" Column: " + details.getColumnNumber());
495
496
details.getUrl().ifPresent(url ->
497
System.err.println(" URL: " + url));
498
499
details.getStackTrace().ifPresent(stackTrace -> {
500
System.err.println(" Stack Trace:");
501
stackTrace.getCallFrames().forEach(frame -> {
502
System.err.printf(" at %s (%s:%d:%d)%n",
503
frame.getFunctionName().isEmpty() ? "<anonymous>" : frame.getFunctionName(),
504
frame.getUrl(),
505
frame.getLineNumber(),
506
frame.getColumnNumber()
507
);
508
});
509
});
510
});
511
```
512
513
### Event Cleanup
514
515
```java
516
// Always disable runtime when done to clean up resources
517
try {
518
// Perform operations requiring event monitoring
519
performTestOperations();
520
} finally {
521
// Clean up - disable runtime domain
522
devTools.send(domains.events().disableRuntime());
523
}
524
```
525
526
## Error Handling
527
528
Event monitoring operations can encounter various issues:
529
530
- **Runtime not enabled**: Enable runtime domain before event monitoring
531
- **Event overflow**: High-frequency events can overwhelm listeners
532
- **Context mismatches**: Events may come from unexpected execution contexts
533
- **Memory leaks**: Event listeners should be properly cleaned up
534
535
Handle errors through proper exception handling and resource management:
536
537
```java
538
try {
539
devTools.send(domains.events().enableRuntime());
540
541
// Set up event listeners
542
setupEventListeners();
543
544
// Perform test operations
545
runTests();
546
547
} catch (DevToolsException e) {
548
System.err.println("Failed to enable event monitoring: " + e.getMessage());
549
} finally {
550
// Always clean up
551
try {
552
devTools.send(domains.events().disableRuntime());
553
} catch (Exception e) {
554
System.err.println("Failed to disable runtime: " + e.getMessage());
555
}
556
}
557
```
558
559
## Performance Considerations
560
561
- **Event frequency**: Console events can be very frequent; filter appropriately
562
- **Object serialization**: Remote objects may contain large data structures
563
- **Memory management**: Event listeners hold references that can prevent garbage collection
564
- **Context tracking**: Monitor only necessary execution contexts to reduce overhead
565
- **Stack trace depth**: Deep stack traces can consume significant memory and processing time