CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-seleniumhq-selenium--selenium-devtools-v99

Chrome DevTools Protocol version 99 support library for Selenium WebDriver Java bindings

Pending
Overview
Eval results
Files

events.mddocs/

Event Handling

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.

Core Imports

import org.openqa.selenium.devtools.v99.V99Events;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.Command;
import org.openqa.selenium.devtools.Event;
import org.openqa.selenium.devtools.events.ConsoleEvent;
import org.openqa.selenium.JavascriptException;
import java.util.function.Consumer;

Capabilities

Events Handler

Creates an event monitoring handler for Chrome DevTools Protocol v99.

/**
 * Creates event monitoring handler for CDP v99
 * @param devtools - DevTools client instance
 */
public V99Events(DevTools devtools);

Runtime Domain Control

Enable and disable the JavaScript runtime domain for event collection.

/**
 * Enable JavaScript runtime domain for event monitoring
 * @return Command to enable runtime
 */
protected Command<Void> enableRuntime();

/**
 * Disable JavaScript runtime domain
 * @return Command to disable runtime
 */
protected Command<Void> disableRuntime();

High-level Event Listeners

Convenient methods for adding event listeners with automatic event conversion.

/**
 * Add listener for console events (console.log, console.error, etc.)
 * @param listener - Consumer that receives console events
 */
public void addConsoleListener(Consumer<ConsoleEvent> listener);

/**
 * Add listener for JavaScript exceptions
 * @param listener - Consumer that receives JavaScript exception events
 */
public void addJavascriptExceptionListener(Consumer<JavascriptException> listener);

/**
 * Disable event monitoring and clean up listeners
 */
public void disable();

Low-level Console Event Monitoring

Monitor browser console API calls (console.log, console.error, etc.).

/**
 * Get event handler for console API calls
 * @return Event for console messages
 */
protected Event<ConsoleAPICalled> consoleEvent();

/**
 * Convert CDP console event to Selenium console event
 * @param event - CDP console API called event
 * @return Selenium console event
 */
protected ConsoleEvent toConsoleEvent(ConsoleAPICalled event);

JavaScript Exception Monitoring

Monitor JavaScript exceptions thrown in the browser.

/**
 * Get event handler for JavaScript exceptions
 * @return Event for JavaScript exceptions
 */
protected Event<ExceptionThrown> exceptionThrownEvent();

/**
 * Convert CDP exception event to JavaScript exception
 * @param event - CDP exception thrown event
 * @return JavascriptException with stack trace
 */
protected JavascriptException toJsException(ExceptionThrown event);

Protocol Types

Console Events

/**
 * Console API called event from CDP
 */
public class ConsoleAPICalled {
    /**
     * Get console call type (log, error, warn, etc.)
     * @return Console API type
     */
    public ConsoleAPIType getType();
    
    /**
     * Get console message arguments
     * @return List of remote objects representing arguments
     */
    public List<RemoteObject> getArgs();
    
    /**
     * Get timestamp of console call
     * @return Timestamp
     */
    public Timestamp getTimestamp();
    
    /**
     * Get execution context ID where console was called
     * @return Context ID
     */
    public ExecutionContextId getExecutionContextId();
    
    /**
     * Get stack trace if available
     * @return Optional stack trace
     */
    public Optional<StackTrace> getStackTrace();
}

/**
 * Console API call types
 */
public enum ConsoleAPIType {
    LOG("log"),
    DEBUG("debug"), 
    INFO("info"),
    ERROR("error"),
    WARNING("warning"),
    CLEAR("clear"),
    DIR("dir"),
    DIRXML("dirxml"),
    TABLE("table"),
    TRACE("trace"),
    STARTGROUP("startGroup"),
    STARTGROUPCOLLAPSED("startGroupCollapsed"),
    ENDGROUP("endGroup"),
    ASSERT("assert"),
    PROFILE("profile"),
    PROFILEEND("profileEnd"),
    COUNT("count"),
    TIMEEND("timeEnd");
}

/**
 * Selenium console event (converted from CDP)
 */
public class ConsoleEvent {
    public ConsoleEvent(String type, Instant timestamp, List<Object> messages);
    
    public String getType();
    public Instant getTimestamp();
    public List<Object> getMessages();
}

Exception Events

/**
 * JavaScript exception thrown event from CDP
 */
public class ExceptionThrown {
    /**
     * Get exception details
     * @return Exception details
     */
    public ExceptionDetails getExceptionDetails();
    
