<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Volta Jebaprashanth</title>
    <description>The latest articles on DEV Community by Volta Jebaprashanth (@voltajeba).</description>
    <link>https://dev.to/voltajeba</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3495681%2Faad493dc-eace-4543-9c45-a350bd5f2301.jpg</url>
      <title>DEV Community: Volta Jebaprashanth</title>
      <link>https://dev.to/voltajeba</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/voltajeba"/>
    <language>en</language>
    <item>
      <title>The Wait Condition You Actually Need Almost Never Matches the One You Wrote</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sun, 09 Aug 2026 10:35:13 +0000</pubDate>
      <link>https://dev.to/voltajeba/the-wait-condition-you-actually-need-almost-never-matches-the-one-you-wrote-49</link>
      <guid>https://dev.to/voltajeba/the-wait-condition-you-actually-need-almost-never-matches-the-one-you-wrote-49</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server built for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;. It gives an AI coding agent a real Selenium WebDriver session to drive Chrome, Firefox, or Edge directly — structured element discovery for reliable locators, Chrome DevTools Protocol network/console tooling, and a standalone REST client, all in one server. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask any Selenium engineer to name the single biggest source of flaky tests in their suite, and "waits" wins almost every time — not because waiting is conceptually hard, but because picking the &lt;em&gt;right&lt;/em&gt; wait condition requires knowing exactly what the page is doing at that moment, and most of the time you're guessing.&lt;/p&gt;

&lt;p&gt;You wait for an element to be visible, but the click handler attached to it hasn't finished initializing. You wait for a URL to change, but the page it changed to is still fetching the data it needs to render. You wait for text to appear, but it appears immediately in a loading state and then changes again half a second later. Every one of these produces a test that passes locally nine times out of ten and fails in CI often enough to erode trust in the whole suite.&lt;/p&gt;

&lt;p&gt;This piece is about how &lt;strong&gt;selenium-mcp&lt;/strong&gt;'s wait tooling — and the CDP-backed network tools sitting next to it — help an AI coding assistant actually diagnose which condition you need, instead of you iterating through &lt;code&gt;Thread.sleep()&lt;/code&gt; values by hand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhiyozkv86zcnb9jedv74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhiyozkv86zcnb9jedv74.png" alt="Image desc" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The full set of wait conditions available
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;WaitTools&lt;/code&gt; covers the standard explicit-wait surface, all with a configurable timeout (default 10s):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waitForVisible&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;waitForClickable&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;waitForPresent&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;waitForInvisible&lt;/code&gt;&lt;/strong&gt; — the core element-state waits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waitForTextPresent&lt;/code&gt;&lt;/strong&gt; — waits until an element contains specific text, useful for loading-state-to-final-state transitions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waitForTitleContains&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;waitForUrlContains&lt;/code&gt;&lt;/strong&gt; — page-level navigation waits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waitForPageLoad&lt;/code&gt;&lt;/strong&gt; — waits until &lt;code&gt;document.readyState&lt;/code&gt; is &lt;code&gt;"complete"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waitForJsCondition&lt;/code&gt;&lt;/strong&gt; — waits until an arbitrary JavaScript expression evaluates truthy, for the cases where none of the built-in conditions quite fit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waitForElementCount&lt;/code&gt;&lt;/strong&gt; — waits until the number of elements matching a locator equals an expected count, handy for list/table rendering that happens incrementally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waitForAttributeToBe&lt;/code&gt;&lt;/strong&gt; — waits until an element's attribute or DOM property equals an expected value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;waitForNumberOfWindowsToBe&lt;/code&gt;&lt;/strong&gt; — waits until the open window/tab count matches, for flows that open a new tab.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And critically, sitting in &lt;code&gt;NetworkTools&lt;/code&gt; rather than &lt;code&gt;WaitTools&lt;/code&gt; because it's CDP-backed: &lt;strong&gt;&lt;code&gt;waitForNetworkIdle&lt;/code&gt;&lt;/strong&gt;, which waits until there have been no in-flight HTTP requests for a continuous idle period. This is the condition that actually matches what most engineers mean when they add a sleep "to let things settle" — not an element state, but the absence of pending network activity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why having an agent pick the condition is the actual value-add
&lt;/h2&gt;

&lt;p&gt;Any experienced Selenium engineer knows this list already. The hard part was never knowing the API — it's diagnosing, for a &lt;em&gt;specific&lt;/em&gt; flaky test, which condition actually corresponds to the real race. That diagnosis normally means reproducing the failure, watching it happen (ideally slowed down or recorded), and reasoning backward from what state the page was actually in when the assertion fired too early.&lt;/p&gt;

&lt;p&gt;With an AI agent that has both &lt;code&gt;WaitTools&lt;/code&gt; and &lt;code&gt;NetworkTools&lt;/code&gt; available in the same session, that diagnosis becomes something you can actually delegate. A reasonable prompt: "This test fails intermittently at the &lt;code&gt;assertOrderConfirmed&lt;/code&gt; step. Run it, capture the network log and console output around that assertion, and tell me what's actually still pending when it fails." The agent can drive the flow, pull &lt;code&gt;getNetworkLog&lt;/code&gt; and &lt;code&gt;getConsoleLogs&lt;/code&gt; scoped to that window, and tell you concretely — "there's a &lt;code&gt;POST /api/orders&lt;/code&gt; still in flight when the assertion runs" — instead of you inferring it from a screenshot or a CI video recording.&lt;/p&gt;

&lt;p&gt;Once the actual cause is known, the fix is usually obvious and small: swap a blind &lt;code&gt;Thread.sleep(2000)&lt;/code&gt; for &lt;code&gt;waitForNetworkIdle&lt;/code&gt;, or add &lt;code&gt;waitForElementCount&lt;/code&gt; where the UI renders a list in multiple network round trips instead of one. The value isn't that the agent knows an API you didn't — it's that it can &lt;em&gt;run the reproduction and read the evidence&lt;/em&gt; faster than you can context-switch into doing it yourself, especially for a test that only fails intermittently and needs a few reproduction attempts to catch in the act.&lt;/p&gt;

&lt;h2&gt;
  
  
  A pattern worth adopting even without an AI agent in the loop
&lt;/h2&gt;

&lt;p&gt;Independent of whether you're using an agent at all: if you're debugging a flaky Selenium test today, reach for &lt;code&gt;waitForNetworkIdle&lt;/code&gt; and a network log before you reach for a longer sleep. A longer sleep treats the symptom and makes your suite slower for everyone, forever, whether or not the race condition is even still there next month. Actually looking at what's in flight when the assertion fires tells you the real cause, and usually the real fix is a more precise wait, not a bigger one.&lt;/p&gt;

&lt;p&gt;Full parameter details for every wait condition and the network tools they pair with are on the &lt;a href="https://selenium-mcp.xpathy.uk/docs/tools" rel="noopener noreferrer"&gt;tool reference&lt;/a&gt;. If your suite has a flaky test sitting in a "known issue, don't have time" state right now, it's a reasonable one to try this against first.&lt;/p&gt;

</description>
      <category>selenium</category>
      <category>mcp</category>
      <category>agents</category>
      <category>java</category>
    </item>
    <item>
      <title>I Looked at Every Selenium MCP Server I Could Find Before Building My Own. Here's the Actual Landscape.</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sun, 09 Aug 2026 10:33:07 +0000</pubDate>
      <link>https://dev.to/voltajeba/i-looked-at-every-selenium-mcp-server-i-could-find-before-building-my-own-heres-the-actual-42c8</link>
      <guid>https://dev.to/voltajeba/i-looked-at-every-selenium-mcp-server-i-could-find-before-building-my-own-heres-the-actual-42c8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server that gives an AI coding assistant a real Selenium WebDriver session to inspect and drive Chrome, Firefox, or Edge directly, built specifically for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;. It combines structured element discovery for reliable locators, Chrome DevTools Protocol network/console tooling, and a standalone REST client in one server. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before writing a single line of &lt;strong&gt;selenium-mcp&lt;/strong&gt;, I did what you're supposed to do before building anything: I checked whether it already existed. It's a reasonable thing to want to verify as a reader too — "another Selenium MCP server" is a fair amount of skepticism to bring to a new one. So here's the honest landscape, from the perspective of the audience this project is actually for: &lt;strong&gt;test automation engineers working in Java, Selenium, and REST Assured&lt;/strong&gt;, evaluating whether any of these tools help with that specific job, not general browser automation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7bqaq14inkg5cm5jzafe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7bqaq14inkg5cm5jzafe.png" alt="Image descr" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's actually out there
&lt;/h2&gt;

&lt;p&gt;There are more Selenium MCP servers than you'd expect — a healthy sign the underlying idea (let an AI agent drive Selenium) is obviously useful. Most cluster around the same shape:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js/TypeScript implementations&lt;/strong&gt;, several of which expose 15–80+ tools covering browser lifecycle, element interaction, and window/frame/cookie management — the standard Selenium surface. One of the more complete ones even includes an accessibility-tree resource for structured page inspection, which is a genuinely good idea done well. What none of them offer, as far as I found: a REST client for API testing alongside the browser tools, or Chrome DevTools Protocol access for network mocking/blocking. And structurally, they're aimed at general agentic browser automation — the target user is "an agent doing a task in a browser," not specifically a Java engineer maintaining a Selenium test suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python implementations&lt;/strong&gt;, similar shape — solid coverage of core Selenium actions, locator-based find/click/type tooling, screenshots. Same gap: no structured ancestor/sibling context for disambiguating locators, no CDP-backed network tooling, no adjacent API-testing capability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remote/browserless-backed implementations&lt;/strong&gt;, built for connecting to a Selenium Grid or a browserless service rather than driving a local browser — useful for a specific infrastructure pattern, but orthogonal to the locator-discovery and API-testing gaps this piece is about.&lt;/p&gt;

&lt;p&gt;I want to be fair here: several of these are well-built, actively maintained projects solving a real problem — browser automation for AI agents, full stop. That's a legitimate and different goal from what &lt;code&gt;selenium-mcp&lt;/code&gt; is for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's specifically missing, and it's the same gap every time
&lt;/h2&gt;

