CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-seleniumhq-selenium--selenium-api

Selenium WebDriver core API for automating web browsers across different platforms and programming languages.

Pending
Overview
Eval results
Files

javascript.mddocs/

JavaScript Execution

Interface for executing JavaScript code in the browser context with support for synchronous/asynchronous execution, script pinning, and argument passing.

Capabilities

JavascriptExecutor Interface

Interface for executing JavaScript code within the browser context with parameter passing and return value handling.

/**
 * JavascriptExecutor interface for executing JavaScript code in browser context
 * Provides synchronous and asynchronous script execution with argument passing
 */
interface JavascriptExecutor {
    /**
     * Execute JavaScript synchronously in browser context
     * @param script - JavaScript code to execute
     * @param args - Arguments to pass to script (accessible as arguments[0], arguments[1], etc.)
     * @return Result of script execution (may be null, primitive, WebElement, or List)
     */
    Object executeScript(String script, Object... args);
    
    /**
     * Execute JavaScript asynchronously in browser context
     * @param script - JavaScript code to execute (must call callback to complete)
     * @param args - Arguments to pass to script
     * @return Result of script execution
     */
    Object executeAsyncScript(String script, Object... args);
    
    /**
     * Pin script for reuse with better performance
     * @param script - JavaScript code to pin
     * @return ScriptKey for referencing pinned script
     */
    ScriptKey pin(String script);
    
    /**
     * Unpin previously pinned script
     * @param key - ScriptKey of script to unpin
     */
    void unpin(ScriptKey key);
    
    /**
     * Get all currently pinned scripts
     * @return Set of ScriptKey objects for pinned scripts
     */
    Set<ScriptKey> getPinnedScripts();
    
    /**
     * Execute pinned script by key
     * @param key - ScriptKey of pinned script
     * @param args - Arguments to pass to script
     * @return Result of script execution
     */
    Object executeScript(ScriptKey key, Object... args);
}

ScriptKey Class

Reference key for pinned JavaScript scripts enabling efficient reuse.

/**
 * ScriptKey class representing a pinned JavaScript script
 * Used for efficient execution of frequently used scripts
 */
class ScriptKey {
    /**
     * Get script identifier
     * @return Unique identifier for the pinned script
     */
    String getId();
    
    /**
     * Get original script content
     * @return JavaScript code that was pinned
     */
    String getScript();
}

Usage Examples

Basic JavaScript Execution

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.chrome.ChromeDriver;

WebDriver driver = new ChromeDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;

try {
    driver.get("https://example.com");
    
    // Simple script execution
    String title = (String) js.executeScript("return document.title;");
    System.out.println("Page title: " + title);
    
    // Execute script with return value
    Long scrollHeight = (Long) js.executeScript("return document.body.scrollHeight;");
    System.out.println("Page height: " + scrollHeight);
    
    // Execute script that modifies the page
    js.executeScript("document.body.style.backgroundColor = 'lightblue';");
    
    // Execute script with no return value
    js.executeScript("console.log('Hello from WebDriver!');");
    
} finally {
    driver.quit();
}

JavaScript with Arguments

// Pass arguments to JavaScript
WebElement element = driver.findElement(By.id("myElement"));
String elementText = (String) js.executeScript(
    "return arguments[0].textContent;", 
    element
);

// Multiple arguments
js.executeScript(
    "arguments[0].style.backgroundColor = arguments[1]; arguments[0].style.color = arguments[2];",
    element,
    "yellow",
    "red"
);

// Pass different types of arguments
js.executeScript(
    "var element = arguments[0]; var show = arguments[1]; var delay = arguments[2]; " +
    "if (show) { element.style.display = 'block'; } " +
    "setTimeout(function() { element.style.opacity = '1'; }, delay);",
    element,
    true,
    1000
);

// Return complex objects
Map<String, Object> elementInfo = (Map<String, Object>) js.executeScript(
    "var elem = arguments[0]; " +
    "return { " +
    "  tagName: elem.tagName, " +
    "  id: elem.id, " +
    "  className: elem.className, " +
    "  visible: elem.offsetWidth > 0 && elem.offsetHeight > 0 " +
    "};",
    element
);

DOM Manipulation and Queries

// Scroll to element
WebElement targetElement = driver.findElement(By.id("target"));
js.executeScript("arguments[0].scrollIntoView(true);", targetElement);

// Highlight element
js.executeScript(
    "arguments[0].style.border = '3px solid red';" +
    "arguments[0].style.backgroundColor = 'yellow';",
    targetElement
);