    /**
     * Get timestamp when exception occurred
     * @return Timestamp
     */
    public Timestamp getTimestamp();
}

/**
 * Detailed exception information
 */
public class ExceptionDetails {
    /**
     * Get exception ID
     * @return Exception ID
     */
    public ExceptionId getExceptionId();
    
    /**
     * Get exception text/message
     * @return Exception message
     */
    public String getText();
    
    /**
     * Get line number where exception occurred
     * @return Line number
     */
    public Integer getLineNumber();
    
    /**
     * Get column number where exception occurred  
     * @return Column number
     */
    public Integer getColumnNumber();
    
    /**
     * Get URL/script where exception occurred
     * @return Optional URL
     */
    public Optional<String> getUrl();
    
    /**
     * Get stack trace if available
     * @return Optional stack trace
     */
    public Optional<StackTrace> getStackTrace();
    
    /**
     * Get exception object details
     * @return Optional remote object representing the exception
     */
    public Optional<RemoteObject> getException();
    
    /**
     * Get execution context ID where exception occurred
     * @return Optional context ID
     */
    public Optional<ExecutionContextId> getExecutionContextId();
}

Common Types

/**
 * Remote JavaScript object representation
 */
public class RemoteObject {
    /**
     * Get object type (string, number, boolean, object, etc.)
     * @return Object type
     */
    public RemoteObjectType getType();
    
    /**
     * Get object value if primitive
     * @return Optional value
     */
    public Optional<Object> getValue();
    
    /**
     * Get object description
     * @return Optional description string  
     */
    public Optional<String> getDescription();
}

/**
 * JavaScript stack trace information
 */
public class StackTrace {
    /**
     * Get description of the stack trace
     * @return Optional description
     */
    public Optional<String> getDescription();
    
    /**
     * Get call frames in the stack trace
     * @return List of call frames
     */
    public List<CallFrame> getCallFrames();
    
    /**
     * Get parent stack trace if available
     * @return Optional parent stack trace
     */
    public Optional<StackTrace> getParent();
}

/**
 * Individual call frame in stack trace
 */
public class CallFrame {
    /**
     * Get function name
     * @return Function name
     */
    public String getFunctionName();
    
    /**
     * Get script URL
     * @return Script URL
     */
    public String getUrl();
    
    /**
     * Get line number in script
     * @return Line number (0-based)
     */
    public Integer getLineNumber();
    
    /**
     * Get column number in line
     * @return Column number (0-based)
     */
    public Integer getColumnNumber();
}

/**
 * CDP timestamp representation
 */
public class Timestamp {
    /**
     * Convert timestamp to JSON number
     * @return JSON representation
     */
    public JsonInput toJson();
    
    /**
     * Convert to string representation
     * @return String representation
     */
    public String toString();
}

Usage Examples

Basic Console Monitoring

import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v99.V99Domains;
import org.openqa.selenium.devtools.events.ConsoleEvent;

DevTools devTools = ...; // from ChromeDriver
V99Domains domains = new V99Domains(devTools);

// Add console listener using high-level API
domains.events().addConsoleListener(consoleEvent -> {
    System.out.printf("[%s] %s: %s%n", 
        consoleEvent.getTimestamp(),
        consoleEvent.getType(),
        consoleEvent.getMessages()
    );
});

// Now navigate to page - console messages will be captured
driver.get("https://example.com");

Exception Monitoring

// Add JavaScript exception listener using high-level API
domains.events().addJavascriptExceptionListener(jsException -> {
    System.err.println("JavaScript Exception: " + jsException.getMessage());
    
    // Print stack trace
    for (StackTraceElement element : jsException.getStackTrace()) {
        System.err.println("  at " + element.toString());
    }
});

// This will trigger exception monitoring for any JavaScript errors
driver.executeScript("throw new Error('Test exception');");

Combined Event Monitoring

// Set up both console and exception monitoring together
domains.events().addConsoleListener(consoleEvent -> {
    // Handle console messages based on type
    switch (consoleEvent.getType()) {
        case "error":
            System.err.println("Console Error: " + consoleEvent.getMessages());
            break;
        case "warning":
            System.out.println("Console Warning: " + consoleEvent.getMessages());
            break;
        default:
            System.out.println("Console " + consoleEvent.getType() + ": " + consoleEvent.getMessages());
    }
});