&lt;p&gt;Across essentially all of them, three things are consistently absent — and they're the three things that matter most if your actual job is maintaining a Java test suite, not just getting an agent to click through a demo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Structured, disambiguating element discovery.&lt;/strong&gt; Most expose a &lt;code&gt;find_element&lt;/code&gt;-equivalent plus raw page source. None I found return a match's ancestor chain with sibling position/count the way &lt;code&gt;getPageElementsFiltered&lt;/code&gt; does — the specific thing that lets an agent construct a locator that's unique &lt;em&gt;before&lt;/em&gt; trying it, instead of hitting &lt;code&gt;NoSuchElementException&lt;/code&gt; and iterating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDP-backed network and console tooling.&lt;/strong&gt; Selenium 4 has had &lt;code&gt;HasDevTools&lt;/code&gt;/&lt;code&gt;NetworkInterceptor&lt;/code&gt; access for a while. Almost nobody wires it up. Network capture shows up occasionally; mocking, blocking, simulated network conditions, and console log capture — the tools that actually help diagnose a flaky test — are rare to absent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A standalone REST client for API testing.&lt;/strong&gt; Not one of the general-purpose Selenium MCP servers I found ships an HTTP client alongside the browser tools. Given that &lt;a href="https://github.com/rest-assured/rest-assured/issues/1832" rel="noopener noreferrer"&gt;REST Assured's own repo has an open issue&lt;/a&gt; asking for exactly this kind of AI-driven API testing support, this isn't a niche gap — it's a documented, unaddressed one across the whole Java testing ecosystem, not just among Selenium MCP servers specifically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where Playwright MCP fits into this
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/microsoft/playwright-mcp" rel="noopener noreferrer"&gt;Playwright MCP&lt;/a&gt; deserves its own mention because it's the project that proved the underlying idea — structured page inspection beats raw HTML dumps for agent reliability — at scale, with official backing. It's excellent. It's also Node/Playwright, which means it does nothing for a team whose suite, CI, and team expertise are Java and Selenium, short of a full framework migration. I've written &lt;a href="//06-java-selenium-vs-playwright-mcp-enterprise-qa.md"&gt;more on that specific trade-off separately&lt;/a&gt; — the short version is that &lt;code&gt;selenium-mcp&lt;/code&gt; brings the same category of capability natively into Selenium, rather than asking Java teams to leave it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where selenium-mcp actually sits
&lt;/h2&gt;

&lt;p&gt;Putting it plainly, without the hedging: &lt;code&gt;selenium-mcp&lt;/code&gt; is, as far as I've been able to verify, the only Selenium-based MCP server that combines all three of structured ancestor/sibling-aware element discovery, CDP-backed network/console tooling, and a standalone REST client for API testing — built in Java specifically so it drops into an existing Selenium/Maven toolchain rather than asking a team to adopt a new language or runtime. If you know of another implementation that covers this same combination, I'd genuinely like to hear about it — &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; or a discussion, comparisons like this are only useful if they stay accurate as the landscape moves.&lt;/p&gt;

&lt;p&gt;If you want to check the claims yourself rather than take my word for it, the &lt;a href="https://selenium-mcp.xpathy.uk/docs/tools" rel="noopener noreferrer"&gt;tool reference&lt;/a&gt; lists every one of the 112 tools with parameters, and the &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;repo&lt;/a&gt; is MIT-licensed and open for inspection.&lt;/p&gt;

</description>
      <category>selenium</category>
      <category>mcp</category>
      <category>agents</category>
      <category>java</category>
    </item>
    <item>
      <title>Your Bank's QA Team Isn't Rewriting Ten Years of Selenium Tests for Anything. Here's What They Can Actually Adopt.</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sun, 09 Aug 2026 10:30:28 +0000</pubDate>
      <link>https://dev.to/voltajeba/your-banks-qa-team-isnt-rewriting-ten-years-of-selenium-tests-for-anything-heres-what-they-can-2j6e</link>
      <guid>https://dev.to/voltajeba/your-banks-qa-team-isnt-rewriting-ten-years-of-selenium-tests-for-anything-heres-what-they-can-2j6e</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server that gives an AI coding assistant a real Selenium WebDriver session, built specifically for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;. It drives Chrome, Firefox, or Edge directly, finds elements with enough structure to build locators that are unique on the first try, and adds Chrome DevTools Protocol network/console tooling plus a standalone REST client — as a development-time tool that plugs into an existing Selenium/Maven suite. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Enterprise QA doesn't move like a startup. If you're on a test automation team at a bank, an insurer, a healthcare company, or basically anywhere with a compliance department, you've got a Selenium suite that's been growing for years, a Selenium Grid or a cloud grid provider running it in CI, TestNG or JUnit reporting feeding into whatever dashboard your stakeholders check, and a very good reason not to touch any of it lightly: it works, it's audited, and "we rewrote our test framework" is not a sentence anyone wants to say after a compliance-relevant regression slips through.&lt;/p&gt;

&lt;p&gt;That's exactly the environment where most "AI-powered testing" pitches fall apart. They assume you're starting fresh, or that you're willing to adopt a new framework, a new language, a new CI integration. Enterprise QA teams correctly don't do that. I built &lt;strong&gt;selenium-mcp&lt;/strong&gt; to be adoptable by teams in exactly this position — because it doesn't ask you to change anything about how your suite runs. It only changes how new tests get written and how existing ones get debugged.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1rrys8umgtu3p4ilfjv7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1rrys8umgtu3p4ilfjv7.png" alt="Image desc" width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Nothing about your CI pipeline changes
&lt;/h2&gt;

&lt;p&gt;This is worth stating plainly because it's the first question a lead will ask: &lt;code&gt;selenium-mcp&lt;/code&gt; is a development-time tool. It runs on an engineer's machine, alongside their MCP-capable coding assistant, while they're &lt;em&gt;writing or debugging&lt;/em&gt; a test. The tests it helps produce are plain Java files using plain Selenium and, where relevant, a plain REST client. They get committed to the same repo, run through the same Maven build, execute on the same Selenium Grid, and report through the same TestNG/JUnit pipeline your team already has. Nothing about the CI side of your pipeline needs to know this tool exists.&lt;/p&gt;

&lt;p&gt;Compare that to the alternative most teams imagine when they hear "AI-assisted testing" — a hosted platform that runs your tests in its own cloud sandbox, with its own reporting, its own auth model, its own vendor relationship for a compliance team to evaluate. That's a much bigger adoption decision, and for a lot of enterprise teams, a non-starter on procurement grounds alone before anyone even evaluates whether it's good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it actually helps day to day
&lt;/h2&gt;

&lt;p&gt;Two workflows come up constantly on established Selenium teams, and both are exactly what this tool targets:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Writing new tests against pages your team didn't build.&lt;/strong&gt; Enterprise apps are frequently a patchwork of internal teams, contractors, and acquired products, which means your QA engineers are constantly writing locators against markup nobody on your team wrote and nobody documented. &lt;code&gt;getPageElementsFiltered&lt;/code&gt; — the tool that finds every match for a locator and returns its ancestor chain and sibling position — turns that into an inspection an agent can do directly against your actual staging environment, instead of your engineer manually reverse-engineering someone else's &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; soup in DevTools every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging flaky tests in an established suite.&lt;/strong&gt; A suite with years of history has years of accumulated flaky tests nobody's had time to properly fix — the ones with a &lt;code&gt;Thread.sleep()&lt;/code&gt; some engineer added years ago as a stopgap that never got revisited. &lt;code&gt;NetworkTools&lt;/code&gt;, particularly &lt;code&gt;waitForNetworkIdle&lt;/code&gt; and &lt;code&gt;getNetworkLog&lt;/code&gt;, gives an agent a way to actually diagnose &lt;em&gt;why&lt;/em&gt; a wait was needed in the first place, built on Chrome DevTools Protocol access that Selenium 4 already has but almost nobody wires up by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The audit trail question
&lt;/h2&gt;

&lt;p&gt;If your organization needs to know what changed and why — normal for regulated industries — the answer here is straightforward: every change an agent makes shows up as a normal diff in a normal pull request, same as if an engineer wrote it. There's no separate system generating or modifying tests outside your existing review process. The agent is a tool an engineer uses while writing a PR, not a system with its own write access to your codebase or CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to start if this is your situation
&lt;/h2&gt;

&lt;p&gt;Don't roll this out to a whole QA org on day one. Pick one engineer, one moderately painful area of the suite — a flaky test nobody's had time to fix, or a page with locators nobody trusts — and let them try &lt;code&gt;selenium-mcp&lt;/code&gt; against it for a week. The output is a plain Java diff either way; it's reviewable with exactly the rigor your team already applies to any PR. &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;Quickstart's here&lt;/a&gt; if that's the plan.&lt;/p&gt;

&lt;p&gt;Full tool reference, including everything mentioned above, is on the &lt;a href="https://selenium-mcp.xpathy.uk/docs/tools" rel="noopener noreferrer"&gt;docs site&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>selenium</category>
      <category>mcp</category>
      <category>agents</category>
      <category>java</category>
    </item>
    <item>
      <title>From Zero to a Working Selenium Test, Written by an AI Agent That Can Actually See the Page</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sun, 09 Aug 2026 10:27:48 +0000</pubDate>
      <link>https://dev.to/voltajeba/from-zero-to-a-working-selenium-test-written-by-an-ai-agent-that-can-actually-see-the-page-50nj</link>
      <guid>https://dev.to/voltajeba/from-zero-to-a-working-selenium-test-written-by-an-ai-agent-that-can-actually-see-the-page-50nj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server built for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;. It gives an AI coding agent — Claude Code, Cursor, Claude Desktop, anything that speaks MCP — a real Selenium WebDriver session it can drive directly, with structured element discovery, CDP network/console tooling, and a standalone REST client, instead of guessing at locators from pasted HTML. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one's a walkthrough, not an argument. If you're a test automation engineer curious about &lt;strong&gt;selenium-mcp&lt;/strong&gt; but haven't tried it yet, here's exactly how to go from nothing to an AI coding assistant writing a real, passing Selenium test against a page it inspected itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo2ll8z078taedha7dty3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo2ll8z078taedha7dty3.png" alt="Image" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Nothing exotic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 21+, with &lt;code&gt;JAVA_HOME&lt;/code&gt; pointing at it&lt;/li&gt;
