0

I'm trying to make a Selenium test script that checks if a bootstrap validation popover appears when submitting a form containing a bad value.

My script below returns this error:

org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#amount"}

Relevant code:

WebDriver driver = new ChromeDriver()
WebElement field = driver.findElement(By.id("amount"));  //errors here every execution
Boolean is_valid = (Boolean)WebUI.executeScript("return arguments[0].checkValidity();", field);

if (!is_valid) {
     //intentionally fail test
}

When I inspect the form field, I see the id equals amount, so why am I unable to find this element in Selenium?

enter image description here

Here's my full script:

WebUI.openBrowser('')

WebUI.navigateToUrl('Foo')

WebUI.setText(findTestObject('Object Repository/Page_bar/input_concat(Recipient, , s email address)_email'), '[email protected]')

WebUI.setText(findTestObject('Object Repository/Page_bar/input_Amount (USD)_amount'), '10001')

WebUI.click(findTestObject('Object Repository/Page_bar/button_Send Payment'))

 
WebDriver driver = new ChromeDriver() WebElement field =
driver.findElement(By.id("amount")); Boolean is_valid =
(Boolean)WebUI.executeScript("return arguments[0].checkValidity();", field);

if (!is_valid) { //intentionally fail test }

WebUI.closeBrowser()

Full HTML:

<body cz-shortcut-listen="true">
    <div id="__nuxt"><!----><div id="__layout"><div data-v-f1473ce4=""><header data-v-7ea66436="" data-v-f1473ce4="" class="sr-header"><div data-v-7ea66436="" class="custom-container"><div data-v-7ea66436="" class="header-wrap"><div data-v-7ea66436="" class="row"><div data-v-7ea66436="" class="col-6"><div data-v-7ea66436="" class="header-left d-flex align-items-center"><span data-v-7ea66436="" class="d-block d-md-none mobile-menu-trigger"><i data-v-7ea66436="" class="fa-solid fa-bars"></i></span> <a data-v-7ea66436="" href="/" class="nuxt-link-active"><img data-v-7ea66436="" src="/images/logo-icon.png" alt="" class="sr-logo"></a> <div data-v-7ea66436="" class="user-portal d-none d-md-block"><ul data-v-7ea66436="" class="sr-nav nav"><li data-v-7ea66436=""><a data-v-7ea66436="" href="/" class="active nuxt-link-active">Dashboard</a></li></ul></div></div></div> <div data-v-7ea66436="" class="col-6"><div data-v-7ea66436="" class="sr-user-profile position-relative d-flex justify-content-end align-items-center h-100"><span data-v-7ea66436="" class="position-relative notification-icon"><!----> <img data-v-7ea66436="" src="/images/bxs-bell.svg" alt=""></span> <ul data-v-7ea66436="" class="snapr-notification"><li data-v-7ea66436="" class="d-flex align-items-center justify-content-between"><p data-v-7ea66436="">You have no unseen notifications</p></li></ul> <div data-v-7ea66436="" class="sr-profile clearfix"><img data-v-7ea66436="" src="https://storage.googleapis.com/snapr-dev.appspot.com/images/aXmr0zJOqqhOTBpPenxgerP3CNH3.jfif" alt="" class="avatar"> <a data-v-7ea66436="" href="/" class="d-none d-md-inline-block nuxt-link-active">Mark</a> <ul data-v-7ea66436="" class="sr__profile-links"><li data-v-7ea66436=""><a data-v-7ea66436="" href="/profile" class="">Settings</a></li> <li data-v-7ea66436=""><a data-v-7ea66436="" href="javascript:void(0)">Logout</a></li></ul></div></div></div></div></div></div></header> <main data-v-f1473ce4="" class="sr__main-body"><div data-v-f1473ce4="" class="custom-container"><h2 data-v-f1473ce4="" class="text-white mb-1">Welcome, Test Biz</h2> <p data-v-f1473ce4="" class="mb-4 mb-md-0">SnapRefund is fast, simple, and secure</p> <div data-v-f1473ce4="" class="body-wrapper clearfix"><div data-v-f00dedfc="" data-v-f1473ce4="" class="d-flex flex-wrap sr__profile-tabs mb-xl-5 justify-content-center"><a data-v-f00dedfc="" href="javascript:void(0)" class="closePosition closeBtn"><i data-v-f00dedfc="" class="fa fa-close fa-2x" aria-hidden="true"></i></a> <a data-v-f00dedfc="" href="/send-payment" aria-current="page" class="sr__tab nuxt-link-exact-active nuxt-link-active"><div data-v-f00dedfc="" class="d-flex align-items-center"><span data-v-f00dedfc="" class="icon-box"><img data-v-f00dedfc="" src="/images/ionic-ios-send.svg" alt=""></span> <span data-v-f00dedfc="" class="sr__tab-title">Send <br data-v-f00dedfc=""> Payment</span></div></a> <a data-v-f00dedfc="" href="/pending-payment" class="sr__tab"><div data-v-f00dedfc="" class="d-flex align-items-center"><span data-v-f00dedfc="" class="icon-box"><img data-v-f00dedfc="" src="/images/open-reload.svg" alt=""></span> <span data-v-f00dedfc="" class="sr__tab-title">Pending <br data-v-f00dedfc="">Payments</span></div></a> <a data-v-f00dedfc="" href="/transactions" class="sr__tab"><div data-v-f00dedfc="" class="d-flex align-items-center"><span data-v-f00dedfc="" class="icon-box"><img data-v-f00dedfc="" src="/images/ionic-ios-paper.svg" alt=""></span> <span data-v-f00dedfc="" class="sr__tab-title">Transaction <br data-v-f00dedfc="">History</span></div></a> <a data-v-f00dedfc="" href="/bank-card" class="sr__tab"><div data-v-f00dedfc="" class="d-flex align-items-center"><span data-v-f00dedfc="" class="icon-box"><img data-v-f00dedfc="" src="/images/ionic-ios-card.svg" alt=""></span> <span data-v-f00dedfc="" class="sr__tab-title">Banks &amp;<br data-v-f00dedfc="">Cards</span></div></a> <a data-v-f00dedfc="" href="/my-wallet" class="sr__tab"><div data-v-f00dedfc="" class="d-flex align-items-center"><span data-v-f00dedfc="" class="icon-box"><img data-v-f00dedfc="" src="/images/ionic-ios-wallet.svg" alt=""></span> <span data-v-f00dedfc="" class="sr__tab-title">Wallet</span></div></a> <a data-v-f00dedfc="" href="/my-preference" class="sr__tab"><div data-v-f00dedfc="" class="d-flex align-items-center"><span data-v-f00dedfc="" class="icon-box"><img data-v-f00dedfc="" src="/images/ionic-ios-settings.svg" alt=""></span> <span data-v-f00dedfc="" class="sr__tab-title">Preferences</span></div></a></div> <div data-v-f1473ce4="" class="body-content"><div data-v-f1473ce4="" class="row"><div data-v-f896e768="" data-v-f1473ce4="" class="col-xl-6 offset-xl-3 px-xl-5"><div data-v-f896e768="" class="sr__send-payment-card sr__card"><h2 data-v-f896e768="" class="text-white text-center">Send a Payment</h2> <p data-v-f896e768="" class="text-center mb-5">Fast. Simple. Secure.</p> <form data-v-f896e768=""><div data-v-f896e768="" class="mb-4"><label data-v-f896e768="" for="email" class="d-block">Recipient's email address</label> <input data-v-f896e768="" type="text" id="email" placeholder="[email protected]" name="email" required="required" class="d-block w-100"></div> <div data-v-f896e768="" class="mb-5"><label data-v-f896e768="" for="amount" class="d-block">Amount (USD)</label> <div data-v-f896e768="" class="position-relative adjust-dollar-sign"><input data-v-f896e768="" type="number" id="amount" placeholder="0.00" step=".01" min="0" max="10000" name="amount" required="required" class="d-block w-100"> <i data-v-f896e768="" class="fa-solid fa-dollar-sign"></i></div></div> <div data-v-f896e768="" class="d-flex justify-content-center"><button data-v-f896e768="" type="submit" class="sr__button me-3">Send Payment</button></div></form></div></div></div></div></div></div></main></div></div></div><script>window.__NUXT__=function(t){return{staticAssetsBase:"/_nuxt/static/1645950364",layout:"default",error:t,state:t,serverRendered:!1,routePath:"/",config:{_app:{basePath:"/",assetsPath:"/_nuxt/",cdnURL:t}}}}(null)</script><script src="/_nuxt/aee8d4c.js" defer=""></script><script src="/_nuxt/31db832.js" defer=""></script><script src="/_nuxt/b069f1c.js" defer=""></script><script src="/_nuxt/b379d09.js" defer=""></script>
  

<div id="ryq5aiihF" role="status" aria-live="polite" aria-atomic="false" class="toasted-container top-right fit-to-screen"></div></body>

Related Question: How to get the text from the HTML5 input field error message in Selenium?

3
  • What website url is this? I am assuming it looks for the element prior to it popping up. Commented Feb 27, 2022 at 4:16
  • it is created dynamically and added to dom content later. therefore you have to request popover with timeout or equivalent something Commented Feb 27, 2022 at 8:36
  • Does this answer your question? How to handle HTML constraint validation pop-up using Selenium? Commented Nov 23, 2022 at 14:30

2 Answers 2

1

The popover is the HTML5 Constraint validation message which is the outcome of Constraint API's element.setCustomValidity() method.

To retrieve the text Value must be less than or equal to 10000. you need to induce WebDriverWait for the elementToBeClickable() and you can use either of the locator strategies:

  • Using cssSelector:

    WebElement amount = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("input#amount[name='amount']")));
    System.out.println(amount.getAttribute("validationMessage"));
    
  • Using xpath:

    WebElement amount = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//input[@id='amount' and @name='amount']")));
    System.out.println(amount.getAttribute("validationMessage"));
    

