A headless browser for Java programs that provides web automation, form handling, JavaScript execution, and DOM manipulation capabilities.
—
JavaScript engine configuration and event handling including script execution control, error handling, and browser API simulation for comprehensive JavaScript support in headless browsing.
Control JavaScript execution and configure engine behavior for optimal performance and compatibility.
/**
* Enable or disable JavaScript execution globally
* @param enabled true to enable JavaScript processing
*/
public void setJavaScriptEnabled(boolean enabled);
/**
* Check if JavaScript is currently enabled
* @return true if JavaScript execution is enabled
*/
public boolean isJavaScriptEnabled();
/**
* Configure whether JavaScript errors should throw exceptions
* @param throwException true to throw exceptions on script errors
*/
public void setThrowExceptionOnScriptError(boolean throwException);
/**
* Wait for background JavaScript tasks to complete
* @param timeoutMillis maximum time to wait in milliseconds
* @return number of JavaScript jobs that completed
*/
public int waitForBackgroundJavaScript(long timeoutMillis);Usage Examples:
WebClient webClient = new WebClient();
// Enable JavaScript for dynamic pages
webClient.getOptions().setJavaScriptEnabled(true);
// Configure error handling - don't fail on script errors
webClient.getOptions().setThrowExceptionOnScriptError(false);
// Load a page with JavaScript
HtmlPage page = webClient.getPage("https://example.com/dynamic-app");
// Wait for JavaScript to complete (AJAX, timers, etc.)
webClient.waitForBackgroundJavaScript(5000); // Wait up to 5 seconds
// Now interact with the fully loaded page
HtmlElement dynamicContent = page.getElementById("ajax-loaded-content");Handle JavaScript alert() dialog boxes with custom alert handlers.
public interface AlertHandler {
/**
* Handle a JavaScript alert dialog
* @param page the page that triggered the alert
* @param message the alert message text
*/
void handleAlert(Page page, String message);
}
/**
* Set a custom handler for JavaScript alert() calls
* @param handler the AlertHandler implementation
*/
public void setAlertHandler(AlertHandler handler);Usage Examples:
// Simple alert handler that prints to console
webClient.setAlertHandler(new AlertHandler() {
@Override
public void handleAlert(Page page, String message) {
System.out.println("JavaScript Alert on " + page.getUrl() + ": " + message);
}
});
// Lambda-based alert handler
webClient.setAlertHandler((page, message) -> {
System.out.println("Alert: " + message);
});
// Store alerts for later verification in tests
List<String> alerts = new ArrayList<>();
webClient.setAlertHandler((page, message) -> alerts.add(message));
// Load page that shows alerts
HtmlPage page = webClient.getPage("https://example.com/alert-demo");
// JavaScript: alert("Welcome to our site!");
// Check collected alerts
assertEquals(1, alerts.size());
assertEquals("Welcome to our site!", alerts.get(0));Handle JavaScript confirm() dialog boxes with custom confirm handlers that can return true/false responses.
public interface ConfirmHandler {
/**
* Handle a JavaScript confirm dialog
* @param page the page that triggered the confirm
* @param message the confirm message text
* @return true to simulate clicking "OK", false for "Cancel"
*/
boolean handleConfirm(Page page, String message);
}
/**
* Set a custom handler for JavaScript confirm() calls
* @param handler the ConfirmHandler implementation
*/
public void setConfirmHandler(ConfirmHandler handler);Usage Examples:
// Always confirm (click "OK")
webClient.setConfirmHandler((page, message) -> {
System.out.println("Confirm: " + message + " -> OK");
return true;
});
// Conditional confirm based on message content
webClient.setConfirmHandler((page, message) -> {
if (message.contains("delete")) {
System.out.println("Confirming deletion: " + message);
return true;
} else {
System.out.println("Canceling: " + message);
return false;
}
});
// Test confirm behavior
HtmlPage page = webClient.getPage("https://example.com/confirm-demo");
HtmlButton deleteBtn = page.getElementById("deleteButton");
// JavaScript: if (confirm("Are you sure you want to delete this item?")) { ... }
deleteBtn.click(); // Will trigger confirm handlerHandle JavaScript prompt() dialog boxes with custom prompt handlers that can provide input values.
public interface PromptHandler {
/**
* Handle a JavaScript prompt dialog
* @param page the page that triggered the prompt
* @param message the prompt message text
* @param defaultValue the default value shown in the prompt, may be null
* @return the value to return to JavaScript, or null to simulate "Cancel"
*/
String handlePrompt(Page page, String message, String defaultValue);
}
/**
* Set a custom handler for JavaScript prompt() calls
* @param handler the PromptHandler implementation
*/
public void setPromptHandler(PromptHandler handler);Usage Examples:
// Simple prompt handler that returns default values
webClient.setPromptHandler((page, message, defaultValue) -> {
System.out.println("Prompt: " + message);
return defaultValue != null ? defaultValue : "default response";
});
// Dynamic prompt responses based on message
webClient.setPromptHandler((page, message, defaultValue) -> {
if (message.contains("name")) {
return "John Doe";
} else if (message.contains("email")) {
return "john@example.com";
} else {
return defaultValue;
}
});
// Cancel specific prompts
webClient.setPromptHandler((page, message, defaultValue) -> {
if (message.contains("password")) {
// Return null to simulate clicking "Cancel"
return null;
}
return "some value";
});
// Usage in testing
HtmlPage page = webClient.getPage("https://example.com/prompt-demo");
// JavaScript: var name = prompt("Please enter your name:", "Guest");
// Will use the configured prompt handlerHandle JavaScript execution errors with detailed error listeners and custom error processing.
public interface JavaScriptErrorListener {
/**
* Handle JavaScript runtime exceptions
* @param page the page where the error occurred
* @param scriptException the JavaScript exception details
*/
void scriptException(HtmlPage page, ScriptException scriptException);
/**
* Handle JavaScript execution timeouts
* @param page the page where the timeout occurred
* @param allowedTime the maximum time allowed for execution
* @param executionTime the actual execution time
*/
void timeoutError(HtmlPage page, long allowedTime, long executionTime);
/**
* Handle malformed script URLs
* @param page the page with the malformed URL
* @param url the malformed URL string
* @param malformedURLException the URL parsing exception
*/
void malformedScriptURL(HtmlPage page, String url, MalformedURLException malformedURLException);
/**
* Handle script loading errors
* @param page the page where the error occurred
* @param scriptUrl the URL of the script that failed to load
* @param exception the loading exception
*/
void loadScriptError(HtmlPage page, URL scriptUrl, Exception exception);
}
public class DefaultJavaScriptErrorListener implements JavaScriptErrorListener {
// Default implementation that logs errors
}
public class SilentJavaScriptErrorListener implements JavaScriptErrorListener {
// Silent implementation that ignores all errors
}
/**
* Set a JavaScript error listener
* @param listener the JavaScriptErrorListener implementation
*/
public void setJavaScriptErrorListener(JavaScriptErrorListener listener);Usage Examples:
// Custom error listener for debugging
webClient.setJavaScriptErrorListener(new JavaScriptErrorListener() {
@Override
public void scriptException(HtmlPage page, ScriptException scriptException) {
System.err.println("JavaScript Error on " + page.getUrl());
System.err.println("Error: " + scriptException.getMessage());
scriptException.printStackTrace();
}
@Override
public void timeoutError(HtmlPage page, long allowedTime, long executionTime) {
System.err.println("JavaScript Timeout on " + page.getUrl());
System.err.println("Allowed: " + allowedTime + "ms, Actual: " + executionTime + "ms");
}
@Override
public void malformedScriptURL(HtmlPage page, String url, MalformedURLException exception) {
System.err.println("Malformed Script URL: " + url);
}
@Override
public void loadScriptError(HtmlPage page, URL scriptUrl, Exception exception) {
System.err.println("Failed to load script: " + scriptUrl);
}
});
// Use silent listener to ignore all JavaScript errors
webClient.setJavaScriptErrorListener(new SilentJavaScriptErrorListener());
// Collect errors for testing
List<ScriptException> scriptErrors = new ArrayList<>();
webClient.setJavaScriptErrorListener(new JavaScriptErrorListener() {
@Override
public void scriptException(HtmlPage page, ScriptException scriptException) {
scriptErrors.add(scriptException);
}
// Implement other methods as needed
@Override
public void timeoutError(HtmlPage page, long allowedTime, long executionTime) {}
@Override
public void malformedScriptURL(HtmlPage page, String url, MalformedURLException exception) {}
@Override
public void loadScriptError(HtmlPage page, URL scriptUrl, Exception exception) {}
});Exception types thrown by JavaScript execution problems.
public class ScriptException extends RuntimeException {
// Runtime JavaScript execution errors
// Contains details about the JavaScript error
}
public class ElementNotFoundException extends RuntimeException {
// Thrown when JavaScript tries to access non-existent DOM elements
}Usage Examples:
try {
// Enable JavaScript error exceptions
webClient.getOptions().setThrowExceptionOnScriptError(true);
HtmlPage page = webClient.getPage("https://example.com/broken-js");
} catch (ScriptException e) {
System.err.println("JavaScript execution failed: " + e.getMessage());
// Handle specific error conditions
if (e.getMessage().contains("undefined")) {
System.err.println("Undefined variable or function");
}
}Advanced techniques for working with JavaScript-heavy applications.
Usage Examples:
// Configuration for single-page applications (SPAs)
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(true); // May be needed for layout-dependent JS
webClient.getOptions().setThrowExceptionOnScriptError(false);
// Set up comprehensive JavaScript handlers
webClient.setAlertHandler((page, message) -> System.out.println("Alert: " + message));
webClient.setConfirmHandler((page, message) -> true); // Auto-confirm
webClient.setPromptHandler((page, message, defaultValue) -> defaultValue);
// Load SPA and wait for initialization
HtmlPage page = webClient.getPage("https://example.com/spa");
// Wait for initial JavaScript setup
webClient.waitForBackgroundJavaScript(3000);
// Wait for specific element to appear (loaded by AJAX)
int attempts = 0;
HtmlElement dynamicButton = null;
while (attempts < 10 && dynamicButton == null) {
dynamicButton = page.getElementById("ajax-loaded-button");
if (dynamicButton == null) {
Thread.sleep(500);
webClient.waitForBackgroundJavaScript(1000);
attempts++;
}
}
if (dynamicButton != null) {
// Interact with dynamically loaded content
dynamicButton.click();
webClient.waitForBackgroundJavaScript(2000);
}
// For testing JavaScript-generated content
String pageContent = page.asNormalizedText();
assertTrue("Expected content not found", pageContent.contains("Dynamic Content Loaded"));Install with Tessl CLI
npx tessl i tessl/maven-org-htmlunit--htmlunit