&lt;li&gt;Chrome, Firefox, or Edge installed locally — WebDriver binaries are fetched automatically on first use, no manual driver management&lt;/li&gt;
&lt;li&gt;An MCP-capable client: Claude Code, Claude Desktop, Cursor, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the whole list. No Node toolchain, no separate browser runtime to install — the server drives the actual browser you already have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Grab the jar
&lt;/h2&gt;

&lt;p&gt;Every push to &lt;code&gt;main&lt;/code&gt; publishes a fresh GitHub Release with the jar attached, so there's no build step required:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp/releases/latest/download/selenium-mcp.jar" rel="noopener noreferrer"&gt;⬇ Download selenium-mcp.jar (latest release)&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you'd rather build from source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Volta-Jebaprashanth/selenium-mcp.git
&lt;span class="nb"&gt;cd &lt;/span&gt;selenium-mcp
mvn clean package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2 — Point your MCP client at it
&lt;/h2&gt;

&lt;p&gt;The server talks over stdio, so it's launched by your MCP client rather than run standalone in a terminal. For Claude Code or Claude Desktop, add this to your MCP server config, adjusting the path to wherever you saved the jar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"selenium-mcp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"java"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-jar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/absolute/path/to/selenium-mcp.jar"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart your client, and you should see &lt;code&gt;selenium-mcp&lt;/code&gt; show up as an available tool provider, with all 112 tools across 16 categories ready to call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Point it at your actual Maven project
&lt;/h2&gt;

&lt;p&gt;This is the part that matters if you're evaluating this for real work rather than just kicking the tires: open your MCP client in the same workspace as your existing Java/Selenium/Maven test project. The agent isn't just driving a throwaway browser session — it's writing Java files directly into your &lt;code&gt;src/test/java&lt;/code&gt; tree, using whatever test framework (TestNG, JUnit 5) and structure your project already has.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Ask for a real test
&lt;/h2&gt;

&lt;p&gt;Here's a prompt shape that exercises the actual point of the tool, rather than a toy example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Open Chrome and navigate to our staging login page at &lt;code&gt;https://staging.example.com/login&lt;/code&gt;. Inspect the email and password fields using the page element tools, then write a &lt;code&gt;LoginPageTest&lt;/code&gt; class in our existing &lt;code&gt;LoginPage&lt;/code&gt; Page Object style, using TestNG, that logs in with a valid test user and asserts we land on the dashboard."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Watch the tool calls as they happen (most MCP clients show these): &lt;code&gt;openBrowser&lt;/code&gt;, &lt;code&gt;navigate&lt;/code&gt;, then &lt;code&gt;getPageElementsFiltered&lt;/code&gt; against the login form to get real ancestor/sibling-disambiguated locators — not guesses. The agent writes the &lt;code&gt;By&lt;/code&gt; selectors from what it actually found on the page, adds a &lt;code&gt;waitForVisible&lt;/code&gt; or &lt;code&gt;waitForPageLoad&lt;/code&gt; where the flow needs it, and hands you a test file that follows your project's existing conventions because it can see them, same as it can see the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Run it, review it like any other PR
&lt;/h2&gt;