// Get element position and size
Map<String, Object> elementBounds = (Map<String, Object>) js.executeScript(
    "var rect = arguments[0].getBoundingClientRect(); " +
    "return { " +
    "  x: rect.left, " +
    "  y: rect.top, " +
    "  width: rect.width, " +
    "  height: rect.height " +
    "};",
    targetElement
);

// Check if element is in viewport
Boolean isInViewport = (Boolean) js.executeScript(
    "var rect = arguments[0].getBoundingClientRect(); " +
    "return rect.top >= 0 && rect.left >= 0 && " +
    "rect.bottom <= window.innerHeight && rect.right <= window.innerWidth;",
    targetElement
);

// Find elements by complex criteria
List<WebElement> visibleElements = (List<WebElement>) js.executeScript(
    "var elements = document.querySelectorAll(arguments[0]); " +
    "var visible = []; " +
    "for (var i = 0; i < elements.length; i++) { " +
    "  if (elements[i].offsetWidth > 0 && elements[i].offsetHeight > 0) { " +
    "    visible.push(elements[i]); " +
    "  } " +
    "} " +
    "return visible;",
    ".product-card"
);

Asynchronous JavaScript Execution

// Set script timeout for async operations
driver.manage().timeouts().setScriptTimeout(Duration.ofSeconds(30));

// Simple async script with callback
String result = (String) js.executeAsyncScript(
    "var callback = arguments[arguments.length - 1]; " +
    "setTimeout(function() { " +
    "  callback('Async operation completed'); " +
    "}, 2000);"
);

// AJAX request with async script
String responseText = (String) js.executeAsyncScript(
    "var callback = arguments[arguments.length - 1]; " +
    "var xhr = new XMLHttpRequest(); " +
    "xhr.open('GET', arguments[0], true); " +
    "xhr.onreadystatechange = function() { " +
    "  if (xhr.readyState === 4) { " +
    "    callback(xhr.responseText); " +
    "  } " +
    "}; " +
    "xhr.send();",
    "https://api.example.com/data"
);

// Wait for page element to load asynchronously
WebElement dynamicElement = (WebElement) js.executeAsyncScript(
    "var callback = arguments[arguments.length - 1]; " +
    "var checkElement = function() { " +
    "  var element = document.querySelector(arguments[0]); " +
    "  if (element) { " +
    "    callback(element); " +
    "  } else { " +
    "    setTimeout(checkElement, 100); " +
    "  } " +
    "}; " +
    "checkElement();",
    "#dynamic-content"
);

Script Pinning for Performance

// Pin frequently used scripts
ScriptKey scrollScript = js.pin(
    "window.scrollTo(0, arguments[0]);"
);

ScriptKey highlightScript = js.pin(
    "arguments[0].style.border = '2px solid ' + arguments[1];" +
    "arguments[0].style.backgroundColor = arguments[2];"
);

ScriptKey getElementInfoScript = js.pin(
    "var elem = arguments[0]; " +
    "return { " +
    "  text: elem.textContent, " +
    "  visible: elem.offsetWidth > 0 && elem.offsetHeight > 0, " +
    "  classes: elem.className.split(' '), " +
    "  attributes: Array.from(elem.attributes).map(attr => ({name: attr.name, value: attr.value})) " +
    "};"
);

// Use pinned scripts multiple times
js.executeScript(scrollScript, 500);
js.executeScript(scrollScript, 1000);

WebElement button1 = driver.findElement(By.id("btn1"));
WebElement button2 = driver.findElement(By.id("btn2"));

js.executeScript(highlightScript, button1, "red", "yellow");
js.executeScript(highlightScript, button2, "blue", "lightgreen");

Map<String, Object> info1 = (Map<String, Object>) js.executeScript(getElementInfoScript, button1);
Map<String, Object> info2 = (Map<String, Object>) js.executeScript(getElementInfoScript, button2);

// Clean up pinned scripts when done
js.unpin(scrollScript);
js.unpin(highlightScript);
js.unpin(getElementInfoScript);

// Or get all pinned scripts and unpin them
Set<ScriptKey> pinnedScripts = js.getPinnedScripts();
pinnedScripts.forEach(js::unpin);

Page Analysis and Testing

// Performance metrics
Map<String, Object> performanceData = (Map<String, Object>) js.executeScript(
    "var perf = window.performance; " +
    "var timing = perf.timing; " +
    "return { " +
    "  loadTime: timing.loadEventEnd - timing.navigationStart, " +
    "  domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart, " +
    "  firstPaint: perf.getEntriesByType('paint')[0]?.startTime || null, " +
    "  memoryUsage: perf.memory ? perf.memory.usedJSHeapSize : null " +
    "};"
);

