What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use the right Selenium interface for the dialog you actually have. An AngularJS, UI Bootstrap, Bootstrap, or custom modal is rendered in the page DOM, so locate it as an element and wait for its required state. A JavaScript alert, confirm, or prompt is browser UI and must be handled through Selenium’s alert API. After clicking the intended control, wait for the modal to become hidden or for the application’s success state; do not rely on an arbitrary sleep.
This distinction resolves most “element not clickable” and “modal never appears” failures. The rendered HTML, not the AngularJS directive name, is the authoritative source for selectors. The examples below use Selenium’s JavaScript binding; adapt the same conditions to your project’s language binding and installed Selenium version.
1. Identify which kind of dialog you are testing
AngularJS or Bootstrap modal (a DOM element)
A UI Bootstrap $uibModal dialog, a Bootstrap modal, and a custom AngularJS modal are ordinary elements inserted into or revealed in the document. They may have role="dialog", an accessible label, a backdrop, and buttons, but the exact structure depends on the application and framework version. Angular UI Bootstrap 2.3.2 documents $uibModal, while an older AngularJS application or a custom directive can produce different markup. Inspect the live DOM after opening the dialog and build locators from stable attributes, labels, accessible names, or button text.
Native JavaScript alert, confirm, or prompt
A native prompt is not in the page DOM. Selenium’s alert interface is the correct API: wait for the alert, read its text if useful, then accept or dismiss it. A prompt also accepts text before it is accepted. Selenium describes this family as browser prompts, not elements you can find with CSS or XPath. See the Selenium alerts documentation.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
A practical classification check
- If browser developer tools show a dialog element and backdrop in the page, use element locators and explicit waits.
- If the browser displays a native prompt that is not inspectable in the DOM, use
driver.switchTo().alert(). - If a test sees an overlay but cannot click the page behind it, treat the overlay as a modal and wait for its visible or hidden state.
2. Inspect the rendered modal before writing selectors
Open the dialog manually, pause any animation, and inspect the final HTML. Prefer a selector that expresses the control’s purpose rather than a generated Angular scope class or a position such as “the second button.” Useful candidates include:
[role="dialog"]or a dialog container with a stable application-specific ID;aria-labelledbyconnected to a stable heading;- a modal-specific data attribute such as
data-testid="delete-dialog"; - button text or an accessible name such as “Save,” “Cancel,” or “Close”;
- a stable form field label or name.
Do not assume that every UI Bootstrap or Bootstrap release uses the same classes. UI Bootstrap creates the dialog, but your template and framework version determine the actual rendered structure. A selector such as [role="dialog"] is an example, not a universal contract. If several dialogs can exist, scope the button search to the dialog that has the expected heading or test ID.
3. Use explicit waits for the state you need
AngularJS can add or reveal a modal after the initial document load. Selenium explicit waits poll a condition until it succeeds or a timeout expires. Choose the condition that represents the next action: presence when you only need an element in the DOM, visibility when it must be displayed, clickability when it must receive a click, and invisibility or staleness when it has closed. Selenium’s Waiting Strategies documentation explains these conditions and warns: “Do not mix implicit and explicit waits.” A nonzero implicit wait combined with explicit waits can produce unpredictable total timeout behavior.
JavaScript Selenium setup
The following examples assume Selenium 4’s JavaScript bindings and an installed WebDriver for your browser.
Free tools Windows power users keep installed
One-click scans. No signup required.
const { Builder, By, until } = require('selenium-webdriver');
const driver = await new Builder().forBrowser('chrome').build();
try {
await driver.get('https://example.test/orders');
// Keep implicit waiting disabled when using explicit waits.
await driver.manage().setTimeouts({ implicit: 0, pageLoad: 30000, script: 30000 });
} finally {
await driver.quit();
}
Open the modal, wait for visibility, and click a scoped button
const openButton = await driver.wait(
until.elementLocated(By.css('[data-testid="open-delete"]')),
5000,
'Open button was not added to the page'
);
await driver.wait(until.elementIsVisible(openButton), 5000);
await openButton.click();
const modal = await driver.wait(
until.elementLocated(By.css('[role="dialog"][data-testid="delete-dialog"]')),
5000,
'Delete dialog was not created'
);
await driver.wait(until.elementIsVisible(modal), 5000);
const confirmButton = await modal.findElement(
By.css('button[type="submit"]')
);
await driver.wait(until.elementIsEnabled(confirmButton), 5000);
await confirmButton.click();
If your binding does not provide elementIsEnabled, locate the button and let the click produce a diagnostic exception, or wait on a custom condition that checks the element’s disabled property.
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
Wait for the modal to close and assert the result
// Some applications remove the modal; others keep it and toggle visibility.
await driver.wait(until.stalenessOf(modal), 5000).catch(async () => {
await driver.wait(until.elementIsNotVisible(modal), 5000);
});
const success = await driver.wait(
until.elementLocated(By.css('[role="status"][data-testid="delete-success"]')),
5000,
'Expected success message did not appear'
);
await driver.wait(until.elementIsVisible(success), 5000);
Use one closing condition that matches your application. If the node remains in the DOM, staleness will never occur; wait for invisibility instead. Conversely, if the framework destroys and recreates the node, a previously stored element reference can become stale, so locate the replacement after the transition.
4. Handle Bootstrap animation deliberately
Bootstrap 4.6 documents shown.bs.modal after the modal is visible and its CSS transition has completed, and hidden.bs.modal after hiding has completed. If your test harness can observe application events, waiting for those events can make the assertion describe the real lifecycle. Otherwise, wait for the visible or hidden DOM state and, when necessary, for an application result such as a success message.
// Event-based helper executed in the page context.
async function waitForBootstrapEvent(driver, selector, eventName, timeout = 5000) {
await driver.executeAsyncScript((sel, name, ms, done) => {
const element = document.querySelector(sel);
if (!element) return done({ ok: false, error: 'modal not found' });
const timer = setTimeout(() => done({ ok: false, error: 'timeout' }), ms);
element.addEventListener(name, () => {
clearTimeout(timer);
done({ ok: true });
}, { once: true });
}, selector, eventName, timeout);
}
Register the listener before triggering the action; otherwise a fast transition can fire before the listener exists. Check the application’s Bootstrap major version before using these event names. A custom AngularJS directive may not emit Bootstrap events at all.
5. Native alerts, confirms, and prompts
Do not search for a native alert with CSS. Trigger the action, wait for the browser prompt, and use Selenium’s alert object.
Accept an alert or confirm
const { By, until } = require('selenium-webdriver');
await driver.findElement(By.css('[data-testid="delete-now"]')).click();
const alert = await driver.wait(until.alertIsPresent(), 5000);
const message = await alert.getText();
if (!message.includes('permanently')) {
throw new Error(`Unexpected prompt text: ${message}`);
}
await alert.accept();
Dismiss a confirmation
await driver.findElement(By.css('[data-testid="cancel-action"]')).click();
const confirmation = await driver.wait(until.alertIsPresent(), 5000);
await confirmation.dismiss();
Fill and accept a prompt
await driver.findElement(By.css('[data-testid="rename"]')).click();
const prompt = await driver.wait(until.alertIsPresent(), 5000);
await prompt.sendKeys('Quarterly report');
await prompt.accept();
Selenium’s alert documentation states that WebDriver can retrieve popup text and accept or dismiss these alerts. After accepting or dismissing, wait for the page’s resulting state rather than assuming the action completed synchronously.
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
6. A complete AngularJS modal test flow
This example keeps the dialog locator, action, and postcondition explicit. Replace the example attributes with values from your rendered markup.
const { Builder, By, until } = require('selenium-webdriver');
(async () => {
const driver = await new Builder().forBrowser('chrome').build();
try {
await driver.manage().setTimeouts({ implicit: 0, pageLoad: 30000, script: 30000 });
await driver.get('https://example.test/profile');
const edit = await driver.wait(
until.elementLocated(By.css('[data-testid="edit-profile"]')),
10000
);
await driver.wait(until.elementIsVisible(edit), 5000);
await edit.click();
const dialog = await driver.wait(
until.elementLocated(By.css('[role="dialog"][aria-labelledby="profile-title"]')),
10000
);
await driver.wait(until.elementIsVisible(dialog), 5000);
const name = await dialog.findElement(By.name('displayName'));
await name.clear();
await name.sendKeys('Sam Example');
const save = await dialog.findElement(By.css('button[type="submit"]'));
await driver.wait(until.elementIsEnabled(save), 5000);
await save.click();
await driver.wait(until.elementIsNotVisible(dialog), 10000);
const saved = await driver.wait(
until.elementLocated(By.css('[data-testid="profile-saved"]')),
10000
);
await driver.wait(until.elementIsVisible(saved), 5000);
} finally {
await driver.quit();
}
})();
If the save operation is asynchronous, the disappearing dialog only proves that the dialog closed. The success message, updated field, network-backed status, or another application-specific assertion proves that the operation completed.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minute7. Why modal clicks fail and how to fix them
“NoSuchElementError”
- Cause: the modal has not been created yet, or the selector targets pre-render rather than live markup.
- Fix: wait for
elementLocated, inspect the post-open DOM, and scope the search to the correct dialog.
“Element is not visible”
- Cause: the node exists but is hidden during an AngularJS or Bootstrap transition.
- Fix: wait for
elementIsVisibleand, if applicable, the Bootstrapshown.bs.modalevent.
“Element click intercepted”
- Cause: a backdrop, animation layer, cookie banner, or another overlay covers the button.
- Fix: wait until the intended dialog is visible, target the button inside that dialog, and handle the overlay that belongs to the test scenario. Do not replace a real user action with JavaScript clicking merely to bypass an overlay.
“StaleElementReferenceError”
- Cause: AngularJS destroyed and recreated the modal node.
- Fix: wait for the old node to become stale, then locate the new node; avoid retaining element references across a rerender.
Timeout while waiting for disappearance
- Cause: the application hides the modal with a class instead of removing it, or the close action failed validation.
- Fix: inspect the class and computed visibility, wait for invisibility rather than staleness, and assert validation errors before expecting closure.
Click returns but Angular state does not update
AngularJS documents that browser-called JavaScript can run outside Angular’s execution context; model changes made there may not receive the usual binding and watch processing. This is mainly an application-diagnosis issue, not a universal Selenium wait recipe. Prefer clicking the real control and asserting the resulting DOM or application state. If custom test code invokes application functions directly, verify that the application enters the appropriate Angular context.
8. Backdrop, Escape, and close-button behavior
A Bootstrap modal may close through its close button, the Escape key, or a backdrop click, depending on configuration. Test the behavior your product promises:
- For a close-button test, locate and click the button inside the dialog, then wait for hidden state.
- For Escape behavior, send the key to the dialog or active control and assert the same hidden state.
- For backdrop dismissal, click the backdrop only when backdrop dismissal is the requirement. Some dialogs intentionally disable it to prevent accidental data loss.
Do not treat a backdrop click as a generic workaround for a blocked button; that can make a test pass while skipping the behavior it was meant to verify.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
9. Timing, reliability, and maintainability
- Use a bounded timeout based on the operation. A local animation and a remote API save need different limits; keep the timeout long enough for the environment but short enough to fail diagnostically.
- Wait on observable conditions. Presence, visibility, enabled state, disappearance, and a success indicator are more reliable than fixed sleeps.
- Keep one waiting strategy. Selenium explicitly cautions against mixing implicit and explicit waits; set the implicit timeout to zero when your suite uses explicit conditions.
- Capture diagnostics on failure. Save a screenshot, page source, current URL, and visible dialog text in the test reporter.
- Make selectors testable contracts. A dedicated
data-testidor accessible name usually survives CSS refactoring better than generated Angular classes. - Reset state between tests. A leftover modal, cookie consent choice, or unsaved form can change which dialog appears next.
Or skip the browser setup
When your goal is a clean page image rather than interactive modal assertions, ScreenshotNeo makes one request to capture a URL. It accepts cookie and consent banners before the capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
For the full parameter list and setup, see the ScreenshotNeo API documentation.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo includes full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets plus custom viewports, retina scale, PDF controls, custom CSS and JavaScript, pre-capture clicks, hidden selectors, waits for selectors, delays or network idle, request and resource blocking, custom headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, an OpenAPI specification, and compatibility with parameter names used by other screenshot APIs.
The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create your free ScreenshotNeo account to get started.
10. FAQ
Should I use XPath for an AngularJS modal?
Only when the rendered structure gives you a stable relationship that CSS cannot express. A stable role, test ID, label, or accessible button name is usually easier to maintain than an XPath tied to nesting depth.
Recommended Free Tools
Can I wait for AngularJS itself instead of the modal?
Wait for the user-visible condition your test requires. AngularJS does not provide one universal Selenium wait hook across UI Bootstrap, Bootstrap, and custom directives; a visible dialog or completed result is the portable contract.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
Why does my modal remain in the DOM after closing?
Many implementations hide and reuse the node. Assert invisibility or a hidden class rather than staleness, and locate it again when the next test opens it.
Is a Bootstrap modal the same as a browser alert?
No. A Bootstrap modal is page DOM; a browser alert is native browser UI. Mixing the two APIs produces the wrong kind of wait or locator.
Frequently Asked Questions
How do I know whether to call `alertIsPresent()`?
Use it only when the browser shows a native JavaScript alert, confirm, or prompt that is not present in the page DOM. AngularJS and Bootstrap modals use ordinary element locators.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →What should I assert after clicking the modal’s Save button?
Assert the application outcome: for example, a success message, updated value, or completed navigation. Modal disappearance alone proves only that the dialog closed.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

