Sahi operates as an intermediary proxy server that intercepts HTTP traffic between the browser and web server, injecting JavaScript to manipulate DOM elements dynamically. Unlike conventional automation frameworks that rely on rigid locator strategies, Sahi employs a context-aware identification mechanism that adapts to dynamic web applications through visible attributes and spatial relationships.
Comparison with Traditional Automation Tools
While Selenium supports multiple scripting languages and Watir emphasizes execution speed, Sahi differentiates itself through built-in recording capabilities, cross-browser compatibility, and intelligent synchronization mechanisms. The tool excels in handling Ajax-heavy interfaces and Web 2.0 applications without requiring explicit wait statements.
Context-Based Element Identification
Traditional automation relies on DOM traversal, XPath expressions, or static attributes like id and name. These approaches become fragile when applications generate dynamic identifiers or modify structural hierarchies frequently.
Sahi implements a relationship-based lookup strategy using three primary APIs:
_in(container): Restricts search within a specific parent element_near(anchor): Locates elements adjacent to a reference point_under(header): Finds elements positioned below a specified header
Consider a product catalog interface where multiple input fields share identical attributes:
_input("quantity", _near(_cell("Wireless Mouse")), _under(_cell("Stock")))
This locates the quantity field specifically for the "Wireless Mouse" row under the "Stock" column, eliminating ambiguity without relying on brittle XPath expressions.
For nested structures within complex tables:
_checkbox("select", _in(_div("OrderSummary")), _near(_text("Premium Plan")))
Regular expressions further enhance flexibility:
_button(/submit.*order/i)
Intelligent Synchronization Mechanism
Modern web applications utilize asynchronous JavaScript and XML (Ajax) to fetch data dynamically. Conventional tools require manual polling or arbitrary sleep intervals, creating either flaky tests or unnecessary delays.
Sahi embeds an implicit wait system that automatically detects Ajax completion states. The proxy monitors network activity and DOM stability, proceeding with subsequent actions only when the application reaches a quiescent state. This eliminates the need for explicit Thread.sleep() calls or custom polling logic in test scripts.
Architectural Workflow
The automation process follows three distinct phases:
1. Capture Phase The proxy intercepts user interactions, translating mouse clicks and keyboard inputs into executable scripts. Sahi injects event listeners into the browser via its proxy layer, recording actions without browser extensions.
2. Refinement Phase Raw recorded scripts undergo parameterization and modularization. Hard-coded values transform into variables, enabling data-driven testing from external CSV files or databases. Reusable functions encapsulate common workflows:
function authenticate($user, $pass) {
_setValue(_textbox("email"), $user);
_setValue(_password("pwd"), $pass);
_click(_button("Sign In"));
}
3. Execution Phase The refined script executes through the proxy layer, which translates commands into browser-specific actions. Results generate detailed logs with screenshots and stack traces for failed assertions.
Installation and Configuration
Download the executible JAR (sahi-installer.jar) from SourceForge. Execute the installer to deploy the proxy components and browser configurations. The installation creates a userdata directory for scripts and logs.
Launch the Sahi Dashboard to initialize the proxy service on port 9999 (configurable). The dashboard auto-detects installed browsers; manually configure additional browsers via the configuration panel if necessary.
For HTTPS testing, access the SSL Manager through the dashboard to install root certificates, enabling traffic decryption for secure sites.
Recording and Script Development
Initiate recording through the Controller interface (accessed via Alt-double-click on any webpage). Specify a script name and perform the desired workflow. The recorder captures element interactions using Sahi's accessor syntax.
Add assertions during recording by Ctrl-hovering over target elements. The Controller displays available actions—assert, highlight, or storeValue—allowing verification points within the workflow.
Generated scripts reside in userdata/scripts/ by default. Refactor these to eliminate redundancy:
// Raw recorded line
_click(_link("Dashboard"));
// Refactored with explicit wait and highlight
_highlight(_link("Dashboard"));
_click(_link("Dashboard"));
Java integration extends capabilities for enterprise environments. Include sahi.jar in the classpath and initialize the configuration:
import net.sf.sahi.client.Browser;
import net.sf.sahi.config.Configuration;
String basePath = "D:/automation/sahi/";
String userData = "D:/automation/sahi/userdata";
Configuration.initJava(basePath, userData);
Browser driver = new Browser("chrome");
driver.open();
driver.navigateTo("https://demo.example.com");
driver.textbox("username").setValue("admin");
driver.password("secret").setValue("p@ssw0rd");
driver.submit("login").click();
String result = driver.textbox("message").value();
System.out.println("Response: " + result);
driver.close();
Script Syntax Fundamentals
Sahi scripts utilize JavaScript syntax with mandatory dollar-sign prefixes for variables:
var $customerId = "CUST-2024-001";
var $orderTotal;
$orderTotal = calculateSum($lineItems);
Function definitions follow standard JavaScript conventions:
function calculateSum($items) {
var $sum = 0;
for (var $i = 0; $i < $items.length; $i++) {
$sum += $items[$i];
}
return $sum;
}
External libraries load via _include():
_include("lib/utilities.sah");
_include("data/testdata.sah");
API categories include:
- Accessors:
_textbox(),_button(),_table() - Actions:
_click(),_setValue(),_check() - Utilities:
_log(),_wait(),_alert()
Execution and Reporting
Run scripts through the Controller's Playback tab or via command-line for CI/CD integration:
java -cp lib/sahi.jar net.sf.sahi.test.TestRunner test.sah
Logs generate in HTML format with step-by-step execution traces, screenshots on failure, and performance metrics. Configure sahi.properties to adjust timeout thresholds and browser launch parameters.