&lt;p&gt;The output is a plain Java file using standard Selenium and your existing test framework — nothing proprietary, no runtime dependency on the MCP server itself (see the &lt;a href="//05-architecture-tour-clean-selenium-layer.md"&gt;architecture piece&lt;/a&gt; if you want the detail on why that's true by design). Run it with your normal &lt;code&gt;mvn test&lt;/code&gt;. Review it the way you'd review any teammate's PR — check the locators are sensible, check the waits are appropriate, ask for changes the same way you would with a human's first draft.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few things worth trying beyond the first test
&lt;/h2&gt;

&lt;p&gt;Once the basic loop works, a few follow-ups are worth exploring in the same session:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask it to add a REST Assured-style verification step using &lt;code&gt;ApiTools&lt;/code&gt;, seeding or checking data through the API instead of only through the UI — see the &lt;a href="//04-rest-assured-ai-gap-api-ui-testing.md"&gt;API+UI piece&lt;/a&gt; for what that looks like in practice.&lt;/li&gt;
&lt;li&gt;Point it at a flaky existing test and ask it to diagnose the timing issue using &lt;code&gt;NetworkTools&lt;/code&gt; — &lt;code&gt;waitForNetworkIdle&lt;/code&gt; and &lt;code&gt;getNetworkLog&lt;/code&gt; in particular.&lt;/li&gt;
&lt;li&gt;Ask it to refactor an existing Page Object's brittle locators using &lt;code&gt;getPageElementsFiltered&lt;/code&gt;, rather than only writing new ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  If something doesn't work
&lt;/h2&gt;

&lt;p&gt;The project is MIT-licensed and actively maintained — if a tool call behaves unexpectedly or a locator strategy you need isn't supported, &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;. The full, searchable tool reference — every parameter, every category — lives on the &lt;a href="https://selenium-mcp.xpathy.uk/docs/tools" rel="noopener noreferrer"&gt;docs site&lt;/a&gt;, worth bookmarking once you're past the first test and exploring what else is available.&lt;/p&gt;

</description>
      <category>selenium</category>
      <category>mcp</category>
      <category>java</category>
      <category>agents</category>
    </item>
    <item>
      <title>No, Your Team Doesn't Need to Rewrite Its Selenium Suite in Playwright to Get AI-Assisted Testing</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sun, 09 Aug 2026 10:24:40 +0000</pubDate>
      <link>https://dev.to/voltajeba/no-your-team-doesnt-need-to-rewrite-its-selenium-suite-in-playwright-to-get-ai-assisted-testing-25n3</link>
      <guid>https://dev.to/voltajeba/no-your-team-doesnt-need-to-rewrite-its-selenium-suite-in-playwright-to-get-ai-assisted-testing-25n3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server that gives an AI coding assistant a real Selenium WebDriver session to drive Chrome, Firefox, or Edge directly, built specifically for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;. It covers structured element discovery for reliable locators, Chrome DevTools Protocol network/console debugging, and a standalone REST client for API testing — all inside the Selenium/Maven toolchain teams already run. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every few months, someone on a Java QA team asks the same question in a different form: "should we just move to Playwright? It's got better AI tooling, better tracing, the MCP server is official." It's a fair question. &lt;a href="https://github.com/microsoft/playwright-mcp" rel="noopener noreferrer"&gt;Playwright MCP&lt;/a&gt; is genuinely good — structured accessibility-tree snapshots, official Microsoft backing, tight integration with the framework it's built for.&lt;/p&gt;

&lt;p&gt;It's also, for a huge share of enterprise QA teams, not a realistic answer. You don't migrate a decade of Selenium suites, a CI pipeline built around a Selenium Grid, a team of engineers who know Java and TestNG, and every internal utility library built on top of &lt;code&gt;WebDriver&lt;/code&gt;, just to get an AI coding assistant that can see the page. That's not a tooling decision, that's a multi-quarter migration project with its own risk, and most teams correctly won't sign up for it just to unlock a developer-experience improvement.&lt;/p&gt;

&lt;p&gt;This is the actual reason I built &lt;strong&gt;selenium-mcp&lt;/strong&gt;: so Java/Selenium teams get the same category of capability without the rewrite.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fffz8fxs78fwveaknkd7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fffz8fxs78fwveaknkd7q.png" alt="No, Your Team Doesn't Need to Rewrite Its Selenium Suite in Playwright to Get AI-Assisted Testing" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Playwright MCP actually solved
&lt;/h2&gt;

&lt;p&gt;Worth being precise about this, since it's the thing everyone's actually asking for. Playwright MCP's core contribution is replacing raw DOM dumps with a structured accessibility-tree snapshot — an agent reasons about "the Sign In button" as a distinct, addressable thing instead of parsing markup by eye. That's the capability that made AI-driven browser testing actually reliable instead of a novelty.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;selenium-mcp&lt;/code&gt; brings the same underlying idea to Selenium — not the identical mechanism (Selenium doesn't expose Playwright's accessibility-snapshot API), but the same outcome: &lt;code&gt;getPageElementsFiltered&lt;/code&gt; finds every element matching a locator and returns it with full ancestor-chain and sibling-position context, so an agent builds a locator that's unique by construction instead of by guesswork. Same problem, same category of fix, native to Selenium instead of bolted onto it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the two genuinely differ, past that
&lt;/h2&gt;

&lt;p&gt;Being straight about trade-offs matters more than pretending there aren't any:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Language and existing investment.&lt;/strong&gt; Playwright MCP is Node.js. If your suite, your CI, and your team's expertise are already Java/Selenium, &lt;code&gt;selenium-mcp&lt;/code&gt; runs as a single jar inside that same world — no new language, no new CI toolchain, no new runtime to operationalize.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser engine.&lt;/strong&gt; Playwright drives Chromium, Firefox, and WebKit through its own automation protocol. Selenium drives real Chrome, Firefox, and Edge through WebDriver — the actual browsers your users run, via the actual protocol your existing suite already trusts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API testing in the same tool.&lt;/strong&gt; &lt;code&gt;selenium-mcp&lt;/code&gt; ships a standalone REST client (&lt;code&gt;ApiTools&lt;/code&gt;) alongside the browser tools, so an agent can help write a REST Assured-style verification step in the same session as a UI step. Playwright MCP is scoped to the browser; API testing is a separate concern in that ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDP-backed network and console tooling.&lt;/strong&gt; Both expose network capture; &lt;code&gt;selenium-mcp&lt;/code&gt; additionally offers request mocking/blocking and simulated network conditions via Chrome DevTools Protocol on Chrome/Edge — the same low-level access, made reachable from Selenium instead of requiring you to already be on Playwright to get it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What this isn't
&lt;/h2&gt;

&lt;p&gt;This isn't "Selenium is better than Playwright" — that's a different, much older debate, and it depends heavily on what you're testing and how your team already works. This is specifically about the AI-assisted testing gap: if your team's stack is already Playwright, you have this solved. If it's Java and Selenium, you didn't, until now, and the honest fix for that gap was never "switch frameworks" — it was "bring the same capability natively to the framework you're already using and already trust."&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual decision in front of most teams
&lt;/h2&gt;

&lt;p&gt;If you're starting a browser-automation project from zero today, with no existing suite and no team constraints, the Playwright-vs-Selenium conversation is genuinely open and worth having on its own merits. But that's not the situation most QA organizations reading this are in. You have a working Selenium suite, a CI pipeline that runs it, and engineers who are productive in Java. The question was never "is Playwright's tooling nicer" — often, yes. The question is whether that's worth a rewrite. For most teams, it isn't, and now it doesn't have to be a trade-off you make at all.&lt;/p&gt;

&lt;p&gt;Full tool reference is on the &lt;a href="https://selenium-mcp.xpathy.uk/docs/tools" rel="noopener noreferrer"&gt;docs site&lt;/a&gt; if you want to see exactly what's available before deciding whether this closes the gap for your team.&lt;/p&gt;

</description>
      <category>java</category>
      <category>selenium</category>
      <category>mcp</category>
      <category>agents</category>
    </item>
    <item>
      <title>I Didn't Want an AI Tool That Pollutes My Test Codebase. Here's How the Architecture Prevents That.</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sun, 09 Aug 2026 10:21:47 +0000</pubDate>
      <link>https://dev.to/voltajeba/i-didnt-want-an-ai-tool-that-pollutes-my-test-codebase-heres-how-the-architecture-prevents-that-5e8f</link>
      <guid>https://dev.to/voltajeba/i-didnt-want-an-ai-tool-that-pollutes-my-test-codebase-heres-how-the-architecture-prevents-that-5e8f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server built for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;. It gives an AI coding assistant a real Selenium WebDriver session to drive Chrome, Firefox, or Edge directly — structured element discovery for reliable locators, Chrome DevTools Protocol network/console tooling, and a standalone REST client, all in one server. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A fair worry, if you're a test automation engineer looking at any AI-adjacent tool: does adopting this mean my codebase now has some framework's fingerprints all over it? Half the "AI-powered testing" tools out there generate code that's obviously generated — proprietary annotations, a runtime dependency on the vendor's SDK, patterns your team wouldn't have chosen on their own. You end up maintaining the AI tool's opinions as much as your actual tests.&lt;/p&gt;

&lt;p&gt;That was a hard constraint for me going into &lt;strong&gt;selenium-mcp&lt;/strong&gt;: whatever code an agent writes using this should look exactly like Selenium code a senior engineer on your team would have written by hand. No trace of "an MCP server helped write this." Here's how the architecture makes that true, not just a claim in a README.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fba0v8gw1m7ajkfspm1h0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fba0v8gw1m7ajkfspm1h0.png" alt="Image" width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Three layers, deliberately kept apart
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tools/      @McpTool-annotated classes. MCP-facing only.
webdriver/  Plain-Java Selenium layer. No Spring, no MCP annotations.
http/       Plain-Java REST client. No Selenium/Spring/MCP dependency at all.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;tools/&lt;/code&gt; package is the only place that knows this is an MCP server at all — parameter validation, "is a browser open" precondition checks, translating exceptions into readable strings. Genuinely thin.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;webdriver/&lt;/code&gt; is where the real work happens, and it has zero knowledge of MCP, Spring, or an AI agent existing. &lt;code&gt;Tools.java&lt;/code&gt; is the facade; &lt;code&gt;BrowserFactory&lt;/code&gt;, &lt;code&gt;BrowserSession&lt;/code&gt;, &lt;code&gt;Locators&lt;/code&gt;, &lt;code&gt;Navigator&lt;/code&gt;, &lt;code&gt;ElementInteractor&lt;/code&gt;, and the rest are single-responsibility collaborators wired through constructors. This is exactly the shape a hand-written Selenium utility layer would take if you built it from scratch with clean separation of concerns.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http/&lt;/code&gt; mirrors that for the REST client (&lt;code&gt;ApiClient&lt;/code&gt;) — standalone, no relationship to the browser session or the MCP layer at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond "clean code"
&lt;/h2&gt;

&lt;p&gt;It's not an aesthetic preference. It has a concrete consequence: &lt;strong&gt;&lt;code&gt;webdriver/Tools&lt;/code&gt; is usable directly, with no MCP server running at all&lt;/strong&gt;, as a standalone Selenium utility layer for hand-writing or generating tests. Same for &lt;code&gt;http/ApiClient&lt;/code&gt; on the API side. The AI-assisted layer sits &lt;em&gt;on top of&lt;/em&gt; a plain Java Selenium library — it isn't a separate thing that happens to also produce Selenium-shaped output. When an agent uses &lt;code&gt;selenium-mcp&lt;/code&gt; to explore a page and then writes a &lt;code&gt;LoginPage&lt;/code&gt; class for your suite, the Java it writes calls the same kind of APIs — &lt;code&gt;driver.findElement(By.cssSelector(...))&lt;/code&gt;, explicit &lt;code&gt;WebDriverWait&lt;/code&gt;s — that you'd write yourself, because under the hood, that's genuinely what's running.&lt;/p&gt;

&lt;p&gt;That's the difference between "AI tool that happens to output Java" and "Selenium library an AI agent happens to be using." The second one is what you actually want in a codebase your whole team maintains, agent-assisted or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule that keeps it that way
&lt;/h2&gt;

&lt;p&gt;There's a hard line documented in the project's &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp/blob/main/AGENTS.md" rel="noopener noreferrer"&gt;AGENTS.md&lt;/a&gt;, the file that governs how AI coding agents are allowed to modify the project itself: no Selenium calls in &lt;code&gt;tools/&lt;/code&gt;, no MCP/Spring types in &lt;code&gt;webdriver/&lt;/code&gt; or &lt;code&gt;http/&lt;/code&gt;. It's enforced by convention and code review, not a compiler — but it's the single rule that keeps the Selenium layer honest as a standalone library instead of slowly growing MCP-specific assumptions into itself over time.&lt;/p&gt;

&lt;p&gt;There's a second convention worth calling out for anyone auditing this before adopting it: &lt;strong&gt;&lt;code&gt;@McpTool&lt;/code&gt; methods always return strings, success or failure&lt;/strong&gt; — exceptions are caught in the tool wrapper and turned into a descriptive message rather than propagating out. That's a deliberate MCP-protocol-compatibility choice at the &lt;code&gt;tools/&lt;/code&gt; boundary, and it stays exactly at that boundary — it doesn't leak into how &lt;code&gt;webdriver/Tools&lt;/code&gt; itself is written, which throws normal Java exceptions like any other library.&lt;/p&gt;

&lt;h2&gt;
  
  
  CDP support gets the same treatment
&lt;/h2&gt;

&lt;p&gt;One more example, because it's a real edge case: &lt;code&gt;NetworkMonitor&lt;/code&gt; and &lt;code&gt;ConsoleLogMonitor&lt;/code&gt; are built on Selenium 4's Chrome DevTools Protocol support, which Firefox doesn't implement. Their methods throw &lt;code&gt;UnsupportedOperationException&lt;/code&gt; on an unsupported driver — that's plain Java behavior, no MCP awareness. It's only the &lt;code&gt;tools/NetworkTools&lt;/code&gt; wrapper that catches that specific exception and turns it into an explanatory string for the agent. The distinction matters: the capability boundary is enforced in the Selenium layer, where it belongs; the "make this readable for an AI client" translation happens only at the very top.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means if you're evaluating this for your team
&lt;/h2&gt;

&lt;p&gt;If your team is cautious about adopting AI tooling into a shared test codebase — a completely reasonable position — the thing to check isn't "does it generate working tests," it's "what does the generated code actually depend on." Here, the answer is: your test files depend on plain Selenium and a plain REST client, same as if you'd written them by hand. The MCP server is a development-time tool, not a runtime dependency your suite inherits. You can stop using &lt;code&gt;selenium-mcp&lt;/code&gt; entirely tomorrow and every test it helped write keeps running exactly as it does today.&lt;/p&gt;

&lt;p&gt;Full project structure is documented in the &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp#project-structure" rel="noopener noreferrer"&gt;README&lt;/a&gt; and &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp/blob/main/AGENTS.md" rel="noopener noreferrer"&gt;AGENTS.md&lt;/a&gt; if you want to see the layering rules in full before pointing an agent at your repo.&lt;/p&gt;

</description>
      <category>java</category>
      <category>selenium</category>
      <category>mcp</category>
      <category>automation</category>
    </item>
    <item>
      <title>REST Assured Doesn't Have an Official AI Tool Yet. Here's Why That Matters More Than It Sounds.</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sun, 09 Aug 2026 10:18:43 +0000</pubDate>
      <link>https://dev.to/voltajeba/rest-assured-doesnt-have-an-official-ai-tool-yet-heres-why-that-matters-more-than-it-sounds-31b</link>
      <guid>https://dev.to/voltajeba/rest-assured-doesnt-have-an-official-ai-tool-yet-heres-why-that-matters-more-than-it-sounds-31b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server that gives an AI coding assistant a real Selenium WebDriver session — plus a standalone REST client — built specifically for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;. It drives Chrome, Firefox, or Edge directly, discovers page elements with enough structure to write locators that are unique on the first try, and exposes Chrome DevTools Protocol tooling alongside plain HTTP request tools for API testing. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go look at &lt;a href="https://github.com/rest-assured/rest-assured/issues/1832" rel="noopener noreferrer"&gt;issue #1832 on the REST Assured GitHub repo&lt;/a&gt;. Someone's asking, plainly: is there a plan for an official MCP server, so AI agents can drive API test automation the way they've started driving everything else? As of writing, there's no official answer.&lt;/p&gt;

&lt;p&gt;That's a small GitHub issue, but it says something real about where the current wave of "AI-assisted testing" tooling has and hasn't reached. If you write UI tests in Playwright and TypeScript, or you're doing general web scraping, there's no shortage of AI tooling aimed at you. If you write &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt; — which describes a huge share of enterprise QA teams — the tooling gap is real, and it's not just about the browser. It's about the API layer too.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;selenium-mcp&lt;/strong&gt; to close both halves of that gap at once, for exactly that audience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F26mtx8qlpn2ttj5oqjoy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F26mtx8qlpn2ttj5oqjoy.png" alt="Image des" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a browser tool also needs an API client
&lt;/h2&gt;

&lt;p&gt;Think about how a real end-to-end test actually gets written. You rarely test the UI in total isolation — you seed data through an API first (create a user, create an order), drive the UI flow, and then very often verify the &lt;em&gt;result&lt;/em&gt; by calling the API again rather than scraping it back out of the DOM. That's the whole reason REST Assured exists next to Selenium in so many Java test suites in the first place: UI and API testing are two tools for the same job, used together constantly.&lt;/p&gt;

&lt;p&gt;An AI coding assistant that can only see the browser is missing half of that picture. It can help you write the UI half of a test and then just... stop, and hand the API half back to you. That's the same "you do the real work, I'll type it up" problem I've written about with locators — just showing up in a different part of the test.&lt;/p&gt;

&lt;h2&gt;
  
  
  What &lt;code&gt;ApiTools&lt;/code&gt; gives you
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ApiTools&lt;/code&gt; is a standalone HTTP client, independent of the browser session entirely — it works whether or not a browser is even open. It gives an agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;httpGet&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;httpDelete&lt;/code&gt;&lt;/strong&gt; — GET/DELETE with optional headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;httpPost&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;httpPut&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;httpPatch&lt;/code&gt;&lt;/strong&gt; — send a body plus optional headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;httpRequest&lt;/code&gt;&lt;/strong&gt; — arbitrary HTTP method, for the odd &lt;code&gt;HEAD&lt;/code&gt; or &lt;code&gt;OPTIONS&lt;/code&gt; check.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every response comes back as a consistent JSON shape — &lt;code&gt;{status, headers, body, durationMillis}&lt;/code&gt; — which matters more than it sounds like: it means the agent (and you, reading the tool call output) get response &lt;em&gt;and&lt;/em&gt; timing back from the same call, useful when you're checking not just correctness but whether an endpoint is meeting a latency expectation as part of the test. Headers go in as a plain JSON object string, e.g. &lt;code&gt;{"Authorization": "Bearer xyz", "Content-Type": "application/json"}&lt;/code&gt; — nothing to memorize beyond what you'd already write in REST Assured itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this looks like in a real test
&lt;/h2&gt;

&lt;p&gt;Say you're writing an end-to-end checkout test. The flow is: create a test user via API, log that user in through the UI, add an item to the cart, complete checkout, then verify the order landed correctly by calling the orders API directly rather than trusting a confirmation &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; on screen.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;ApiTools&lt;/code&gt; and &lt;code&gt;BrowserTools&lt;/code&gt;/&lt;code&gt;PageSourceTools&lt;/code&gt; available in the same agent session, you can ask for exactly that end-to-end flow in one request, and the agent writes it as one coherent Java test — &lt;code&gt;httpPost&lt;/code&gt; to seed the user, Selenium calls (with correctly discovered locators, via &lt;code&gt;getPageElementsFiltered&lt;/code&gt;) to drive the UI, &lt;code&gt;httpGet&lt;/code&gt; to verify the order — instead of you assembling the API call yourself and asking the agent to "add this in."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is different from a general-purpose REST client tool
&lt;/h2&gt;

&lt;p&gt;There are plenty of standalone MCP servers that just do HTTP requests — Postman-style tools, generic API testers. What makes this different isn't the HTTP client itself; it's that it lives in the &lt;em&gt;same&lt;/em&gt; session as the Selenium tooling, so an agent building a test doesn't have to context-switch between two separate MCP servers to write one test that spans both layers. One conversation, one Java test file, both halves of your suite's actual working pattern reflected in the output.&lt;/p&gt;

&lt;p&gt;It's also, notably, not something the Node/Python Selenium MCP servers offer either — most of them are scoped to browser automation alone, aimed at agentic browsing rather than test-suite authoring. Between that and the open question on REST Assured's own repo about official AI tooling, this is a gap that's been sitting unaddressed on the Java/Selenium/REST Assured side specifically, not something everyone else already solved and I just packaged differently.&lt;/p&gt;

&lt;p&gt;Full details on request/response shapes are on the &lt;a href="https://selenium-mcp.xpathy.uk/docs/tools" rel="noopener noreferrer"&gt;tool reference&lt;/a&gt;. If you're maintaining a suite that already mixes REST Assured and Selenium, this is the part of &lt;code&gt;selenium-mcp&lt;/code&gt; worth trying first — it's the piece that mirrors how you were already structuring tests, not a new pattern to learn.&lt;/p&gt;

</description>
      <category>java</category>
      <category>api</category>
      <category>test</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Your Selenium Test Isn't Flaky. Your Backend Is Just Slower Than Your Thread.sleep().</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sun, 09 Aug 2026 10:13:16 +0000</pubDate>
      <link>https://dev.to/voltajeba/your-selenium-test-isnt-flaky-your-backend-is-just-slower-than-your-threadsleep-2ikc</link>
      <guid>https://dev.to/voltajeba/your-selenium-test-isnt-flaky-your-backend-is-just-slower-than-your-threadsleep-2ikc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server that gives an AI coding assistant — Claude Code, Cursor, Claude Desktop — a real Selenium WebDriver session to drive Chrome, Firefox, or Edge directly, built specifically for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;. Beyond structured element discovery for reliable locators, it exposes Chrome DevTools Protocol tooling for network capture, mocking, and console log debugging, plus a standalone REST client for API testing. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every Selenium suite has that one test. It passes locally, fails in CI, passes again if you re-run it, fails again next Tuesday for no obvious reason. Nine times out of ten, when you actually dig in, the cause isn't your locator or your assertion — it's timing. Some XHR call the click triggered hadn't finished when your test tried to read the result.&lt;/p&gt;

&lt;p&gt;The usual fixes are all some flavor of unsatisfying: a &lt;code&gt;Thread.sleep(2000)&lt;/code&gt; that either wastes time or isn't long enough depending on the day, or an explicit wait on a UI element that only &lt;em&gt;implies&lt;/em&gt; the network call behind it has settled. Neither one tells you what's actually happening on the wire.&lt;/p&gt;

&lt;p&gt;Selenium 4 quietly shipped access to the Chrome DevTools Protocol — the same low-level API Chrome's own DevTools panel uses — which means you can actually see the network traffic, not just guess at it from what rendered. Most Selenium suites never touch it, because wiring up &lt;code&gt;HasDevTools&lt;/code&gt; and &lt;code&gt;NetworkInterceptor&lt;/code&gt; by hand is enough ceremony that people reach for &lt;code&gt;Thread.sleep()&lt;/code&gt; instead. I wired it into &lt;strong&gt;selenium-mcp&lt;/strong&gt; so an AI coding assistant can use it on your behalf, as part of writing or debugging a Java Selenium test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0v5qo4uayi54wgdyel7t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0v5qo4uayi54wgdyel7t.png" alt="Image des" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What &lt;code&gt;NetworkTools&lt;/code&gt; actually gives you
&lt;/h2&gt;

&lt;p&gt;This group is built on Selenium 4's CDP support and works against Chrome and Edge (Firefox doesn't expose CDP the same way — every tool in this group returns a clear explanatory message instead of throwing if you call it on an unsupported browser, so it fails loud and readable, not silently).&lt;/p&gt;