// Accessibility checks
List<Map<String, Object>> accessibilityIssues = (List<Map<String, Object>>) js.executeScript(
    "var issues = []; " +
    "var images = document.querySelectorAll('img'); " +
    "images.forEach(function(img, index) { " +
    "  if (!img.alt) { " +
    "    issues.push({type: 'missing-alt', element: 'img', index: index}); " +
    "  } " +
    "}); " +
    "var links = document.querySelectorAll('a'); " +
    "links.forEach(function(link, index) { " +
    "  if (!link.textContent.trim() && !link.getAttribute('aria-label')) { " +
    "    issues.push({type: 'empty-link', element: 'a', index: index}); " +
    "  } " +
    "}); " +
    "return issues;"
);

// Form validation status
Boolean isFormValid = (Boolean) js.executeScript(
    "var form = arguments[0]; " +
    "return form.checkValidity();",
    driver.findElement(By.id("myForm"))
);

// Get all form errors
List<String> formErrors = (List<String>) js.executeScript(
    "var form = arguments[0]; " +
    "var errors = []; " +
    "var inputs = form.querySelectorAll('input, select, textarea'); " +
    "inputs.forEach(function(input) { " +
    "  if (!input.checkValidity()) { " +
    "    errors.push(input.name + ': ' + input.validationMessage); " +
    "  } " +
    "}); " +
    "return errors;",
    driver.findElement(By.id("myForm"))
);

Advanced JavaScript Patterns

// Custom event triggering
js.executeScript(
    "var event = new CustomEvent(arguments[1], {detail: arguments[2]}); " +
    "arguments[0].dispatchEvent(event);",
    targetElement,
    "customEvent",
    Map.of("data", "test")
);

// Cookie manipulation
js.executeScript("document.cookie = arguments[0] + '=' + arguments[1] + '; path=/';", "testCookie", "testValue");
String cookieValue = (String) js.executeScript(
    "return document.cookie.split('; ').find(row => row.startsWith(arguments[0] + '=')).split('=')[1];",
    "testCookie"
);

// Local storage operations
js.executeScript("localStorage.setItem(arguments[0], arguments[1]);", "key", "value");
String storedValue = (String) js.executeScript("return localStorage.getItem(arguments[0]);", "key");

// Session storage operations
js.executeScript("sessionStorage.setItem(arguments[0], JSON.stringify(arguments[1]));", "userData", Map.of("name", "John", "age", 30));
Map<String, Object> userData = (Map<String, Object>) js.executeScript(
    "return JSON.parse(sessionStorage.getItem(arguments[0]));",
    "userData"
);

// Dynamic CSS injection
js.executeScript(
    "var style = document.createElement('style'); " +
    "style.textContent = arguments[0]; " +
    "document.head.appendChild(style);",
    ".highlight { background-color: yellow; border: 2px solid red; }"
);

Error Handling in JavaScript Execution

// Safe script execution with error handling
public Object safeExecuteScript(JavascriptExecutor js, String script, Object... args) {
    try {
        return js.executeScript(
            "try { " +
            "  return (function() { " + script + " })(); " +
            "} catch (e) { " +
            "  return {error: e.message, stack: e.stack}; " +
            "}",
            args
        );
    } catch (Exception e) {
        System.err.println("Script execution failed: " + e.getMessage());
        return null;
    }
}

// Check if result is an error
public boolean isScriptError(Object result) {
    if (result instanceof Map) {
        Map<String, Object> resultMap = (Map<String, Object>) result;
        return resultMap.containsKey("error");
    }
    return false;
}

// Usage
Object result = safeExecuteScript(js, "return document.querySelector('#nonexistent').textContent;");
if (isScriptError(result)) {
    Map<String, Object> error = (Map<String, Object>) result;
    System.err.println("JavaScript error: " + error.get("error"));
} else {
    System.out.println("Result: " + result);
}

// Timeout handling for async scripts
public Object executeAsyncScriptWithTimeout(JavascriptExecutor js, String script, Duration timeout, Object... args) {
    // Set script timeout
    driver.manage().timeouts().setScriptTimeout(timeout);
    
    try {
        return js.executeAsyncScript(script, args);
    } catch (ScriptTimeoutException e) {
        System.err.println("Async script timed out after " + timeout.getSeconds() + " seconds");
        return null;
    } finally {
        // Reset to default timeout
        driver.manage().timeouts().setScriptTimeout(Duration.ofSeconds(30));
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-seleniumhq-selenium--selenium-api

docs

alerts.md

configuration.md

drivers.md

elements.md

index.md

interactions.md

javascript.md

locators.md

page-objects.md

waits.md

webdriver.md

tile.json