As it is a <label> element as an alternative you can also try the following locator strategies:

  • Using cssSelector:

    WebElement amount = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("label[for='amount']")));
    System.out.println(amount.getAttribute("validationMessage"));
    
  • Using xpath:

    WebElement amount = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//label[@for='amount']")));
    System.out.println(amount.getAttribute("validationMessage"));
    

Instead you can also try for the visibilityOfElementLocated() as follows:

  • Using cssSelector:

    WebElement amount = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("label[for='amount']")));
    System.out.println(amount.getAttribute("validationMessage"));
    
  • Using xpath:

    WebElement amount = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//label[@for='amount']")));
    System.out.println(amount.getAttribute("validationMessage"));
    

References

You can find a couple of relevant detailed discussion in:

Sign up to request clarification or add additional context in comments.

13 Comments

Hm this is a good approach it seems, but the 20s timeout is being hit and i'm seeing the error Expected condition failed: waiting for element to be clickable: By.cssSelector: input#amount[name='amount'] (tried for 20 second(s) with 500 milliseconds interval). Should we be waiting for the amount field to be clickable rather than wait for the popover? I need to check if the validation message is displayed at all but this code would print the value of the message. What would be the correct way to validate whether or not the message is present? WebUI.verifyTextPresent(amount, false) ?
How about the xpath? Are you able to send any text within the Amount field?
Yes, I can send text to the amount field fine with my script in Katalon using WebUI.setText(findTestObject('Object Repository/Page_SnapRefund/input_Amount (USD)_amount'), '10001'). The problem i'm having is I can't programmattically verify the popover is displaying after the text has been entered. I tried with Xpath instead of CSS and got a similar error that the element can't be found: no such element: Unable to locate element: {"method":"xpath","selector":"//input[@id='amount' and @name='amount']"}
Did you apply the wait?
Checkout the answer update and let me know the status.
|
0