&lt;p&gt;The tool that solves the flaky-wait problem directly is &lt;strong&gt;&lt;code&gt;waitForNetworkIdle&lt;/code&gt;&lt;/strong&gt; — it waits until there have been no in-flight HTTP requests for a continuous idle period. That's the actual condition you meant when you wrote a fixed sleep after a click that triggers an XHR call. Pair it with &lt;strong&gt;&lt;code&gt;getPendingRequestCount&lt;/code&gt;&lt;/strong&gt; when you want to assert &lt;em&gt;why&lt;/em&gt; a wait is still blocking, instead of just watching it time out.&lt;/p&gt;

&lt;p&gt;Beyond that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;startNetworkCapture&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;stopNetworkCapture&lt;/code&gt;&lt;/strong&gt; — passively record method, URL, headers, bodies, status, and timing for every request, optionally filtered by a URL regex, so you're not drowning in analytics beacons and font requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;getNetworkLog&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;clearNetworkLog&lt;/code&gt;&lt;/strong&gt; — pull captured entries back as JSON, filterable by URL pattern or method, most recent last.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mockResponse&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;clearMockResponses&lt;/code&gt;&lt;/strong&gt; — stub a response for requests matching a URL regex (status, headers, body) without touching the real network. Genuinely useful for testing a UI's error-handling path when you can't easily make the real backend return a 500 on demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;blockRequests&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;clearBlockedRequests&lt;/code&gt;&lt;/strong&gt; — block requests matching a URL regex outright (immediate 403). Handy for stripping third-party ad/tracker calls that add flakiness to a test with nothing to do with what you're actually testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;setNetworkConditions&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;getNetworkConditions&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;clearNetworkConditions&lt;/code&gt;&lt;/strong&gt; — simulate offline mode, added latency, or throttled throughput, for testing how your app behaves on a bad connection without needing an actual bad connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;setBasicAuthCredentials&lt;/code&gt;&lt;/strong&gt; — register HTTP Basic auth so a login popup never blocks navigation in the first place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;startConsoleCapture&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;getConsoleLogs&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;clearConsoleLogs&lt;/code&gt;&lt;/strong&gt; — capture browser console output (&lt;code&gt;console.log&lt;/code&gt;/&lt;code&gt;warn&lt;/code&gt;/&lt;code&gt;error&lt;/code&gt;), filterable by type. When a test fails and you can't tell if it's a UI bug or a JS exception, this is usually the fastest way to find out.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where this actually changes how you debug
&lt;/h2&gt;

&lt;p&gt;Picture the standard flaky-test investigation: a test fails intermittently in CI, passes locally, and you can't reproduce it on demand. Normally that's an afternoon of adding sleeps, staring at video recordings, and guessing.&lt;/p&gt;

