I have submit button, which is only one on the page, and it's in form.
html part:
<form class="search-form ng-touched ng-dirty ng-valid" novalidate="" style="" xpath="1">
<div class="row">...</div>
<div class="row">...</div>
<div class="row">...</div>
<div class="form__actions" xpath="1">
<div class="form__buttons">
<!---->
<div class="btn__wrapper">
<button class="btn btn__primary" type="submit">
Select My Car
</button>
</div>
</div>
</div>
</form>
So, I'm taking xpath:
//button[#type='submit']
I'm successfully pressing it via submit() (let me skip WebDriver init, its fine):
WebElement searchButton = driver.findElement(By.xpath("//button[#type='submit']"));
searchButton.submit();
(and some search performs)
But when I'm trying to press it via click()
WebElement searchButton = driver.findElement(By.xpath("//button[#type='submit']"));
searchButton.click();
it's not pressed in browser which is launched, and same time Junit test is green (not test, but just pressing button):
#Test
public void test() {
WebElement button = driver.findElement(By.xpath("//button[#type='submit']"));
button.click();
}
Can please someone explain, why submit() successfully presses button in such case, but click() - no. And I do not understand, why "test" is green, when we are trying to click(), but it was not performed, if looking on browser launched by driver.
UPDATED:
I tried
WebElement button = driver.findElement(By.xpath("//button[#type='submit']"));
if (button.isEnabled()) {
button.click();
}
and
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(button)).click();
but still the same - submit() works fine, click() - does not.
The method object.submit() is there for submitting the form to the server. It has another advantage, in case if you're not able to locate the "submit" button then you can take any object of the form and trigger submit() function.
It seems in searchButton.submit(); searchButton is an element of the form and the submit action on it triggers submission of form on server.
Now, why searchButton.click(); not working here could have following reasons.
The button is visible but not enabled.
Driver is finding the 2
instances of searchButton element.
Suggestion: Evaluate following code and check it returns more than one element. If it does then you're clicking on the wrong instance.
List<WebElements> e = driver.findElements(By.xpath("//button[#type='submit']"));
Also try,
driver.findElement(By.xpath(".//button[#class='btn btn__primary'][#type='submit']")).click()
http://docs.seleniumhq.org/docs/03_webdriver.jsp#user-input-filling-in-forms
submit()
submit() method is defined as :
void submit()
Throws:
NoSuchElementException - If the given element is not within a form
As per the JavaDocs when you invoke submit() on an WebElement, if this current element is a form, or an element within a form, then this will be submitted to the remote server. If this causes the current page to change, then this method will block until the new page is loaded.
click()
click() method is defined as :
void click()
Throws:
StaleElementReferenceException - If the element no longer exists as initially define
As per the JavaDocs when you invoke click() on an WebElement and if this causes a new page to load, you should discard all references to this element and any further operations performed on this element will throw a StaleElementReferenceException. Note that if click() is done by sending a native event (which is the default on most browsers/platforms) then the method will not wait for the next page to load and the caller should verify that themselves. There are some ExpectedConditions for an element to be clicked. The element must be visible and it must have a height and width greater then 0.
Your Usecase :
In your usecase, the target WebElement //button[#type='submit'] is within a <form> tag. You are able to successfully press it via submit() as it blocks the method untill the new page is loaded completely as a result of submission on the previous page. Hence the following works :
WebElement searchButton = driver.findElement(By.xpath("//button[#type='submit']"));
searchButton.submit();
But when you try click() method as below, click() being a native event doesn't waits for the new page to load completely. Hence invoking click() method fails.
WebElement button = driver.findElement(By.xpath("//button[#type='submit']"));
button.click();
Your Code Trials :
Validating the button.isEnabled() condition won't fetch us the required result if the element is clickable or not as isEnabled() validates Is the element currently enabled or not? This will generally return true for everything leaving out the disabled input elements. But necessarily isEnabled() wouldn't be validating if the WebElement is visible, interactable and clickable or not.
Solution :
As per the details provided, the solution to invoke click() method would be to induce WebDriverWait with ExpectedConditions clause set to elementToBeClickable as below :
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//button[#type='submit']"))).click();
Update :
Best Practice :
As per the updated HTML and your subsequent comment where you mentioned about Angular4 being used in your app, a much more effective way would be to construct the xpath mocking the HTML DOM as follows :
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//form[#class='search-form ng-touched ng-dirty ng-valid']//button[#class='btn btn__primary' and #type='submit']"))).click();
Related
I'm experiencing a StaleElementReferenceExpection that seems beyond all reason in an application. It involves absolutely no refreshing or reloading of the page, but just two consecutive actions of accessing the element - one click and one assertion that the element is not selected.
Java/Selenium code:
this.element.findElement(By.cssSelector("input[type='checkbox']")).sendKeys(Keys.SPACE);
(SPACE is used because when usng click, Selenium claims "ElementClickInterceptedExcpetion - other element would receive the click")
assertThat(this.element.findElement(By.cssSelector("input[type='checkbox']")).isSelected()).isFalse();
This results in:
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
even when I use brake points int the code, and skip slowly through each step.
Markup:
<div class="hb-cell hb-cell--autoWidth">
<input tusenskilletegn="" id="utgift-2-belop">
<input type="checkbox" id="utgift-2-inkludert">
<div class="hb-label>
<label class="hb-label-tekst" for="utgift-2-inkludert"></label>
</div>
</div>
Also tried accessing the for" in the label, with no luck: (using partial match, in this example)
this.element.findElement(By.cssSelector("label[for$=-inkludert]")).click();
It results in
org.openqa.selenium.ElementNotInteractableException: element not interactable
Any ideas? Selenium seems to have become impossible for me to use lately, with this type of error occuring all "over the place".
If you have issues with the click() function you could always just click it using JS
public void clickWebElementUsingJS(WebElement element) {
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].click();", element);
}
As for the StaleElementReferenceExpection instead of adding an arbitrary Thread.sleep you could just write a little helper method using ExpectedConditions to click it and wait for the element to go stale, then just find the element again.
private WebElement clickCheckBoxAndWaitToGoStale() {
final By byCSS = By.cssSelector("input#utgift-2-inkludert");
// find the element
WebElement checkbox = this.element.findElement(byCSS);
// click it
clickWebElementUsingJS(checkbox ); // or sendKeys(Keys.SPACE) if this doesn't work or you just prefer it
// wait for the WebElement variable to go stale
try {
new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(5))
.pollingEvery(Duration.ofSeconds(1))
.ignoring(StaleElementReferenceException.class)
.ignoring(NullPointerException.class)
.until(ExpectedConditions.invisibilityOf(element));
} catch (WebDriverException e) {
// log
}
// re-find and return the checkbox to run the assert on
return this.element.findElement(byCSS);
}
Unable to click on webelement button
I tried to click on button by mouse movement but no success
my outer html is as below :
<button class="btn btn-alt btn-small" type="button" ng-click="ecdapp.uploadBlueprintModalPopup();">
Create
</button>
button xpath is:
//*[#id="page-content"]/div[3]/button
Not seeing the full page source it's hard to tell where your XPath expression is good or not, you can try locating the button using its text instead
//button[normalize-space(text())='Create']
the normalize-space() function is used to discard heading/trailing whitespaces
It might also be the case the button is not immediately available, I would recommend considering using Explicit Wait approach via WebDriverWait class
WebElement myButton = new WebDriverWait(driver, 10)
.until(ExpectedConditions
.elementToBeClickable(By.xpath("//button[normalize-space(text())='Create']")));
myButton.click();
the above code will try to locate the aforementioned button for 10 seconds and click it as soon as it will be present/visible/clickable. Otherwise it will fail with NoSuchElementException
May be the Xpath is wrong. Try the below xpath:
//button[contains(text(),'Create')]
As you can see on the screenshot this Xpath 100% works, if you still won't be able to click on that button, then problem is not with xpath. Let me know if its still fails.
By.xpath("//button[#class = 'btn btn-alt btn-small' and #type = 'button']")
Based on your comment:
I tried this code , but unable to click . element click intercepted: Element ... is not clickable at point (293, 97). Other element would receive the click: ... (Session info: chrome=74.0.3729.169)
I pretty sure I know whats your problem, before u click on this element, something going on the page:
It says - Other element would receive the click, means there is other element above(overlapping) your button(pop up window, page is greyed out(disabled while loading, Some JS running)), so when Selenium trying to click on your button its actually clicking on that blocking element.
Try to click after Thread.Sleep(); wait 5-10 sec.
If this is the case then u need to add condition before find your button to check that element that prevent from clicking on button is disappeared then u click on it.
Try JavaScript executors as below,
WebElement element = driver.findElement(By.xpath("<xpath of button>"));
JavascriptExecutor js= (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();", element);
I am not able to click on the submit button inside the modal. It only works sometimes - it's not stable.
Below is my HTML element:
<button id="submit-btn" name="submit" data-dismiss="modal" type="submit" class="btn btn-info btn-sm submit projectSaveBtn">Submit</button>
Here I'm using id for locating the element, but I'm not able to click on the submit button inside the modal.
My Java code:
WebElement element1 = driver.findElement(By.id("submit-btn"));
Actions actions = new Actions(driver);
actions.moveToElement(element1).build().perform();
wait.until(ExpectedConditions.elementToBeClickable(element1)).click();
When we use the action class, selenium takes mouse and keyboard controls. If we interact with mouse or keyboard at the time of test execution (specially the actions statement execution), it may fail some times.
You can try with actions class and don't interact until it completes the test execution. it may solve your issue.
Instead of using the id attribute you can use an xpath as follows :
WebElement element1 = driver.findElement(By.xpath("//button[#id='submit-btn']"));
element1.click();
or
WebElement element2 = driver.findElement(By.xpath("//button[#class='btn btn-info btn-sm submit projectSaveBtn' and #id='submit-btn']"));
element2.click();
If it's a windows modal dialog box, you might want to first switchTo() to the modal and then perform accept() on it.
driver.switchTo().alert().accept();
driver.switchTo().window("");
I solved the issue, it was timing issue .Modal was opened before the page loaded properly so giving the time before clicking/opening modal solves the issue .
Here is my code -->
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement add = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.btn.projectAddBtn")));
add.click();
This solved my issue.Thank you all for the support :-)
I am trying to click a calendar from the following website using Selenium with Java (3.3.0 and java version "1.8.0_66").
https://www.cathaypacific.com/cx/en_US.html
Target to be clicked - Flights - One Way - 'Departing On' button
No matter, what possible options I tried - by.id, by.xpath and Actions, EventFiringMouse etc., this button does not get clicked at all.
"<div class="button-date-picker-wrapper field-group cx-inputfield">
<span class="field-label input-filled" aria-hidden="true">Departing on</span>
<button id="dppju1sm" class="button-date-picker field-button from-button has-dates input-filled" role="link" type="button" data-ui-overlay-shared="true" data-ui-overlay-id="trip-dates-picker" aria-expanded="false" aria-label="Departing on Thursday 20 April 2017">
</div>"
private static void pickFlightCode() throws InterruptedException {
WebElement element = driver.findElement(By.xpath("//div[1]/button[starts-with(#id,'dp')]"));
//wdwait.until(ExpectedConditions.elementToBeClickable(element));
Actions actions=new Actions(driver);
actions.moveToElement(element).moveToElement(driver.findElement(By.xpath("//div[1]/button[starts-with(#id,'dp')]"))).click().build().perform();
element = driver.findElement(By.xpath("//div[1]/button[starts-with(#id,'dp')]"));
System.out.println(element.getAttribute("aria-hidden"));
}
(or)
driver.findElement(By.xpath("//div[1]/button[starts-with(#id,'dp')]")).click();
String js = "document.getElementById("field-label").style.display = "block";';
arguments[0].style.visibility='visible';";
The above code does not work and I am getting 'Element Not Visible' Exception.
Driver.findElement - isEnabled returns true and Driver.findElement - isDisplayed returns false.
Is this something to do with the 'aria-hidden'=true attribute in span? How should we handle 'aria-hidden' and click on the button?
In order to reach to the required control, you can make use of its container. Hence, try following:
//div[#data-date-picker-id='book-trip']//button[starts-with(#id,'dp') and starts-with(#aria-label, 'Departing on ')]
Let me know, whether it works for you.
Try this for the button's xpath -
//div[#class = 'dates-picker-wrapper splited-date-picker flight-datepicker']/div[1]/button
I have checked this in Firefox and it working for me.
Try this JavaScript code to enable visibility of selected element.
WebElement element = driver.findElement(By.xpath("Element Xpath"));
String js = "arguments[0].style.height='auto'; arguments[0].style.visibility='visible';";
((JavascriptExecutor) driver).executeScript(js, elem);
I am trying to press the "grid" class button that is on a web page but I am having trouble. Here is the HTML:
<li id="prodlist" class="prodtab">
<span> Products</span>
<div class="grid" onclick="goToView('productGrid');"></div>
<div class="list" onclick="goToView('productList')"></div>
</li>
Here is what I tried but it gives org.openqa.selenium.NoSuchElementException:
driver.findElement(By.xpath("div[contains(#class, 'grid')]")).click();
The solution to this kind of problems is usually either switch to an iframe, if the element is inside it:
WebElement frame = driver.findElement(by.cssSelector("iframe.ajaxStoreNumberAppendSrc"));
driver.switchTo().frame(frame);
// then, search for element
driver.findElement(By.xpath("//div[contains(#class, 'grid')]")).click();
Or, make an explicit wait to wait for element to become present:
WebDriverWait wait = new WebDriverWait(webDriver, 5);
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//div[contains(#class, 'grid')]")));