Handling JavaScript-Based Applications in Selenium WebDriver
Modern web applications are heavily dependent on JavaScript to create dynamic, interactive, and responsive user interfaces. Applications built with JavaScript frameworks such as React, Angular, Vue.js, and other client-side technologies frequently update page content without performing a complete browser refresh. Handling such JavaScript-based applications effectively is an important skill for Selenium WebDriver automation.
In Selenium automation, JavaScript can control page elements, load dynamic content, modify the DOM, trigger browser events, display or hide elements, handle asynchronous operations, and communicate with backend services through AJAX or Fetch APIs. Because of this dynamic behavior, Selenium tests must be designed carefully to locate elements at the correct time, wait for required conditions, handle DOM changes, and interact with elements reliably.
This topic explains how Selenium WebDriver works with JavaScript-based applications, including dynamic elements, AJAX requests, JavaScriptExecutor, waits, asynchronous content, DOM updates, React and Angular applications, event handling, stale elements, scrolling, hidden elements, overlays, and practical automation techniques.
Selenium Training Course | Register for Course Demo
1. What is a JavaScript-Based Application?
A JavaScript-based application is a web application that uses JavaScript extensively to control the user interface, perform calculations, communicate with servers, update page content, and respond to user actions.
Unlike traditional websites where clicking a link may reload the entire page, JavaScript applications can update only a specific section of the page while the rest of the application remains unchanged.
User Action
|
v
JavaScript Event
|
v
API / Server Request
|
v
Response Received
|
v
DOM Updated
|
v
User Interface Changes
2. Examples of JavaScript-Based Applications
- React applications
- Angular applications
- Vue.js applications
- Single Page Applications (SPA)
- AJAX-based applications
- Dynamic dashboards
- E-commerce websites
- Online banking applications
- Booking applications
- CRM applications
- Real-time chat applications
- Social media applications
3. Why JavaScript Applications Are Challenging for Selenium?
JavaScript applications continuously modify the DOM. An element that exists when the page initially loads may be replaced, removed, or recreated later. Selenium therefore needs to synchronize with the application state rather than simply waiting for the page to load.
- Elements may appear dynamically
- DOM elements may be replaced
- Content may load through AJAX
- Buttons may become enabled later
- Loading overlays may block interactions
- Elements may be rendered after JavaScript execution
- Page content may change without a refresh
- Network requests may complete at different times
- Frameworks may re-render elements
- JavaScript events may control application behavior
4. Traditional Website vs JavaScript Application
| Traditional Website | JavaScript-Based Application |
| Frequent full-page refreshes | Partial DOM updates |
| Content often available after page load | Content may load asynchronously |
| Simple page navigation | Client-side routing |
| Static elements are common | Dynamic elements are common |
| Synchronization is relatively simple | Synchronization requires careful waits |
| Server generates much of the HTML | JavaScript may generate or modify HTML |
5. Understanding the DOM
The Document Object Model (DOM) represents the structure of an HTML document as objects that JavaScript can access and modify.
<html>
<body>
<div id="app">
<button id="login">Login</button>
</div>
</body>
</html>
JavaScript can modify this DOM by changing attributes, text, styles, classes, values, or by creating and removing elements.
6. Selenium and the Browser DOM
Selenium WebDriver communicates with the browser and allows automation scripts to locate and interact with DOM elements.
Test Script
|
v
Selenium WebDriver
|
v
Browser Driver
|
v
Browser
|
v
DOM / Web Application
7. Basic Selenium Setup
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
8. Starting WebDriver
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://example.com");
9. Locating Elements in JavaScript Applications
Locators are especially important when automating dynamic applications. Whenever possible, use stable attributes such as IDs, names, accessible attributes, or application-specific test attributes.
WebElement username =
driver.findElement(By.id("username"));
WebElement login =
driver.findElement(By.id("login"));
10. Common Selenium Locators
| Locator | Example | Usage |
| ID | By.id("username") | Stable unique element ID |
| Name | By.name("email") | Name attribute |
| Class Name | By.className("login") | CSS class |
| Tag Name | By.tagName("button") | HTML tag |
| Link Text | By.linkText("Login") | Exact link text |
| CSS Selector | By.cssSelector("#login") | CSS-based selection |
| XPath | By.xpath("//button[@id='login']") | Flexible element selection |
11. Understanding Dynamic Elements
A dynamic element is an element whose presence, attributes, location, text, or state changes during application execution.
Page Load
|
v
Loading...
|
v
JavaScript Request
|
v
Data Received
|
v
Element Created
|
v
Element Available
12. Why Thread.sleep() Is Not the Best Solution
Using fixed delays can make tests slower and less reliable because the required element may become available before or after the specified delay.
Thread.sleep(5000);
A better approach is to wait for a meaningful application condition.
13. Explicit Wait
Explicit waits allow Selenium to wait until a specific condition becomes true.
WebDriverWait wait =
new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement login =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("login")
)
);
14. Wait for Element to Be Present
WebElement element =
wait.until(
ExpectedConditions.presenceOfElementLocated(
By.id("username")
)
);
15. Wait for Element to Be Visible
WebElement element =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("username")
)
);
16. Wait for Element to Be Clickable
WebElement button =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("login")
)
);
button.click();
17. Wait for Text to Appear
wait.until(
ExpectedConditions.textToBePresentInElementLocated(
By.id("message"),
"Login successful"
)
);
18. Handling AJAX Requests
AJAX allows a web application to communicate with the server without refreshing the entire page. Selenium does not directly wait for an AJAX request itself. Instead, the test should wait for a visible application state that indicates that the request has completed.
Click Search
|
v
AJAX Request
|
v
Loading Indicator
|
v
Server Response
|
v
Results Rendered
|
v
Result Element Available
19. Handling AJAX Results
driver.findElement(By.id("search")).click();
WebElement result =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".search-result")
)
);
System.out.println(result.getText());
20. Handling Loading Indicators
JavaScript applications often display a loading spinner while an operation is in progress.
wait.until(
ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".loading-spinner")
)
);
21. Handling Dynamic Buttons
A button may initially be disabled and become enabled after JavaScript validation.
WebElement submit =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("submit")
)
);
submit.click();
22. Handling Dynamically Generated Text
wait.until(
ExpectedConditions.textToBePresentInElementLocated(
By.id("status"),
"Completed"
)
);
23. Understanding JavaScriptExecutor
JavaScriptExecutor is a Selenium interface that allows JavaScript code to be executed inside the browser.
import org.openqa.selenium.JavascriptExecutor;
JavascriptExecutor js =
(JavascriptExecutor) driver;
24. Executing JavaScript
js.executeScript(
"alert('Hello Selenium');"
);
25. Passing a WebElement to JavaScript
WebElement element =
driver.findElement(By.id("username"));
js.executeScript(
"arguments[0].style.outline='3px solid red';",
element
);
26. Understanding arguments[0]
The arguments[0] expression represents the first object passed to the JavaScript execution method.
js.executeScript(
"arguments[0].click();",
button
);
Here, button becomes arguments[0] inside the JavaScript code.
27. JavaScript Click
WebElement button =
driver.findElement(By.id("submit"));
js.executeScript(
"arguments[0].click();",
button
);
JavaScript click should be used carefully because it can bypass some of the normal interaction behavior that a real user click would trigger.
28. Normal Selenium Click vs JavaScript Click
| Normal Selenium | JavaScript |
| button.click() | arguments[0].click() |
| Uses WebDriver interaction | Executes directly in page JavaScript |
| Better for normal user behavior | Useful for specialized DOM-level operations |
| Can expose interactability problems | May bypass some UI restrictions |
29. Handling Hidden Elements
JavaScript applications may create elements before displaying them. Selenium normally requires elements to be interactable for actions such as clicking.
WebElement element =
driver.findElement(By.id("hiddenElement"));
js.executeScript(
"arguments[0].style.display='block';",
element
);
Changing visibility should be used only for controlled testing or debugging. It should not be used to hide genuine application defects.
30. Handling Disabled Elements
WebElement button =
driver.findElement(By.id("submit"));
js.executeScript(
"arguments[0].removeAttribute('disabled');",
button
);
Removing the disabled attribute may bypass application validation. Therefore, it should be used only when the test specifically needs to inspect that DOM state.
31. Modifying Element Values with JavaScript
WebElement username =
driver.findElement(By.id("username"));
js.executeScript(
"arguments[0].value='admin';",
username
);
32. JavaScript Value Changes and Application Events
A direct JavaScript change to an input's value does not necessarily produce the same events as typing through Selenium. JavaScript frameworks may depend on input, change, keyboard, or other events to update application state.
33. Dispatching an Input Event
js.executeScript(
"arguments[0].value='admin';" +
"arguments[0].dispatchEvent(" +
"new Event('input',{bubbles:true})" +
");",
username
);
34. Dispatching a Change Event
js.executeScript(
"arguments[0].value='IN';" +
"arguments[0].dispatchEvent(" +
"new Event('change',{bubbles:true})" +
");",
country
);
35. Why Events Matter in JavaScript Applications
Modern frameworks often listen for browser events to update their internal state. Changing the DOM alone may therefore not be enough.
User Action
|
v
Browser Event
|
v
Framework Event Handler
|
v
Application State
|
v
DOM Re-render
36. Handling React Applications
React applications commonly use component state and virtual DOM rendering. An element can be recreated after a state change, which means a previously stored WebElement reference may become stale.
For React applications, prefer normal Selenium interactions and explicit waits whenever possible. Use stable locators and re-locate elements after significant re-renders.
37. React Dynamic Element Example
WebElement username =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector("input[name='username']")
)
);
username.clear();
username.sendKeys("admin");
38. Handling React Re-Renders
If a React state change replaces an element, Selenium may report a StaleElementReferenceException.
WebElement button =
driver.findElement(By.id("submit"));
button.click();
// Application re-renders the button
button =
driver.findElement(By.id("submit"));
39. Handling Angular Applications
Angular applications can also dynamically render components and update elements based on application state, HTTP responses, form validation, and user events.
Use stable locators, explicit waits, and application-specific conditions rather than relying on arbitrary delays.
40. Handling Vue.js Applications
Vue.js applications dynamically update components and DOM elements based on reactive data. Selenium automation should wait for the required state rather than assuming that an element will remain unchanged after it is located.
41. Single Page Applications
A Single Page Application (SPA) can change views without performing a complete browser page refresh.
Login View
|
v
Dashboard View
|
v
Products View
|
v
Checkout View
The browser may remain on the same URL while the displayed DOM changes significantly.
42. Handling SPA Navigation
Because the page may not reload, a Selenium script should wait for an element or state that identifies the new view.
driver.findElement(By.id("dashboardLink")).click();
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard")
)
);
43. Handling Dynamic URLs
SPA applications may change URL fragments or paths without a traditional page reload.
wait.until(
ExpectedConditions.urlContains("/dashboard")
);
44. Handling DOM Changes
JavaScript can add, remove, replace, or modify DOM elements during execution. Tests should therefore avoid assuming that a WebElement reference remains valid indefinitely.
45. StaleElementReferenceException
StaleElementReferenceException occurs when Selenium has a reference to an element that is no longer attached to the current DOM.
WebElement element =
driver.findElement(By.id("username"));
driver.navigate().refresh();
element =
driver.findElement(By.id("username"));
46. Handling Stale Elements with Re-Locating
WebElement element =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("username")
)
);
element.click();
Re-locating the element after a known DOM refresh or re-render is often simpler than retaining an outdated reference.
47. Handling Stale Elements with a Retry Strategy
for (int i = 0; i < 3; i++) {
try {
WebElement button =
driver.findElement(By.id("submit"));
button.click();
break;
} catch (org.openqa.selenium.StaleElementReferenceException e) {
System.out.println("Element became stale. Retrying...");
}
}
48. Handling Dynamic Tables
JavaScript applications often update table rows dynamically after filtering, searching, pagination, or API responses.
WebElement row =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector("table tbody tr")
)
);
System.out.println(row.getText());
49. Handling Dynamic Dropdowns
A dropdown may load options only after the user clicks it or enters text.
WebElement search =
driver.findElement(By.id("country"));
search.sendKeys("India");
WebElement option =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.xpath("//li[contains(.,'India')]")
)
);
option.click();
50. Handling Auto-Suggestion Boxes
WebElement search =
driver.findElement(By.id("search"));
search.sendKeys("Mumbai");
WebElement suggestion =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".suggestion")
)
);
suggestion.click();
51. Handling Dynamic Search Results
driver.findElement(By.id("search"))
.sendKeys("Selenium");
driver.findElement(By.id("searchButton"))
.click();
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".search-result")
)
);
52. Handling JavaScript Alerts
JavaScript applications may display browser alerts, confirmations, or prompts.
driver.findElement(By.id("delete")).click();
wait.until(
ExpectedConditions.alertIsPresent()
);
driver.switchTo().alert().accept();
53. Handling JavaScript Confirmation
driver.switchTo().alert().dismiss();
54. Handling JavaScript Prompt
driver.switchTo().alert().sendKeys("Test Data");
driver.switchTo().alert().accept();
55. Handling Overlays
JavaScript applications frequently display modal dialogs, cookie banners, loading overlays, or notification layers above the target element.
wait.until(
ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".overlay")
)
);
driver.findElement(By.id("submit")).click();
56. Handling Modal Dialogs
WebElement modal =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".modal")
)
);
WebElement input =
modal.findElement(By.cssSelector("input"));
input.sendKeys("Test Data");
57. Handling Cookie Banners
WebElement accept =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("acceptCookies")
)
);
accept.click();
58. Handling Shadow DOM
Some modern web applications use Shadow DOM to encapsulate HTML, CSS, and JavaScript behavior. Standard locators may not always be able to access elements inside a shadow root directly.
59. JavaScript Access to Shadow Root
WebElement host =
driver.findElement(By.cssSelector("my-component"));
WebElement shadowElement =
(WebElement) js.executeScript(
"return arguments[0].shadowRoot.querySelector('button');",
host
);
shadowElement.click();
60. Shadow DOM Considerations
- Identify the shadow host
- Access the shadow root
- Locate the required element inside the shadow root
- Use Selenium's supported Shadow DOM APIs where applicable
- Avoid unnecessary JavaScript when normal WebDriver methods are sufficient
61. Handling Iframes in JavaScript Applications
Some JavaScript applications load payment forms, authentication widgets, advertisements, or external components inside iframes.
WebElement frame =
wait.until(
ExpectedConditions.presenceOfElementLocated(
By.id("paymentFrame")
)
);
driver.switchTo().frame(frame);
WebElement card =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("cardNumber")
)
);
card.sendKeys("4111111111111111");
driver.switchTo().defaultContent();
62. Handling Multiple Windows and Tabs
JavaScript applications can open new tabs or windows through user actions.
String originalWindow =
driver.getWindowHandle();
driver.findElement(By.id("openWindow")).click();
wait.until(
d -> d.getWindowHandles().size() > 1
);
for (String windowHandle : driver.getWindowHandles()) {
if (!windowHandle.equals(originalWindow)) {
driver.switchTo().window(windowHandle);
break;
}
}
63. Handling JavaScript Scroll
WebElement element =
driver.findElement(By.id("footer"));
js.executeScript(
"arguments[0].scrollIntoView({block:'center'});",
element
);
64. Scrolling the Page
js.executeScript(
"window.scrollTo(0, document.body.scrollHeight);"
);
65. Scroll by a Specific Amount
js.executeScript(
"window.scrollBy(0,500);"
);
66. Handling Lazy-Loaded Elements
Lazy loading means content is loaded only when it becomes necessary, often when the user scrolls toward it.
WebElement product =
driver.findElement(
By.cssSelector(".lazy-product")
);
js.executeScript(
"arguments[0].scrollIntoView({block:'center'});",
product
);
wait.until(
ExpectedConditions.visibilityOf(product)
);
67. Handling Infinite Scrolling
long previousHeight = 0;
while (true) {
long currentHeight =
((Number) js.executeScript(
"return document.body.scrollHeight;"
)).longValue();
if (currentHeight == previousHeight) {
break;
}
previousHeight = currentHeight;
js.executeScript(
"window.scrollTo(0, document.body.scrollHeight);"
);
Thread.sleep(1000);
}
For production automation, condition-based synchronization is generally preferable to relying on a fixed sleep.
68. Handling Dynamic Forms
JavaScript applications frequently enable, disable, add, or remove fields depending on previous selections.
driver.findElement(By.id("accountType"))
.click();
WebElement companyName =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("companyName")
)
);
companyName.sendKeys("ABC Technologies");
69. Handling Dependent Dropdowns
driver.findElement(By.id("country"))
.sendKeys("India");
WebElement state =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("state")
)
);
state.sendKeys("Maharashtra");
70. Handling Dynamic Checkboxes
WebElement checkbox =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("terms")
)
);
if (!checkbox.isSelected()) {
checkbox.click();
}
71. Handling Dynamic Radio Buttons
WebElement radio =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("male")
)
);
if (!radio.isSelected()) {
radio.click();
}
72. Handling Dynamic Attributes
JavaScript frameworks can dynamically generate attributes such as IDs, classes, ARIA attributes, and data attributes.
Prefer stable application-specific attributes whenever possible.
WebElement element =
driver.findElement(
By.cssSelector("[data-testid='login-button']")
);
73. Using data-testid for Automation
A dedicated test attribute can make automation locators more stable.
WebElement login =
driver.findElement(
By.cssSelector("[data-testid='login']")
);
74. Handling Dynamic Class Names
Some frameworks generate changing CSS class names. Avoid depending on an unstable generated class when a more stable attribute is available.
By locator =
By.xpath("//button[contains(.,'Login')]");
75. Handling Dynamic IDs
If an ID changes between sessions, use another stable locator.
By locator =
By.cssSelector("input[name='username']");
76. Handling Web Components
Modern JavaScript applications may use custom web components. These components can contain their own internal DOM or Shadow DOM.
77. Handling Client-Side Validation
JavaScript applications frequently validate forms before sending data to the server.
WebElement email =
driver.findElement(By.id("email"));
email.clear();
email.sendKeys("invalid-email");
driver.findElement(By.id("submit"))
.click();
WebElement error =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".email-error")
)
);
System.out.println(error.getText());
78. Handling Real-Time Validation
Some applications validate fields immediately after input events.
email.sendKeys("[email protected]");
wait.until(
ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".email-error")
)
);
79. Handling Network-Dependent UI
When a UI depends on an API response, wait for a user-visible condition such as a result, status message, table row, or spinner disappearance.
driver.findElement(By.id("loadData")).click();
wait.until(
ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".loading")
)
);
WebElement result =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("result")
)
);
80. Handling API-Driven Tables
driver.findElement(By.id("loadUsers")).click();
wait.until(
ExpectedConditions.numberOfElementsToBeMoreThan(
By.cssSelector("table tbody tr"),
0
)
);
81. Handling Dynamic Notifications
driver.findElement(By.id("save")).click();
WebElement notification =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".notification")
)
);
System.out.println(notification.getText());
82. Handling Toast Messages
wait.until(
ExpectedConditions.textToBePresentInElementLocated(
By.cssSelector(".toast"),
"Saved successfully"
)
);
83. Handling Dynamic Menus
WebElement menu =
driver.findElement(By.id("menu"));
menu.click();
WebElement item =
wait.until(
ExpectedConditions.elementToBeClickable(
By.xpath("//a[contains(.,'Dashboard')]")
)
);
item.click();
84. Handling Hover Menus
import org.openqa.selenium.interactions.Actions;
Actions actions =
new Actions(driver);
WebElement menu =
driver.findElement(By.id("products"));
actions.moveToElement(menu).perform();
WebElement item =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("electronics")
)
);
item.click();
85. Handling JavaScript-Based Login
WebElement username =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("username")
)
);
WebElement password =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("password")
)
);
username.clear();
username.sendKeys("admin");
password.clear();
password.sendKeys("Password123");
WebElement login =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("login")
)
);
login.click();
86. Verifying Login After JavaScript Processing
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard")
)
);
System.out.println("Dashboard loaded successfully.");
87. Handling JavaScript-Based Logout
WebElement logout =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("logout")
)
);
logout.click();
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("login")
)
);
88. Handling Dynamic E-Commerce Applications
E-commerce websites commonly use JavaScript for product filtering, cart updates, price calculations, stock information, coupons, checkout steps, and payment workflows.
Search Product
|
v
API Request
|
v
Product Results
|
v
Select Product
|
v
Add to Cart
|
v
Cart Updated
|
v
Checkout
89. Handling Dynamic Product Cards
WebElement product =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".product-card")
)
);
WebElement addToCart =
product.findElement(
By.cssSelector(".add-to-cart")
);
addToCart.click();
90. Verifying Dynamic Cart Updates
wait.until(
ExpectedConditions.textToBePresentInElementLocated(
By.id("cartCount"),
"1"
)
);
91. Handling Dynamic Price Updates
driver.findElement(By.id("quantity"))
.clear();
driver.findElement(By.id("quantity"))
.sendKeys("2");
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("totalPrice")
)
);
System.out.println(
driver.findElement(By.id("totalPrice")).getText()
);
92. Handling Search Suggestions
WebElement search =
driver.findElement(By.id("search"));
search.sendKeys("Laptop");
WebElement suggestion =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.xpath("//li[contains(.,'Laptop')]")
)
);
suggestion.click();
93. Handling JavaScript-Based Pagination
WebElement next =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("nextPage")
)
);
next.click();
wait.until(
ExpectedConditions.stalenessOf(
driver.findElement(
By.cssSelector("table tbody tr")
)
)
);
94. Handling Dynamic Search Filters
driver.findElement(By.id("category"))
.click();
driver.findElement(
By.xpath("//option[contains(.,'Electronics')]")
).click();
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".product-card")
)
);
95. Handling Dynamic Modals
driver.findElement(By.id("openModal")).click();
WebElement modal =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".modal")
)
);
modal.findElement(
By.id("username")
).sendKeys("admin");
96. Handling Animations
JavaScript applications may animate elements before making them available for interaction. If an animation blocks an interaction, wait for the appropriate state rather than assuming that visibility alone means the element is ready.
97. Handling Animated Elements
WebElement button =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("submit")
)
);
button.click();
98. Handling Elements Covered by Another Element
ElementClickInterceptedException may occur when an overlay, animation, sticky header, or another element is positioned above the target.
wait.until(
ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".overlay")
)
);
driver.findElement(By.id("submit")).click();
99. Handling ElementNotInteractableException
This exception can occur when an element exists in the DOM but cannot currently be interacted with.
- Check visibility
- Check whether the element is enabled
- Check for overlays
- Check whether the element is inside an iframe
- Check whether the application is still rendering
- Use explicit waits
100. Handling NoSuchElementException
NoSuchElementException usually means that Selenium could not locate the element at the time the locator was executed.
WebElement element =
wait.until(
ExpectedConditions.presenceOfElementLocated(
By.id("username")
)
);
101. Handling TimeoutException
TimeoutException means that the expected condition was not satisfied within the configured wait period.
- Verify the locator
- Check whether the page is loaded correctly
- Check whether an iframe is involved
- Check whether the element appears only after an API response
- Check for application errors
- Use a suitable condition
102. Handling StaleElementReferenceException
For JavaScript-heavy applications, stale elements are common because frameworks can replace DOM nodes.
try {
WebElement element =
driver.findElement(By.id("submit"));
element.click();
} catch (org.openqa.selenium.StaleElementReferenceException e) {
WebElement element =
driver.findElement(By.id("submit"));
element.click();
}
103. Handling JavascriptException
JavascriptException can occur when JavaScript execution fails.
- Check JavaScript syntax
- Check whether the element exists
- Check whether the element is in the correct document context
- Check iframe or Shadow DOM boundaries
- Verify that the JavaScript operation is supported
104. Debugging JavaScript Applications
When a Selenium test fails against a JavaScript application, inspect the application in the browser first.
- Open browser developer tools
- Inspect the target element
- Check whether the element exists
- Observe DOM changes
- Check Console errors
- Check Network requests
- Check loading indicators
- Check iframe boundaries
- Verify the locator
- Add an appropriate explicit wait
105. Using Browser Developer Tools
Browser developer tools are extremely useful when understanding JavaScript-based applications. The Elements panel shows the DOM, the Console shows JavaScript errors and messages, and the Network panel shows requests and responses.
106. Inspecting Dynamic Elements
Right Click
|
v
Inspect
|
v
Elements Panel
|
+---- Check ID
+---- Check Class
+---- Check Data Attributes
+---- Check DOM Position
+---- Check Shadow DOM
|
v
Create Stable Locator
107. Handling Console Errors
If a JavaScript application itself has a runtime error, Selenium may report symptoms such as missing elements, incomplete rendering, or unexpected states. Browser console inspection can help distinguish an automation synchronization problem from an application problem.
108. Handling Network Delays
Network delays can cause elements to appear later than expected. Tests should synchronize with application-visible conditions rather than using unnecessarily large fixed delays.
109. JavaScriptExecutor for Page Scrolling
WebElement element =
driver.findElement(By.id("target"));
js.executeScript(
"arguments[0].scrollIntoView({block:'center'});",
element
);
110. JavaScriptExecutor for Highlighting
js.executeScript(
"arguments[0].style.outline='3px solid red';",
element
);
111. JavaScriptExecutor for Reading DOM Information
String text =
(String) js.executeScript(
"return arguments[0].textContent;",
element
);
System.out.println(text);
112. JavaScriptExecutor for Reading the Current URL
String url =
(String) js.executeScript(
"return window.location.href;"
);
System.out.println(url);
113. JavaScriptExecutor for Page Title
String title =
(String) js.executeScript(
"return document.title;"
);
System.out.println(title);
114. JavaScriptExecutor for Document Ready State
String state =
(String) js.executeScript(
"return document.readyState;"
);
System.out.println(state);
115. Understanding document.readyState
The document ready state can indicate whether the initial document has been loaded, but it does not necessarily mean that a JavaScript application has finished rendering all dynamic content.
| State | Meaning |
| loading | Document is still loading |
| interactive | Initial document has been parsed |
| complete | Document and dependent resources have finished loading |
116. Waiting for document.readyState
wait.until(
d -> ((JavascriptExecutor) d)
.executeScript(
"return document.readyState"
)
.equals("complete")
);
For JavaScript applications, this should generally be combined with waits for application-specific elements or states.
117. Handling Application-Specific Loading States
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard")
)
);
118. Handling URL-Based SPA State
wait.until(
ExpectedConditions.urlContains("/dashboard")
);
119. Handling JavaScript-Based File Uploads
File upload controls may be wrapped inside custom JavaScript components. Selenium should normally interact with the underlying file input using sendKeys() when possible.
WebElement upload =
driver.findElement(By.cssSelector(
"input[type='file']"
));
upload.sendKeys(
"C:\\\\Users\\\\Test\\\\Documents\\\\sample.pdf"
);
120. Handling Custom File Upload Components
If the visible upload button is only a JavaScript wrapper around a hidden file input, locate the actual input element where possible rather than trying to automate the operating-system file chooser.
121. Handling JavaScript-Based Date Pickers
Modern date pickers frequently generate calendar elements dynamically.
driver.findElement(By.id("date"))
.click();
WebElement date =
wait.until(
ExpectedConditions.elementToBeClickable(
By.xpath("//button[contains(.,'25')]")
)
);
date.click();
122. Handling Calendar Navigation
driver.findElement(By.id("nextMonth"))
.click();
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".calendar")
)
);
123. Handling Dynamic Tooltips
WebElement icon =
driver.findElement(By.id("help"));
new Actions(driver)
.moveToElement(icon)
.perform();
WebElement tooltip =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".tooltip")
)
);
System.out.println(tooltip.getText());
124. Handling Dynamic Tabs
driver.findElement(By.id("profileTab"))
.click();
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("profileContent")
)
);
125. Handling Dynamic Accordions
driver.findElement(By.id("faq1"))
.click();
WebElement answer =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("answer1")
)
);
System.out.println(answer.getText());
126. Handling JavaScript-Based Drag and Drop
WebElement source =
driver.findElement(By.id("source"));
WebElement target =
driver.findElement(By.id("target"));
Actions actions =
new Actions(driver);
actions.dragAndDrop(source, target)
.perform();
127. Handling Dynamic Mouse Interactions
Actions actions =
new Actions(driver);
actions.moveToElement(
driver.findElement(By.id("menu"))
).click().perform();
128. Handling JavaScript-Based Rich Text Editors
Rich text editors may use contenteditable elements rather than standard input elements.
WebElement editor =
driver.findElement(
By.cssSelector("[contenteditable='true']")
);
editor.click();
editor.sendKeys("Hello Selenium");
129. Using JavaScript with contenteditable
js.executeScript(
"arguments[0].innerHTML='Hello Selenium';",
editor
);
When using JavaScript to modify contenteditable elements, consider whether the application's event handlers also need to be triggered.
130. Handling Dynamic Chat Applications
Chat applications frequently append new messages dynamically without refreshing the page.
driver.findElement(By.id("message"))
.sendKeys("Hello");
driver.findElement(By.id("send"))
.click();
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".message")
)
);
131. Handling Real-Time Notifications
WebSocket or other real-time communication can update the UI without a page refresh. Selenium should wait for the resulting visible UI state.
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".notification")
)
);
132. Handling WebSocket-Driven Applications
Selenium does not directly control the WebSocket protocol. Instead, it interacts with the UI state produced by the application's real-time communication.
133. Handling Dynamic Dashboards
Dashboards often contain charts, cards, tables, and statistics that are loaded asynchronously.
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard")
)
);
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".dashboard-card")
)
);
134. Handling Dynamic Charts
Charts may be rendered using SVG, Canvas, or JavaScript chart libraries. Selenium can validate the surrounding DOM, labels, legends, and displayed values. Canvas graphics may require additional application-specific strategies because the visual content may not exist as ordinary DOM text.
135. Handling SVG Elements
WebElement svgElement =
driver.findElement(
By.cssSelector("svg")
);
System.out.println(
svgElement.getAttribute("outerHTML")
);
136. Handling Canvas Elements
Canvas content is drawn programmatically and may not expose individual graphical objects as normal HTML elements. Validation may therefore require accessible labels, underlying data, application APIs, or screenshot-based techniques depending on the test objective.
137. JavaScript-Based Application Testing Strategy
Start
|
v
Open Application
|
v
Identify Dynamic Behavior
|
v
Locate Stable Element
|
v
Wait for Required State
|
v
Perform Selenium Action
|
v
Wait for Application Update
|
v
Verify Result
|
v
Handle DOM Changes
|
v
Continue Test
|
v
End
138. Recommended Synchronization Strategy
| Situation | Recommended Approach |
| Element appears later | Explicit wait |
| Button becomes enabled | elementToBeClickable or enabled-state condition |
| Loading spinner disappears | invisibilityOfElementLocated |
| Text changes | textToBePresentInElementLocated |
| URL changes | urlContains or urlToBe |
| DOM element is replaced | Re-locate element |
| Iframe content | switchTo().frame() |
| Special DOM operation | JavaScriptExecutor when appropriate |
139. Common Mistake: Using Thread.sleep() Everywhere
Large fixed sleeps make tests slow and may still fail when application behavior takes longer than expected.
Prefer condition-based explicit waits.
140. Common Mistake: Using JavaScript for Everything
JavaScriptExecutor is powerful, but it should not automatically replace normal Selenium commands.
// Prefer this for normal interaction
element.click();
// Use JavaScript when a DOM-level operation is specifically required
js.executeScript(
"arguments[0].click();",
element
);
141. Common Mistake: Keeping Old WebElements
JavaScript frameworks can replace DOM nodes during re-rendering. Re-locate elements after known DOM changes.
142. Common Mistake: Ignoring Application Events
Directly changing an input value through JavaScript may not update the application's internal state.
When required, trigger the relevant input or change event and verify the resulting application behavior.
143. Common Mistake: Using Unstable Locators
A locator based on generated CSS classes or changing IDs can make tests fragile.
Prefer stable identifiers such as data-testid, name, accessible attributes, or other application-supported test hooks.
144. Common Mistake: Ignoring Iframes
If the target element belongs to an iframe, Selenium must switch into the correct frame before interacting with it.
145. Common Mistake: Ignoring Overlays
A loading overlay or modal can prevent interaction even when the target element is visible.
146. Common Mistake: Verifying Only Element Presence
Presence does not always mean that the application is ready. A stronger test verifies the expected state, text, enabled state, or resulting UI change.
147. Best Practices for JavaScript-Based Applications
- Prefer normal Selenium WebDriver methods for normal user interactions.
- Use explicit waits for dynamic conditions.
- Use stable locators.
- Re-locate elements after major DOM changes.
- Wait for loading indicators to disappear.
- Verify application state after important actions.
- Use JavaScriptExecutor for specialized DOM operations.
- Understand application-specific events.
- Handle iframes and Shadow DOM correctly.
- Avoid unnecessary fixed delays.
- Keep JavaScript snippets small and readable.
- Use reusable wait and utility methods.
- Do not bypass application validation unless the test specifically requires it.
148. Creating a Reusable JavaScript Utility
public class JavaScriptUtils {
public static void click(
WebDriver driver,
WebElement element) {
JavascriptExecutor js =
(JavascriptExecutor) driver;
js.executeScript(
"arguments[0].click();",
element
);
}
public static void scrollIntoView(
WebDriver driver,
WebElement element) {
JavascriptExecutor js =
(JavascriptExecutor) driver;
js.executeScript(
"arguments[0].scrollIntoView({block:'center'});",
element
);
}
public static void highlight(
WebDriver driver,
WebElement element) {
JavascriptExecutor js =
(JavascriptExecutor) driver;
js.executeScript(
"arguments[0].style.outline='3px solid red';",
element
);
}
}
149. Using the JavaScript Utility
WebElement login =
driver.findElement(By.id("login"));
JavaScriptUtils.scrollIntoView(
driver,
login
);
JavaScriptUtils.highlight(
driver,
login
);
login.click();
150. Combining Explicit Wait and JavaScript
WebDriverWait wait =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
WebElement button =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("submit")
)
);
JavaScriptUtils.scrollIntoView(
driver,
button
);
JavaScriptUtils.highlight(
driver,
button
);
151. Page Object Model for JavaScript Applications
Page Object Model helps organize locators and interactions into reusable classes. This becomes particularly useful when working with complex JavaScript applications containing many dynamic components.
public class LoginPage {
private WebDriver driver;
private By username =
By.id("username");
private By password =
By.id("password");
private By login =
By.id("login");
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public void login(
String user,
String pass) {
driver.findElement(username)
.clear();
driver.findElement(username)
.sendKeys(user);
driver.findElement(password)
.clear();
driver.findElement(password)
.sendKeys(pass);
driver.findElement(login)
.click();
}
}
152. Page Object with Explicit Wait
public class LoginPage {
private WebDriver driver;
private WebDriverWait wait;
private By username =
By.id("username");
private By password =
By.id("password");
private By login =
By.id("login");
public LoginPage(WebDriver driver) {
this.driver = driver;
this.wait =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
}
public void login(
String user,
String pass) {
WebElement userElement =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
username
)
);
userElement.clear();
userElement.sendKeys(user);
WebElement passwordElement =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
password
)
);
passwordElement.clear();
passwordElement.sendKeys(pass);
WebElement loginButton =
wait.until(
ExpectedConditions.elementToBeClickable(
login
)
);
loginButton.click();
}
}
153. TestNG with JavaScript-Based Applications
import org.testng.Assert;
import org.testng.annotations.Test;
public class LoginTest {
@Test
public void loginTest() {
WebDriver driver =
new ChromeDriver();
driver.get(
"https://example.com/login"
);
LoginPage loginPage =
new LoginPage(driver);
loginPage.login(
"admin",
"Password123"
);
WebElement dashboard =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
).until(
ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard")
)
);
Assert.assertTrue(
dashboard.isDisplayed()
);
driver.quit();
}
}
154. Practical Example: Dynamic Login Application
WebDriver driver =
new ChromeDriver();
driver.manage()
.window()
.maximize();
driver.get(
"https://example.com/login"
);
WebDriverWait wait =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
WebElement username =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("username")
)
);
WebElement password =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("password")
)
);
username.clear();
username.sendKeys("admin");
password.clear();
password.sendKeys("Password123");
WebElement login =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("login")
)
);
login.click();
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard")
)
);
System.out.println(
"Login successful"
);
driver.quit();
155. Practical Example: AJAX Search
WebDriver driver =
new ChromeDriver();
WebDriverWait wait =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
driver.get(
"https://example.com"
);
WebElement search =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("search")
)
);
search.sendKeys("Selenium");
driver.findElement(
By.id("searchButton")
).click();
WebElement result =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".search-result")
)
);
System.out.println(
"Result: " + result.getText()
);
driver.quit();
156. Practical Example: Dynamic Product Cart
WebDriverWait wait =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
WebElement product =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".product-card")
)
);
WebElement addToCart =
product.findElement(
By.cssSelector(".add-to-cart")
);
addToCart.click();
wait.until(
ExpectedConditions.textToBePresentInElementLocated(
By.id("cartCount"),
"1"
)
);
System.out.println(
"Product added to cart."
);
157. Practical Example: Dynamic Dashboard
driver.get(
"https://example.com/dashboard"
);
WebDriverWait wait =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard")
)
);
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".dashboard-card")
)
);
System.out.println(
"Dashboard loaded."
);
158. Practical Example: JavaScript Highlighting
JavascriptExecutor js =
(JavascriptExecutor) driver;
WebElement element =
driver.findElement(
By.id("username")
);
js.executeScript(
"arguments[0].style.outline='3px solid red';",
element
);
159. Practical Example: JavaScript Scrolling and Clicking
WebElement button =
driver.findElement(
By.id("submit")
);
js.executeScript(
"arguments[0].scrollIntoView({block:'center'});",
button
);
wait.until(
ExpectedConditions.elementToBeClickable(
button
)
);
button.click();
160. Practical Example: Handling a Dynamic Modal
driver.findElement(
By.id("openModal")
).click();
WebElement modal =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".modal")
)
);
WebElement input =
modal.findElement(
By.cssSelector("input")
);
input.sendKeys("Test Data");
WebElement close =
modal.findElement(
By.cssSelector(".close")
);
close.click();
wait.until(
ExpectedConditions.invisibilityOf(modal)
);
161. Practical Example: Handling a Dynamic Table
driver.findElement(
By.id("loadUsers")
).click();
wait.until(
ExpectedConditions.numberOfElementsToBeMoreThan(
By.cssSelector("table tbody tr"),
0
)
);
List<WebElement> rows =
driver.findElements(
By.cssSelector("table tbody tr")
);
for (WebElement row : rows) {
System.out.println(
row.getText()
);
}
162. Practical Example: Handling Dynamic Form Validation
WebElement email =
driver.findElement(By.id("email"));
email.clear();
email.sendKeys("invalid");
driver.findElement(By.id("submit"))
.click();
WebElement error =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".error")
)
);
System.out.println(
"Validation: " + error.getText()
);
163. Practical Example: Handling Dynamic Loading
driver.findElement(
By.id("loadData")
).click();
wait.until(
ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".spinner")
)
);
WebElement data =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("data")
)
);
System.out.println(
data.getText()
);
164. Practical Example: Handling a JavaScript Alert
driver.findElement(
By.id("delete")
).click();
wait.until(
ExpectedConditions.alertIsPresent()
);
Alert alert =
driver.switchTo().alert();
System.out.println(
alert.getText()
);
alert.accept();
165. Practical Example: Complete JavaScript Application Test
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class JavaScriptApplicationTest {
public static void main(String[] args) {
WebDriver driver =
new ChromeDriver();
driver.manage()
.window()
.maximize();
driver.get(
"https://example.com"
);
WebDriverWait wait =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
JavascriptExecutor js =
(JavascriptExecutor) driver;
WebElement username =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("username")
)
);
username.clear();
username.sendKeys("admin");
WebElement password =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("password")
)
);
password.clear();
password.sendKeys("Password123");
WebElement login =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("login")
)
);
js.executeScript(
"arguments[0].scrollIntoView({block:'center'});",
login
);
login.click();
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard")
)
);
System.out.println(
"JavaScript application handled successfully."
);
driver.quit();
}
}
166. Handling JavaScript Applications Flow
Start
|
v
Open Browser
|
v
Open JavaScript Application
|
v
Identify Dynamic Components
|
v
Locate Stable Element
|
v
Wait for Required Condition
|
v
Perform Selenium Action
|
v
Application Executes JavaScript
|
v
DOM / UI Changes
|
v
Wait for Updated State
|
v
Verify Result
|
+----> DOM Re-render?
| |
| v
| Re-locate Element
|
+----> AJAX/API Request?
| |
| v
| Wait for Result
|
+----> iframe?
| |
| v
| Switch Frame
|
+----> Shadow DOM?
|
v
Access Shadow Root
|
v
Continue Test
|
v
End
167. JavaScript Application Handling Decision Guide
| Problem | Possible Approach |
| Element appears later | Explicit Wait |
| Element is replaced | Re-locate the element |
| Loading spinner visible | Wait for spinner to disappear |
| AJAX result not available | Wait for result element |
| Element is in iframe | Switch to iframe |
| Element is inside Shadow DOM | Access shadow root |
| Element is below viewport | Scroll into view |
| Normal click fails because of application-specific DOM behavior | Investigate cause before considering JavaScript click |
| Need DOM-level modification | JavaScriptExecutor |
| Dynamic text changes | Wait for expected text |
| SPA route changes | Wait for URL or view-specific element |
168. Common Selenium Exceptions in JavaScript Applications
| Exception | Common Cause |
| NoSuchElementException | Element is not available when searched |
| StaleElementReferenceException | DOM element was replaced or removed |
| ElementNotInteractableException | Element exists but is not interactable |
| ElementClickInterceptedException | Another element blocks the click |
| TimeoutException | Expected condition was not satisfied |
| JavascriptException | JavaScript execution failed |
| NoSuchFrameException | Required iframe cannot be located |
169. Debugging Checklist
- Is the locator correct?
- Does the element exist in the current DOM?
- Is the element dynamically created?
- Has the application completed its API request?
- Is a loading overlay visible?
- Is the element inside an iframe?
- Is the element inside Shadow DOM?
- Has the element been re-rendered?
- Is the element enabled?
- Is another element covering it?
- Does the application require an input or change event?
- Is the locator dependent on a dynamic class or ID?
- Would a condition-based wait solve the synchronization problem?
170. Interview Question: What is a JavaScript-Based Application?
A JavaScript-based application is a web application that uses JavaScript to dynamically control the user interface, process user interactions, communicate with APIs, and update DOM content without necessarily performing a full page refresh.
171. Interview Question: Why Are JavaScript Applications Challenging in Selenium?
They frequently modify the DOM asynchronously. Elements can appear later, disappear, change state, or be replaced during execution. Therefore, synchronization and stable element identification are important.
172. Interview Question: What is AJAX?
AJAX is a technique that allows web applications to exchange data with a server asynchronously and update parts of the page without requiring a complete page reload.
173. Interview Question: How Do You Handle AJAX in Selenium?
Use explicit waits for application-visible conditions such as result elements, loading indicators, text changes, or enabled controls rather than relying on arbitrary fixed delays.
174. Interview Question: What is JavaScriptExecutor?
JavaScriptExecutor is a Selenium interface that allows JavaScript code to be executed in the browser context.
175. Interview Question: When Should JavaScriptExecutor Be Used?
It can be useful for specialized DOM-level operations such as scrolling, inspecting or modifying DOM properties, highlighting elements, or handling certain browser-side behaviors when normal WebDriver APIs are not suitable for the specific task.
176. Interview Question: Should JavaScriptExecutor Replace Selenium Methods?
No. Normal Selenium WebDriver methods should generally be preferred for normal browser interactions. JavaScriptExecutor should be used when there is a specific reason to perform a DOM-level JavaScript operation.
177. Interview Question: Why Does a WebElement Become Stale?
A WebElement becomes stale when the DOM node represented by the Selenium reference is removed or replaced, which is common after JavaScript framework re-rendering.
178. Interview Question: How Do You Handle Stale Elements?
Re-locate the element after the DOM change and use appropriate waits. In some situations, a controlled retry can also be used.
179. Interview Question: Does document.readyState Guarantee That a JavaScript Application Is Ready?
No. document.readyState describes document loading, but a JavaScript application may continue making API calls and rendering dynamic components after the document becomes complete. Application-specific waits are therefore often required.
180. Interview Question: How Do You Handle Dynamic Elements?
Use stable locators and explicit waits for conditions such as presence, visibility, clickability, text changes, URL changes, or application-specific states.
181. Interview Question: How Do You Handle Hidden Elements?
First determine why the element is hidden and whether the test should interact with it. For specialized debugging or DOM-state testing, JavaScript can change visibility, but doing so may bypass intended application behavior.
182. Interview Question: How Do You Handle Iframes?
driver.switchTo().frame(
driver.findElement(By.id("frame"))
);
driver.findElement(
By.id("username")
).sendKeys("admin");
driver.switchTo().defaultContent();
183. Interview Question: How Do You Handle Shadow DOM?
Identify the shadow host and access its shadow root using supported Selenium Shadow DOM APIs or JavaScript when appropriate. Then locate the required element within the shadow root.
184. Interview Question: Why Can JavaScript Value Changes Fail in React or Angular?
Because changing the DOM property directly does not necessarily trigger the events and framework state updates expected by the application. When required, the relevant input or change event must also be triggered and the resulting UI state should be verified.
185. Quick Revision Table
| Concept | Key Point |
| JavaScript Application | Dynamic client-side application |
| DOM | Object representation of the page structure |
| AJAX | Asynchronous server communication |
| SPA | Application updates views without full page reloads |
| Explicit Wait | Wait for a specific condition |
| JavaScriptExecutor | Execute JavaScript in browser |
| Stale Element | Stored element reference is no longer attached to current DOM |
| Iframe | Separate browsing context |
| Shadow DOM | Encapsulated DOM structure |
| Dynamic Locator | Locator must account for changing attributes or structure |
| Loading Indicator | Signals asynchronous processing |
| Application State | Actual state that should be verified after actions |
186. Best Practices Checklist
- Understand how the JavaScript application renders its UI.
- Use stable locators.
- Prefer WebDriver methods for normal interactions.
- Use explicit waits instead of unnecessary fixed delays.
- Wait for application-specific conditions.
- Re-locate elements after framework re-rendering.
- Handle AJAX and asynchronous content carefully.
- Check for overlays and loading indicators.
- Switch into iframes when necessary.
- Handle Shadow DOM correctly.
- Use JavaScriptExecutor only for appropriate specialized tasks.
- Understand that DOM changes may not update framework state.
- Trigger relevant events when a test specifically requires a JavaScript value modification.
- Verify the application result after every important action.
- Keep JavaScript utility methods reusable and small.
- Avoid unstable generated IDs and classes.
- Use application-supported test attributes where available.
- Do not use DOM manipulation to hide genuine application defects.
- Capture screenshots and logs when debugging failures.
- Use Page Object Model for maintainable test architecture.
187. Practical Mini Project: JavaScript E-Commerce Application Automation
A useful practice project is to automate a JavaScript-based e-commerce workflow.
Open Website
|
v
Login
|
v
Wait for Dashboard
|
v
Search Product
|
v
Wait for AJAX Suggestions
|
v
Select Product
|
v
Wait for Product Details
|
v
Add Product to Cart
|
v
Wait for Cart Update
|
v
Open Cart
|
v
Update Quantity
|
v
Wait for Price Update
|
v
Proceed to Checkout
|
v
Fill Dynamic Form
|
v
Verify Order
|
v
End Test
188. Practical Mini Project: Dynamic Login and Dashboard
- Open the JavaScript-based login application.
- Wait for the username field.
- Enter the username.
- Enter the password.
- Click Login.
- Wait for the authentication request to complete.
- Wait for the dashboard element.
- Verify dashboard content.
- Capture a screenshot.
- Logout.
- Verify that the login page is displayed again.
189. Practical Mini Project: AJAX Search Application
- Open the application.
- Locate the search field.
- Enter a search term.
- Click Search.
- Wait for the loading indicator.
- Wait for the loading indicator to disappear.
- Wait for search results.
- Verify the result count or result text.
- Open one result.
- Verify the details page.
190. Complete Practical Example
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class DynamicJavaScriptAppTest {
public static void main(String[] args) {
WebDriver driver =
new ChromeDriver();
driver.manage()
.window()
.maximize();
driver.get(
"https://example.com"
);
WebDriverWait wait =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
JavascriptExecutor js =
(JavascriptExecutor) driver;
WebElement username =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("username")
)
);
username.clear();
username.sendKeys("admin");
WebElement password =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("password")
)
);
password.clear();
password.sendKeys("Password123");
WebElement login =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("login")
)
);
js.executeScript(
"arguments[0].scrollIntoView({block:'center'});",
login
);
login.click();
wait.until(
ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".loading-spinner")
)
);
WebElement dashboard =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard")
)
);
js.executeScript(
"arguments[0].style.outline='3px solid green';",
dashboard
);
System.out.println(
"Dashboard loaded successfully."
);
driver.quit();
}
}
191. Conclusion
Handling JavaScript-based applications is an important part of modern Selenium WebDriver automation. Dynamic applications frequently update their DOM, communicate with APIs asynchronously, render components after page load, and change element states during execution.
Reliable automation therefore depends on stable locators, explicit waits, correct frame and Shadow DOM handling, proper synchronization with application states, and careful handling of dynamically replaced elements. JavaScriptExecutor can be useful for specialized browser-side operations, but normal Selenium WebDriver APIs should generally be preferred for standard user interactions.
The most important principle is to synchronize the test with the application's actual state rather than simply waiting for a fixed amount of time. Once testers understand DOM changes, AJAX behavior, SPA navigation, framework re-rendering, events, overlays, and asynchronous content, Selenium automation becomes more reliable and maintainable.
192. Selenium Training Resources
To learn Selenium WebDriver, Core Java, automation frameworks, dynamic elements, waits, TestNG, Maven, debugging, and practical automation projects, explore the following resources:
Selenium Training Course
Register for Course Demo
193. Final Quick Reference
// Create WebDriver
WebDriver driver =
new ChromeDriver();
// Open Application
driver.get("https://example.com");
// Create Explicit Wait
WebDriverWait wait =
new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
// Create JavaScriptExecutor
JavascriptExecutor js =
(JavascriptExecutor) driver;
// Locate Dynamic Element
WebElement element =
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("username")
)
);
// Normal Selenium Interaction
element.clear();
element.sendKeys("Admin");
// Click Dynamic Button
WebElement button =
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("submit")
)
);
button.click();
// Scroll Element
js.executeScript(
"arguments[0].scrollIntoView({block:'center'});",
element
);
// Highlight Element
js.executeScript(
"arguments[0].style.outline='3px solid red';",
element
);
// Read Text
String text =
element.getText();
// Read Attribute
String value =
element.getAttribute("value");
// Wait for Text
wait.until(
ExpectedConditions.textToBePresentInElementLocated(
By.id("status"),
"Completed"
)
);
// Wait for Loading Indicator to Disappear
wait.until(
ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".loading")
)
);
// Switch to iframe
driver.switchTo().frame(
driver.findElement(By.id("frame"))
);
// Return to Main Document
driver.switchTo().defaultContent();
// JavaScript Value
js.executeScript(
"arguments[0].value='Test Data';",
element
);
// Dispatch Input Event
js.executeScript(
"arguments[0].dispatchEvent(" +
"new Event('input',{bubbles:true})" +
");",
element
);
// Re-locate After DOM Change
element =
driver.findElement(
By.id("username")
);
// Close Browser
driver.quit();