&lt;p&gt;With an AI agent driving this toolset, you can instead ask it to reproduce the flow, capture the network log around the failing assertion, and check console output for the same window — in one pass, from inside your chat. If the real cause is a request that's still pending when the assertion runs, &lt;code&gt;getNetworkLog&lt;/code&gt; and &lt;code&gt;getPendingRequestCount&lt;/code&gt; show that directly, instead of you inferring it from a screenshot. If it's an uncaught JS error the UI silently swallowed, &lt;code&gt;getConsoleLogs&lt;/code&gt; surfaces it. Either way, you're fixing the actual cause instead of adding another &lt;code&gt;Thread.sleep()&lt;/code&gt; and hoping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters specifically for a Java/Selenium suite
&lt;/h2&gt;

&lt;p&gt;This isn't a capability unique to browser automation in general — Playwright has had first-class network interception for a while, which is part of why Playwright suites are often less flaky than comparable Selenium ones. The gap has always been on the Java/Selenium side: the capability exists in Selenium 4, but almost nobody uses it because there was no lightweight way to reach for it mid-debugging-session. &lt;code&gt;selenium-mcp&lt;/code&gt; doesn't add a new capability to Selenium — it makes the one that was already there, and mostly ignored, actually usable from an AI coding assistant, in the same Java toolchain your suite already runs on.&lt;/p&gt;

&lt;p&gt;Full parameter details for every tool in this group are on the &lt;a href="https://selenium-mcp.xpathy.uk/docs/tools" rel="noopener noreferrer"&gt;tool reference&lt;/a&gt;. If you're chasing a flaky test right now, &lt;code&gt;waitForNetworkIdle&lt;/code&gt; is the one worth trying first — it's usually a straight swap for whatever &lt;code&gt;Thread.sleep()&lt;/code&gt; you were about to write.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>selenium</category>
      <category>java</category>
      <category>automation</category>
    </item>
    <item>
      <title>How to Get an AI Coding Assistant to Write a Correct Selenium Locator on the First Try</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sun, 09 Aug 2026 10:10:11 +0000</pubDate>
      <link>https://dev.to/voltajeba/how-to-get-an-ai-coding-assistant-to-write-a-correct-selenium-locator-on-the-first-try-3a69</link>
      <guid>https://dev.to/voltajeba/how-to-get-an-ai-coding-assistant-to-write-a-correct-selenium-locator-on-the-first-try-3a69</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server that hands an AI coding agent a real Selenium WebDriver session — it opens Chrome, Firefox, or Edge, inspects the actual live page, and writes the Java locator itself instead of guessing from pasted HTML. Built specifically for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;, it also covers CDP network/console debugging and standalone REST API testing. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every Selenium engineer has written this line of debugging output at least once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or the meaner cousin — the locator &lt;em&gt;does&lt;/em&gt; match something, just three of it, and your test clicked the wrong one. You fix it the same way every time: open DevTools, inspect the actual element, walk up the DOM until you find something unique about it, write the real selector, run the test again.&lt;/p&gt;

&lt;p&gt;Now hand that same task to an AI coding assistant without giving it eyes on the page, and it does the only thing it can — it guesses from whatever HTML you pasted in, or from a locator pattern that looked right in a similar test elsewhere in your suite. Sometimes it's right. Often it isn't, and you're back to doing the DevTools inspection yourself and feeding the answer back into the chat.&lt;/p&gt;

&lt;p&gt;This is the specific problem &lt;strong&gt;selenium-mcp&lt;/strong&gt; exists to solve.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8atary2zaptql5qg6dfm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8atary2zaptql5qg6dfm.png" alt="Image" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The tool that changes the workflow
&lt;/h2&gt;

&lt;p&gt;It's called &lt;code&gt;getPageElementsFiltered&lt;/code&gt;, part of the &lt;code&gt;PageSourceTools&lt;/code&gt; group. Instead of finding just the first element that matches a locator, it finds &lt;strong&gt;every&lt;/strong&gt; matching element on the live page and returns each as structured JSON, with three optional context flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;includeAncestors&lt;/code&gt;&lt;/strong&gt; — the full parent chain up to &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;, with every node annotated with &lt;code&gt;siblingIndex&lt;/code&gt; and &lt;code&gt;siblingCount&lt;/code&gt;. This is the piece that matters most: it's what lets the agent build a selector that's provably unique instead of one that merely looks specific.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;includeSiblings&lt;/code&gt;&lt;/strong&gt; — the other children of the same parent, useful when a locator needs to correlate a &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; with the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; sitting next to it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;includeDescendants&lt;/code&gt;&lt;/strong&gt; — expand a match's own children, for when you're locating a container rather than a leaf, like a table row you need to then query further.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The response reports &lt;code&gt;totalMatches&lt;/code&gt;, &lt;code&gt;returnedMatches&lt;/code&gt;, and &lt;code&gt;truncated&lt;/code&gt; every time (results capped via &lt;code&gt;limit&lt;/code&gt;, default 50), so the agent — and you, reading the tool call log — always know whether you're seeing the whole picture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this looks like in a real Page Object
&lt;/h2&gt;

&lt;p&gt;Say you're writing a &lt;code&gt;LoginPage&lt;/code&gt; class and the markup gives you nothing helpful — two &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; elements with no &lt;code&gt;id&lt;/code&gt;, no &lt;code&gt;name&lt;/code&gt;, generic classes shared across the form. This is the exact situation that used to mean tabbing over to the browser yourself.&lt;/p&gt;

&lt;p&gt;Instead, point the agent at &lt;code&gt;getPageElementsFiltered&lt;/code&gt; with &lt;code&gt;locatorType=xpath&lt;/code&gt;, &lt;code&gt;locatorValue=//input&lt;/code&gt;, &lt;code&gt;includeAncestors=true&lt;/code&gt;. It gets back one JSON entry per &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; on the page, each with its ancestor path and sibling position. For the password field — second input inside the login form — the ancestor chain comes back annotated as &lt;code&gt;siblingIndex: 1, siblingCount: 2&lt;/code&gt; under &lt;code&gt;form#login&lt;/code&gt;. From that, the agent writes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;By&lt;/span&gt; &lt;span class="n"&gt;passwordField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;By&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cssSelector&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"div.container &amp;gt; form#login &amp;gt; input:nth-of-type(2)"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That selector is unique &lt;em&gt;because the tool told the agent exactly how many sibling inputs exist and where this one sits&lt;/em&gt; — not because it looked plausible. It compiles into a working &lt;code&gt;LoginPage&lt;/code&gt; method without a single round trip through your browser's DevTools.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rest of the family
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;getPageElementsFiltered&lt;/code&gt; is what you reach for once you know what you're locating. Three other tools in the same group cover the steps before and around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;getPageScripts&lt;/code&gt;&lt;/strong&gt; — every &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; on the page as JSON (&lt;code&gt;src&lt;/code&gt; for external, &lt;code&gt;content&lt;/code&gt; for inline, truncated past 10,000 characters). Handy when you're trying to understand what a page's JS is actually doing before writing a wait condition against it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;getPageStyles&lt;/code&gt;&lt;/strong&gt; — the same idea for stylesheets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;getPageElements&lt;/code&gt;&lt;/strong&gt; — the whole page as a compact JSON tree rooted at &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;, scripts/styles/comments stripped, depth-capped via &lt;code&gt;maxDepth&lt;/code&gt; (default 20). This is the "give me an overview" tool, for when you're starting a new Page Object and don't yet know the structure at all.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this matters for a test suite specifically, not just "an agent"
&lt;/h2&gt;

&lt;p&gt;A generic browser-automation agent just needs &lt;em&gt;a&lt;/em&gt; selector that works once. A test automation engineer needs one that keeps working — through refactors, through a designer swapping a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; for a &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;, through a QA lead reviewing the PR and asking "why does this selector match three things." Getting the ancestor and sibling context up front, before a selector ever gets written into a &lt;code&gt;By.cssSelector(...)&lt;/code&gt; call, is the difference between a Page Object you trust and one you'll be back in six months later, debugging the same &lt;code&gt;NoSuchElementException&lt;/code&gt; all over again.&lt;/p&gt;

&lt;p&gt;It's also just cheaper. A page with a few hundred DOM nodes routinely produces 30,000+ characters of raw HTML. Reading that into a prompt every time you need one locator is expensive in tokens and slow to iterate on. &lt;code&gt;getPageElementsFiltered&lt;/code&gt;, scoped to exactly the elements you're locating, is a fraction of that size — and it comes with the disambiguating context a raw dump never gave you in the first place.&lt;/p&gt;

&lt;p&gt;Full parameter list is on the &lt;a href="https://selenium-mcp.xpathy.uk/docs/tools" rel="noopener noreferrer"&gt;tool reference&lt;/a&gt;; the &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;repo&lt;/a&gt; has the source if you want to see how the ancestor walk is built (plain Selenium/JS underneath, nothing exotic).&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Java and Selenium Test Engineers Have Been Left Out of the AI Coding Wave. Not Anymore.</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Sat, 08 Aug 2026 11:41:23 +0000</pubDate>
      <link>https://dev.to/voltajeba/java-and-selenium-test-engineers-have-been-left-out-of-the-ai-coding-wave-not-anymore-fc7</link>
      <guid>https://dev.to/voltajeba/java-and-selenium-test-engineers-have-been-left-out-of-the-ai-coding-wave-not-anymore-fc7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick context:&lt;/strong&gt; &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;selenium-mcp&lt;/a&gt; is a Java-based &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; server that gives AI coding assistants — Claude Code, Cursor, Claude Desktop — a real Selenium WebDriver session to drive Chrome, Firefox, or Edge directly, instead of guessing at locators from pasted HTML. It's built specifically for test automation engineers working in &lt;strong&gt;Java, Selenium, and REST Assured&lt;/strong&gt;: structured element discovery for locators that are unique on the first try, Chrome DevTools Protocol tooling for network/console debugging, and a standalone REST client, all in one MCP server. Repo: &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp" rel="noopener noreferrer"&gt;github.com/Volta-Jebaprashanth/selenium-mcp&lt;/a&gt; · Docs: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;selenium-mcp.xpathy.uk&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're a test automation engineer working in Java and Selenium, you've probably already tried pointing an AI coding assistant at your test suite. Claude Code, Cursor, Copilot — pick one. They're genuinely good at scaffolding a TestNG class, writing assertions, cleaning up a Page Object Model's structure.&lt;/p&gt;