According to the code you presenting in the question you are trying to access a web element before even opening the web page you are trying to work on.
In case you just omitted driver.get(the_page_url) and the code filling and submitting the form the error here may be caused by several causes:

  1. You are missing a delay. You can not locate the pop-up immediately after clicking the submit button, it takes some short time for pop-up to appear. The preferred approach here is to use Expected Conditions explicit waits, something like this:
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement field = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("amount")));
  1. The elements you are trying to access are inside an iframe.
    In this case you will have to switch into that iframe first in order to access elements inside it, as following:
driver.switchTo().frame(driver.findElement(By.id(the_iframe_id)));

and then continue with

WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement field = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("amount")));

To give you better answer we have to see the page you are working on, to see all your actual code and to debug what actually happens there.

7 Comments

I did indeed omit the part of the script where I open the browser and fill a value into the amount field. I'm just using a bootstrap form as the screenshot shows, I don't think that involves an iFrame (i could be wrong). The field (amount) is an <input> that is likely shadowed by the parent <div data-v-f896e768>, but since it doesn't have an id how can I switch into it? I tried using the full xpath for the amount field I pulled from the inspector, but it isnt foundWebUI.mouseOver(TestObjectHelper.getTestObjectWithXpath("/html/body/div[1]/div/div/header/div/div/div/div[2]/div/div"))
In selenium you need to switch into iframes and shadow DOMs only. I'm afraid we need more details here to help you.
Got it. What details should I provide? My entire page html?
Preferably the link, if not possible - the entire page HTML if possible and all your code if possible
No worries. I added the html to my question if you're interested later. All good, thank you for your suggestions!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.