domains.events().addJavascriptExceptionListener(jsException -> {
    System.err.println("JavaScript Exception: " + jsException.getMessage());
    logExceptionToTestResults(jsException);
});

// Execute test operations - both console and exception events will be captured

// Cleanup when done
domains.events().disable(); // Disables runtime and cleans up listeners

Advanced Console Event Processing (Low-level API)

devTools.send(domains.events().enableRuntime());

devTools.addListener(domains.events().consoleEvent(), consoleApiEvent -> {
    String type = consoleApiEvent.getType().toString();
    List<RemoteObject> args = consoleApiEvent.getArgs();
    
    // Process different console types differently
    switch (type) {
        case "error":
            handleConsoleError(args);
            break;
        case "warning":
            handleConsoleWarning(args);
            break;
        case "log":
        case "info":
            handleConsoleInfo(args);
            break;
        case "table":
            handleConsoleTable(args);
            break;
        default:
            handleGenericConsole(type, args);
    }
});

private void handleConsoleError(List<RemoteObject> args) {
    // Convert remote objects to meaningful error data
    args.forEach(arg -> {
        if (arg.getType() == RemoteObjectType.STRING && arg.getValue().isPresent()) {
            System.err.println("Console Error: " + arg.getValue().get());
        }
    });
}

Filtering Events by Context

// Store execution contexts for filtering
Set<ExecutionContextId> monitoredContexts = new HashSet<>();

devTools.addListener(domains.events().consoleEvent(), consoleEvent -> {
    ExecutionContextId contextId = consoleEvent.getExecutionContextId();
    
    // Only process events from specific contexts
    if (monitoredContexts.contains(contextId)) {
        ConsoleEvent seleniumEvent = domains.events().toConsoleEvent(consoleEvent);
        processConsoleEvent(seleniumEvent);
    }
});

// Add context to monitoring set when needed
// (typically done through other DevTools events or direct context creation)

Exception Details Extraction

devTools.addListener(domains.events().exceptionThrownEvent(), exceptionEvent -> {
    ExceptionDetails details = exceptionEvent.getExceptionDetails();
    
    System.err.println("Exception Details:");
    System.err.println("  Message: " + details.getText());
    System.err.println("  Line: " + details.getLineNumber());
    System.err.println("  Column: " + details.getColumnNumber());
    
    details.getUrl().ifPresent(url -> 
        System.err.println("  URL: " + url));
    
    details.getStackTrace().ifPresent(stackTrace -> {
        System.err.println("  Stack Trace:");
        stackTrace.getCallFrames().forEach(frame -> {
            System.err.printf("    at %s (%s:%d:%d)%n",
                frame.getFunctionName().isEmpty() ? "<anonymous>" : frame.getFunctionName(),
                frame.getUrl(),
                frame.getLineNumber(),
                frame.getColumnNumber()
            );
        });
    });
});

Event Cleanup

// Always disable runtime when done to clean up resources
try {
    // Perform operations requiring event monitoring
    performTestOperations();
} finally {
    // Clean up - disable runtime domain
    devTools.send(domains.events().disableRuntime());
}

Error Handling

Event monitoring operations can encounter various issues:

  • Runtime not enabled: Enable runtime domain before event monitoring
  • Event overflow: High-frequency events can overwhelm listeners
  • Context mismatches: Events may come from unexpected execution contexts
  • Memory leaks: Event listeners should be properly cleaned up

Handle errors through proper exception handling and resource management:

try {
    devTools.send(domains.events().enableRuntime());
    
    // Set up event listeners
    setupEventListeners();
    
    // Perform test operations
    runTests();
    
} catch (DevToolsException e) {
    System.err.println("Failed to enable event monitoring: " + e.getMessage());
} finally {
    // Always clean up
    try {
        devTools.send(domains.events().disableRuntime());
    } catch (Exception e) {
        System.err.println("Failed to disable runtime: " + e.getMessage());
    }
}

Performance Considerations

  • Event frequency: Console events can be very frequent; filter appropriately
  • Object serialization: Remote objects may contain large data structures
  • Memory management: Event listeners hold references that can prevent garbage collection
  • Context tracking: Monitor only necessary execution contexts to reduce overhead
  • Stack trace depth: Deep stack traces can consume significant memory and processing time

Install with Tessl CLI

npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-devtools-v99

docs

events.md

index.md

javascript.md

logging.md

network.md

targets.md

tile.json