&lt;p&gt;Then you ask for the one thing you actually needed help with — "add a method to click the checkout button on this page" — and it stalls. It can't see the page. It doesn't know if that button is &lt;code&gt;#checkout-btn&lt;/code&gt;, &lt;code&gt;.checkout-button&lt;/code&gt;, or the third &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; inside a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; with no id at all. So you do what you always did before AI showed up: open DevTools yourself, inspect the element, copy the selector, paste it back into the chat so the assistant can finish writing the method.&lt;/p&gt;

&lt;p&gt;That's not AI-assisted test automation. That's you doing the automation part and the AI doing the typing.&lt;/p&gt;

&lt;p&gt;I hit this wall enough times that I built a fix for it — open a browser, inspect the actual live page, find the element itself, then write the Java that clicks it. No more being the copy-paste bridge between DevTools and your chat window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbcaeyzg2t4rku7dgjya4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbcaeyzg2t4rku7dgjya4.png" alt="sample" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap this fills
&lt;/h2&gt;

&lt;p&gt;The Node/Playwright ecosystem has had this figured out for a while. &lt;a href="https://github.com/microsoft/playwright-mcp" rel="noopener noreferrer"&gt;Playwright MCP&lt;/a&gt; lets an agent open a page and reason about it structurally instead of guessing from raw markup. If your team writes Playwright and TypeScript, you already have this.&lt;/p&gt;

&lt;p&gt;If your team writes &lt;strong&gt;Java, Selenium, TestNG or JUnit, and REST Assured&lt;/strong&gt; — which is still how most enterprise QA organizations are built, and isn't going anywhere soon — there's been nothing equivalent. I went looking before I built this, because duplicating an existing tool is a waste of everyone's time, and what I found were a handful of Selenium MCP servers, mostly in Node.js and Python, aimed at general browser-automation agents: booking a flight, scraping a page, filling out a form on someone's behalf. None of them are built around the actual day-to-day job of a test automation engineer — writing and maintaining a Java test suite, needing correct locators for a Page Object Model, needing API calls to seed and verify test data alongside the UI flow.&lt;/p&gt;

&lt;p&gt;There's an even more direct signal that this gap is real: &lt;a href="https://github.com/rest-assured/rest-assured/issues/1832" rel="noopener noreferrer"&gt;REST Assured's own GitHub repo has an open issue&lt;/a&gt; asking, essentially, "when do we get an MCP server for AI-driven API test automation?" As of writing, there isn't an official answer. The Java/Selenium/REST Assured ecosystem — the one a huge share of enterprise QA runs on — has been sitting outside the current wave of AI-assisted testing tooling almost entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  What selenium-mcp actually gives you
&lt;/h2&gt;

&lt;p&gt;At its core, it's Selenium WebDriver exposed as MCP tools: open Chrome, Firefox, or Edge, navigate, click, type, read state — all through the same locator strategies (&lt;code&gt;id&lt;/code&gt;, &lt;code&gt;css&lt;/code&gt;, &lt;code&gt;xpath&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;linkText&lt;/code&gt;, and so on) you already write by hand. Nothing exotic there. The part that actually changes your workflow is &lt;code&gt;PageSourceTools&lt;/code&gt;, and specifically &lt;code&gt;getPageElementsFiltered&lt;/code&gt; — a tool that finds every element matching a locator on the live page and hands back each one's ancestor chain and sibling position, so the agent can construct a selector that's unique on the first try instead of guessing and hitting &lt;code&gt;NoSuchElementException&lt;/code&gt; against your test target. I'll go deep on exactly how that works, with a real Page Object example, in the next piece.&lt;/p&gt;

&lt;p&gt;Past locator discovery, it covers the rest of what a real Selenium suite needs: explicit waits, alert and frame handling, window/tab management, cookies, screenshots, drag-and-drop, dropdown handling, file upload, PDF printing. It also exposes Selenium 4's Chrome DevTools Protocol support — network capture, request mocking/blocking, simulated network conditions, console log capture — useful for the kind of flaky-test diagnosis every automation engineer has lost an afternoon to. And because so much real test-suite work is API plus UI together, there's a standalone REST client built in, so an agent can help you write a REST Assured-style verification step and a Selenium UI step as part of the same test, without leaving your Java toolchain.&lt;/p&gt;

&lt;p&gt;That's &lt;strong&gt;112 tools across 16 categories&lt;/strong&gt; at last count — full reference on the &lt;a href="https://selenium-mcp.xpathy.uk/docs/tools" rel="noopener noreferrer"&gt;docs site&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it had to be Java
&lt;/h2&gt;

&lt;p&gt;This is the question I get asked most, so let me be direct: because the people who need this don't want to leave Java. Rewriting a decade of Selenium suites in Playwright and TypeScript just to get an AI coding assistant that can see the page isn't a realistic option for most enterprise QA teams, and it shouldn't have to be. &lt;code&gt;selenium-mcp&lt;/code&gt; ships as a single jar. Point Claude Code or Cursor at it alongside your existing Maven project, and the agent is driving the same WebDriver your suite already runs on — not a different automation stack bolted on next to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This is the first in a set of notes on the specific problems this solves for test automation engineers — locator discovery in depth, using the CDP network tools to debug flaky tests, combining REST Assured-style API checks with Selenium UI flows in one agent session, and the architecture decisions that keep the underlying Selenium layer usable on its own, independent of MCP, so it fits into a codebase you'd actually want to maintain.&lt;/p&gt;

&lt;p&gt;If you want to try it now: &lt;a href="https://selenium-mcp.xpathy.uk/" rel="noopener noreferrer"&gt;quickstart on the docs site&lt;/a&gt;, grab the jar, point your MCP client at it, and ask it to write a Page Object method against a real page. It's MIT-licensed, and if something's rough, &lt;a href="https://github.com/Volta-Jebaprashanth/selenium-mcp/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; — that's genuinely the fastest way to make it better.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The AI-Native Frontier: Redefining the Future of Quality Engineering</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Mon, 02 Mar 2026 06:33:23 +0000</pubDate>
      <link>https://dev.to/voltajeba/the-ai-native-frontier-redefining-the-future-of-quality-engineering-kec</link>
      <guid>https://dev.to/voltajeba/the-ai-native-frontier-redefining-the-future-of-quality-engineering-kec</guid>
      <description>&lt;p&gt;Recently, within the &lt;strong&gt;AT + GSC&amp;amp;MS&lt;/strong&gt; division at &lt;strong&gt;Sysco LABS&lt;/strong&gt;, our Quality Engineering community gathered for an event that felt less like a standard technical conference and more like a bold step into a new reality. &lt;strong&gt;QE Spark 2026&lt;/strong&gt; was a resounding success — not just as a showcase of cutting-edge technology, but as a declaration of a new strategy designed to fundamentally change how we think about scale, growth, and the role of the modern engineer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faokkz3tfa177puti72lq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faokkz3tfa177puti72lq.jpg" alt="Sysco LABS AT + GSC&amp;amp;MS QE Team " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This transformative milestone wouldn’t have been possible without the two pillars of this event: &lt;strong&gt;Sujith Thushara&lt;/strong&gt;, our Senior Manager Quality Engineering and &lt;strong&gt;Kasun de Silva&lt;/strong&gt;, our Architect — Quality Engineering. It was their coordination, leadership, and forward-thinking vision that laid the groundwork for this strategic shift. As a speaker at QE Spark 2026, I was incredibly proud to help bring their vision to life on stage and share our roadmap with an energized, forward-looking community.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncjldxs8ejipp0nax6he.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncjldxs8ejipp0nax6he.jpg" alt="Sujith Thushara" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sujith Thushara, Senior Manager Quality Engineering&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1qlmslgdur06ugkgk41.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1qlmslgdur06ugkgk41.jpg" alt="Kasun de Silva" width="799" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Kasun de Silva, Architect — Quality Engineering&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Vision: Breaking the Linear Curve
&lt;/h2&gt;

&lt;p&gt;For decades, the technology industry has operated under a predictable, yet limiting, law of physics: as business demand and revenue grow, headcount and operational costs must rise in parallel. This linear model is a hurdle to true innovation and velocity.&lt;/p&gt;

&lt;p&gt;The core strategy we unveiled at QE Spark is the creation of a &lt;strong&gt;“Growth Delta.”&lt;/strong&gt; By integrating intelligence into the very fabric of our delivery lifecycle, our goal is to empower business value to soar while keeping our operational footprint lean, agile, and efficient. We are successfully moving away from traditional, effort-based scaling and embracing intelligent growth.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3ob55yvnkkwt5mhp7jq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3ob55yvnkkwt5mhp7jq.jpg" alt="Thanya" width="799" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Journey: From AI-Assisted to AI-Native
&lt;/h2&gt;

&lt;p&gt;A major highlight of the event was outlining our concrete roadmap. We aren’t just talking about the future; we are building it. The transition from legacy methods to an entirely AI-Native ecosystem is broken down into three distinct phases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Traditional QE
&lt;/h3&gt;

&lt;p&gt;The baseline. This phase is defined by human-driven quality, heavy manual validation, and reactive defect detection.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-Assisted QE
&lt;/h3&gt;

&lt;p&gt;Our current state of the art. Here, AI tools actively enhance human effort. We are operating with an automation-first mindset, utilizing tool-enhanced test creation, and driving dramatically faster feedback cycles.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-Native QE
&lt;/h3&gt;

&lt;p&gt;The true frontier. This future state moves far beyond mere “assistance” and into a world of Digital Twins, autonomous test evolution, and real-time quality intelligence. In this phase, AI isn’t just a tool; it is a predictive partner that identifies risks and evolves tests before a developer even pushes code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28rmw035mh61pp1f8v5f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28rmw035mh61pp1f8v5f.jpg" alt="Volta Jebaprashanth" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  A Mindset Shift: The Strategic Engineer
&lt;/h2&gt;

&lt;p&gt;One of the most profound takeaways from QE Spark 2026 was that this transformation isn’t just about software — it’s about people. As we move aggressively toward an AI-Native world, the role of the engineer is getting a massive upgrade.&lt;/p&gt;

&lt;p&gt;We are successfully breaking the “Regression Bottleneck,” where engineers historically spent half their time executing tests simply because those tests existed. Instead, the future Sysco Labs engineer is a systems thinker and a quality strategist. We are shifting from merely coordinating tests to reviewing intelligent decisions, architecting solutions, and validating complex business logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ts8ykx09s7qhgbbtswa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ts8ykx09s7qhgbbtswa.jpg" alt="Akila Rangalla" width="799" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Engine Room: A Collective Force of Builders
&lt;/h2&gt;

&lt;p&gt;While the vision set on stage was ambitious, the most exciting part of this transformation is what is happening off stage. This isn’t just a top-down mandate; it is a grassroots revolution driven by our entire engineering team.&lt;/p&gt;

&lt;p&gt;Our people are in the trenches right now, turning this AI-Native vision into a tangible reality. Across the floor, teams are deeply immersed in hands-on experimentation. We are spinning up rapid prototypes, stress-testing intelligent agents, and deploying cutting-edge Proofs of Concept that challenge the status quo of Quality Engineering. There is an electric culture of innovation taking hold, where every engineer is empowered to become a builder and a disruptor. We aren’t just waiting for the future of QE to arrive — we are actively coding it into existence today.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pmmoamuss6z97c0ygji.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pmmoamuss6z97c0ygji.jpg" alt="Yaseen Mohamed" width="799" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking Ahead
&lt;/h2&gt;

&lt;p&gt;The overwhelming success of QE Spark 2026 was rooted in its clarity of purpose. By shifting from reactive detection to intelligent prevention, our team is actively clearing the path for a future where quality is a continuous, autonomous stream rather than a late-cycle hurdle.&lt;/p&gt;

&lt;p&gt;As the event concluded, the atmosphere was electric. We are no longer just asking, “How can we test this?” We are asking, “How can we do this smarter?” The journey toward an AI-Native future at Sysco Labs has officially begun, and the results promise to redefine the very boundaries of Quality Engineering.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fby96cutjt42v1vd2vp1y.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fby96cutjt42v1vd2vp1y.webp" alt="Group photo" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tharushika Rathnayake, Sachini Karunarathne, Nuwanga Arambawela, Tharindu Dias, Dinithra Thantilage, Pasan Somarathna, Iresha Wijesinghe, Thanya Withanachchi, Shanaz Nabeel, Chiran Govinnage, Akila Rangalla, Mohamed Yaseen, Sujith Thushera, Kasun De Silva, Ruzaik Refai, Dineth Mendis, Volta Jebaprashanth.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>syscolabs</category>
      <category>qualityengineering</category>
      <category>ai</category>
      <category>automation</category>
    </item>
    <item>
      <title>Raw XPath is Dead: How XPathy's Fluent API Solves Your Flaky Test Problem</title>
      <dc:creator>Volta Jebaprashanth</dc:creator>
      <pubDate>Fri, 17 Oct 2025 18:53:19 +0000</pubDate>
      <link>https://dev.to/voltajeba/raw-xpath-is-dead-how-xpathys-fluent-api-solves-your-flaky-test-problem-4h7g</link>
      <guid>https://dev.to/voltajeba/raw-xpath-is-dead-how-xpathys-fluent-api-solves-your-flaky-test-problem-4h7g</guid>
      <description>&lt;p&gt;One of the most frequent causes of flaky tests is when a front-end change inadvertently alters the casing or spacing of an HTML attribute or text content. A CSS class might change from &lt;code&gt;active&lt;/code&gt; to &lt;code&gt;Active&lt;/code&gt;, or an error message might gain an extra space: &lt;code&gt;" Error Message "&lt;/code&gt; vs. &lt;code&gt;"Error Message"&lt;/code&gt;. These minor variations are enough to break an exact-match XPath, leading to frustrating test failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;XPathy's Value Transformation feature&lt;/strong&gt; provides a fluent, built-in mechanism to address these issues. By applying transformations like case-folding and space-normalization &lt;em&gt;before&lt;/em&gt; the locator comparison, XPathy ensures your locators match the &lt;strong&gt;intended value&lt;/strong&gt;, regardless of the developer's formatting choices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92pf48fq58htyy2biwg4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92pf48fq58htyy2biwg4.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Achieving Case-Insensitive Matching
&lt;/h2&gt;

&lt;p&gt;Raw XPath requires the complex use of the &lt;code&gt;translate()&lt;/code&gt; function to achieve case-insensitivity. You must provide the entire alphabet twice: once for upper-case characters to replace, and once for the lower-case equivalents to replace them with.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Raw, Error-Prone XPath&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;//div[contains(translate(@class, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'menu-item')]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;XPathy simplifies this into a single, declarative method call using the &lt;code&gt;Case&lt;/code&gt; enum.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;.withCase(IGNORED)&lt;/code&gt; Method
&lt;/h3&gt;

&lt;p&gt;The most common transformation is to ignore case for stable attributes like &lt;code&gt;id&lt;/code&gt; or &lt;code&gt;class&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;xpathy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Case&lt;/span&gt;&lt;span class="o"&gt;.*;&lt;/span&gt;

&lt;span class="nc"&gt;XPathy&lt;/span&gt; &lt;span class="n"&gt;locator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;byAttribute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;IGNORED&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"active-tab"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Result:&lt;/span&gt;
&lt;span class="c1"&gt;//div[translate(@class, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')='active-tab']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This locator will successfully match elements with &lt;code&gt;class="active-tab"&lt;/code&gt;, &lt;code&gt;class="Active-Tab"&lt;/code&gt;, or &lt;code&gt;class="ACTIVE-TAB"&lt;/code&gt;. This small addition instantly makes the locator bulletproof against casing inconsistencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Force Casing (&lt;code&gt;UPPER&lt;/code&gt; and &lt;code&gt;LOWER&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;You can also force the element's value to a specific case before comparison, which is helpful for standardizing text content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;XPathy&lt;/span&gt; &lt;span class="n"&gt;locator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;byText&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UPPER&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"USERNAME"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Result:&lt;/span&gt;
&lt;span class="c1"&gt;//label[translate(text(), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')='USERNAME']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures the locator matches any variation of "Username," "username," or "USERNAME."&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Whitespace and Symbol Cleanup
&lt;/h2&gt;

&lt;p&gt;Inconsistent spacing in text nodes is a rampant source of locator flakiness. Similarly, needing to compare numeric values (like prices) often requires removing currency symbols.&lt;/p&gt;

&lt;h3&gt;
  
  
  Normalize Space with &lt;code&gt;.withNormalizeSpace()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The XPath &lt;code&gt;normalize-space()&lt;/code&gt; function strips leading and trailing whitespace and replaces sequences of internal whitespace with a single space. XPathy exposes this critical utility directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;XPathy&lt;/span&gt; &lt;span class="n"&gt;locator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;byText&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withNormalizeSpace&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid password"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Result:&lt;/span&gt;
&lt;span class="c1"&gt;//div[normalize-space(text())='Invalid password']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This locator will match text nodes that contain &lt;code&gt;"Invalid password"&lt;/code&gt;, &lt;code&gt;" Invalid password "&lt;/code&gt;, or even &lt;code&gt;"Invalid   password"&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filtering Characters for Consistency
&lt;/h3&gt;

&lt;p&gt;When dealing with dynamic content like prices or order IDs, you often only care about the alphanumeric parts. XPathy allows you to explicitly &lt;strong&gt;keep&lt;/strong&gt; or &lt;strong&gt;remove&lt;/strong&gt; sets of characters.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;XPathy Code&lt;/th&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Numeric Value Check&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;span.byText().withRemoveOnly(SPECIAL_CHARACTERS).contains("1999")&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Removes &lt;code&gt;$&lt;/code&gt; or &lt;code&gt;,&lt;/code&gt; to stabilize price comparison.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ID Clean-up&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;td.byText().withKeepOnly(ENGLISH_ALPHABETS, NUMBERS).equals("ORD123")&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Removes hyphens or spaces from Order IDs like &lt;code&gt;ORD-123&lt;/code&gt; before checking.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These transformations allow you to focus on the &lt;strong&gt;meaningful data&lt;/strong&gt; rather than the superficial presentation or formatting characters, making the locator invariant to regional currency or spacing differences.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Combining Transformations for Ultimate Resilience
&lt;/h2&gt;

&lt;p&gt;The true power of XPathy lies in chaining these operations to clean up a value thoroughly before comparison.&lt;/p&gt;

&lt;p&gt;Imagine a product title that might have inconsistent spacing, numbers (which should be ignored), and mixed casing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;XPathy&lt;/span&gt; &lt;span class="n"&gt;locator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;byText&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withNormalizeSpace&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withRemoveOnly&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NUMBERS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;IGNORED&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"premium feature"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Result:&lt;/span&gt;
&lt;span class="c1"&gt;//div[contains(translate(translate(normalize-space(text()), '0123456789', ''), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'premium feature')]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By stacking &lt;code&gt;.withNormalizeSpace()&lt;/code&gt;, &lt;code&gt;.withRemoveOnly()&lt;/code&gt;, and &lt;code&gt;.withCase()&lt;/code&gt;, the XPath is comprehensively cleaned up. The final result is a locator that will reliably find the element, regardless of how many formatting inconsistencies are introduced by the UI layer.&lt;/p&gt;

&lt;p&gt;These fluent transformations are the key to building locators that are truly &lt;strong&gt;bulletproof&lt;/strong&gt; against the casing, spacing, and formatting issues that plague Selenium test stability.&lt;/p&gt;

&lt;h2&gt;
  
  
  XPathy provides a lot more: Read the Full Documentation:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/volta_jebaprashanth_ac7af/xpathy-a-fluent-api-for-writing-smarter-cleaner-xpath-in-selenium-5753"&gt;https://dev.to/volta_jebaprashanth_ac7af/xpathy-a-fluent-api-for-writing-smarter-cleaner-xpath-in-selenium-5753&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Repository:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Volta-Jebaprashanth/xpathy" rel="noopener noreferrer"&gt;https://github.com/Volta-Jebaprashanth/xpathy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Testing! 🚀&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
