public void privateCohortCreation() {
if(webElements.newCohortElm.isDisplayed()) {
SeleniumUtils.click(getDriver(),webElements.createCohortSelectionFromMenu);
webElements.cohortname.sendKeys("private_cohort_test");
SeleniumUtils.click(getDriver(),webElements.createCohortButton);
}
else {
doApply();
}
}
I want that if the element is displayed then perform the task else call doApply() method. But this is giving an exception
"no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/app-root/div/app-container/app-indv301/app-global-filters/div/ul/li[3]/app-cohort/div/div/app-status/div"} (Session info: chrome=70.0.3538.77)"
You can use findElements() to check whether the element is on the webpage.
findElements() - returns empty list if there is no element with given locator
findElement() - throws NoSuchElementException if element is not on the page
Try below code:
List<WebElement> elements = driver.findElements(By.locator);
if(!elements.isEmpty()) {
if(elements.get(0).isDisplayed()) {
elements.get(0).click();
}
else {
// element not visible
}
}else{
// here mention code if element not present
}
Recommendation : Use relative xpath instead of absolute xpath. or try CSS selector instead.
Try using try catch instead of if else.
try {
if (webElements.newCohortElm.isDisplayed()) {
doApply();
}
}
catch (Exception e){
SeleniumUtils.click(getDriver(), webElements.createCohortSelectionFromMenu);
webElements.cohortname.sendKeys("private_cohort_test");
SeleniumUtils.click(getDriver(), webElements.createCohortButton);
}
Related
I have a test for Selenide:
#Test
public void Test(){
open("https://market.yandex.ru/catalog--smartfony/54726/list?hid=91491&glfilter=7893318%3A153043&glfilter=4940921%3A13475069&onstock=1&local-offers-first=0");
new AfterPhonesCategory()
.collectResults();
}
I have a methods which get the product names and return the selenide elements, when the product runs out, we go to the next page and also get the elements again until they run out:
public class AfterPhonesCategory {
public List<String> collectResultsFromPage() {
List<SelenideElement> resultsNameWebElement = $$x("//article//h3[#data-zone-name = 'title']//span");
Assertions.assertTrue(resultsNameWebElement.stream().anyMatch(x->x.getText().contains("Apple")),
"the snippet does not contain the name of the apple");
return resultsNameWebElement.stream() //line 34
.map(SelenideElement::getText)
.collect(Collectors.toList());
}
private boolean initNextPageButton() {
List<SelenideElement> goNextPageButton = $$x("//a[contains(#class, '_3OFYT')]");
if(goNextPageButton.size() > 0){
goNextPageButton.get(0).click();
return true;
}
else
return false;
}
private List<String> findResults;
public AfterPhonesCategory collectResults() {
findResults = collectResultsFromPage();
while (initNextPageButton()) { //line 52
findResults.addAll(collectResultsFromPage());
}
return this;
}
but when executing the code I get an error:
Caused by: org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
at pages.AfterPhonesCategory.collectResultsFromPage(AfterPhonesCategory.java:34)
at pages.AfterPhonesCategory.collectResults(AfterPhonesCategory.java:52)
What am I doing wrong?
StaleElementReferenceException will be occurs only when your element is not present(vanished or not constructed till) in your website. please add wait conditions to check the visiblity of the element.
By optionXpath = By.xpath("your xpath fp goes here !");
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(optionXpath));
wait.until(ExpectedConditions.visibilityOfElementLocated(optionXpath));
driver.findElement(optionXpath).click();
In case of not constructed :
you need to add wait conditions
In case of vanished :
yours actions on element is wrong. add screenshot just before your failure code and
recheck your code.
Element is not present on the page!
here is the code:
try {
if (driver.findElement(By.xpath("(//*[text()='Duplicate Saved Filter'])")).isDisplayed()) {
driver.findElement(By.xpath("(//*[text()=' Yes '])")).click();
Thread.sleep(2000);
}} catch (NoSuchElementException e) {
logger.info("element not found");
}
What you want:
click on Yes if element is present and visible
otherwise log something, without error throwing
The trick here is to use findElementS (notice the S). This gives a list of found elements, if 0 than there is no element (prevents the error throwing).
If there is an element, check if it is displayed.
From your comment I guess you tried to use findElementS but forgot to add the .size() > 0 check.
List<WebElement> elements = driver.findElements(By.xpath("(//*[text()='Duplicate Saved Filter'])"));
if(elements.size() == 0) {
logger.info("element not found");
} else if(!elements[0].Displayed())) {
logger.info("element not visisble");
} else {
driver.findElement(By.xpath("(//*[text()=' Yes '])")).click();
Thread.sleep(2000);
}
Long story short - I have a button that doesn't have ID's and has a compound class( So selenium hates it / cant find it). So I use the XPath selector for it that works great
driver.findElement(By.xpath("//input[#value='Continue to Payment']")).click()
But the button changes depending on the language being used.
So at the moment, I have
if (driver.findElement(By.xpath("//input[#value='Continue to Payment']")).isDisplayed()){
driver.findElement(By.xpath("//input[#value='Continue to Payment']")).click();
}
else if (driver.findElement(By.xpath("//input[#value='Paiement']")).isDisplayed()){
driver.findElement(By.xpath("//input[#value='Paiement']")).click();
}
else if ( same thing as above but for another language)
But when Selenium errors out after going through the first if statement with:
no such element: Unable to locate element:{"method":"xpath","selector":"//a[contains(text(),'Checkout')]"}
I know the element is not there.. so I dont want it to do anything & move on to the next if else statement.
What am I missing here?
try {
if (driver.findElement(By.xpath("//input[#value='Continue to Payment']")).isDisplayed()){
driver.findElement(By.xpath("//input[#value='Continue to Payment']")).click();
}
else if (driver.findElement(By.xpath("//input[#value='Paiement']")).isDisplayed()){
driver.findElement(By.xpath("//input[#value='Paiement']")).click();
}
else
System.out.println("Button not found");
} catch(NoSuchElementException | StaleElementReferenceException e) {
System.out.println("Impossible to click the pop-up. Reason: " + e.toString());
}
Try above solution, Hopefully it will work for you. In your example wrong code has been written for else if (driver.findElement(By.xpath("//input[#value='Paiement']")).isDisplayed).
You can use separate short methods to achieve expected results and log errors.
public WebElement getElement(WebDriver driver, String XPATH, int timeoutInSeconds){
WebElement elem = null;
try{
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
elem = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(XPATH));
} catch (Exception e){
// log or print error.
}
return elem;
}
You can then call it like
WebElement e = getElement(driver, "//input[#value='Continue to Payment']", 10);
if (e != null) {
e.click();
} else {
e = getElement(driver, "//input[#value='Paiement']", 5);
if (e != null) {
e.click();
} /// and so on....
}
This way you can adjust the wait time for each element and also not fall into errors if any one element is missing because of language.
I have to wait for an element to appear and then click on it. Here is the code I tried and getting the NoSuchElementException.
I have 300 seconds to wait for the element, but it is trying to find the element:
tpo.fwOptimizationTestResults() without waiting for 300 seconds
WebElement fwResults = (new WebDriverWait(driver, 300))
.until(ExpectedConditions.elementToBeClickable(tpo.fwOptimizationTestResults()));
public WebElement fwOptimizationTestResults() {
//return driver.findElement(By.xpath("//*[#class='table table-condensed table-bordered']"));
return driver.findElement(By.xpath("//table[contains(#class, 'table-condensed')]"));
}
Error:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//table[contains(#class, 'table-condensed')]"}
(Session info: chrome=75.0.3770.80)
The exception is not from elementToBeClickable, it's from fwOptimizationTestResults. You are using driver.findElement() which throws the exception and evaluates before the expected condition.
There are two overloads, elementToBeClickable(WebElement) and elementToBeClickable(By), you should use the second one
WebElement fwResults = (new WebDriverWait(driver, 300)).until(ExpectedConditions.elementToBeClickable(By.xpath("//table[contains(#class, 'table-condensed')]")));
You might want to amend your code to add ignoring stanza to the WebDriverWait
so it won't fail on NPEs:
WebElement fwResults = (new WebDriverWait(driver, 5))
.ignoring(NullPointerException.class)
.until(ExpectedConditions.elementToBeClickable(tpo.fwOptimizationTestResults()));
and in its turn put your WebElement function inside the try block and instead of throwing an exception - return null in case if element is not found:
public WebElement fwOptimizationTestResults() {
try {
return driver.findElement(By.xpath("//table[contains(#class, 'table-condensed')]"));
} catch (NoSuchElementException ex) {
return null;
}
}
More information:
FluentWait
How to use Selenium to test web applications using AJAX technology
I am trying to get the id of an element which starts with 'u_' and ends with '_5' and in between data changes alphabetically.So, sometimes i see 'u_d_5' and sometime 'u_6_5' . In that case, how would get the dynamic id?
I know there are some methods like starts-with or ends-with but they aren't working at all for me. Could anyone please suggest me some idea in this?
code snippet:
WebElement cls=ff.findElement(By.xpath("//*[#id='u_6_5']"));
whole code:
String s=System.getProperty("user.dir");
System.setProperty("webdriver.chrome.driver", s+"\\ChromeDriver\\chromedriver.exe");
ChromeDriver ff=new ChromeDriver();
try{
ff.manage().window().maximize();
ReadfrmExcel rd=new ReadfrmExcel();//reading data
String[][] readata=rd.excelRead();
for(int i=1; i<readata.length; i++)
{
ff.get("http://www.facebook.com");
Thread.sleep(1000);
ff.findElementByXPath("//*[#id='email']").sendKeys(readata[i][0]);
ff.findElementByXPath("//*[#id='pass']").sendKeys(readata[i][1]);
ff.findElement(By.id("u_0_v")).click();
System.out.println("Waiting for element to appear");
Thread.sleep(3000);
WebElement element=ff.findElement(By.id("userNavigationLabel"));
element.click();
System.out.println("Clicked drop down");
//ff.findElementByXPath("//*[#id='userNavigationLabel']").click();
System.out.println("sleeping 5 secs");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
WebElement cls=ff.findElement(By.xpath("//*[starts-with(#id,'u_') and ends-with(#id, '_5']"));
boolean vis=cls.isDisplayed();
System.out.println(vis);
Thread.sleep(8000);
System.out.println("Sleeping 8 secs");
cls.click();
System.out.println("After clicking");
System.out.println("Successfully logged out!!");
//ff.close();
ff.close();
}
}
catch(Exception e){
System.out.println(e);
}
you can use xpath's starts-with and ends-with methods:
WebElement cls=ff.findElement(By.xpath("//*[starts-with(#id,'u_') and ends-with(#id, '_5')]"));
if this is not working, your browser might only support xpath 1.0 (see this answer for details) -> then you can only use starts-with
WebElement cls=ff.findElement(By.xpath("//*[starts-with(#id,'u_')]"));
if you definitely need to check the end of the id, then you can try the following xpath instead:
//*[starts-with(#id, 'u_') and substring(#id, string-length(#id) - 1) = '_5']
I have tried to get all ids, which i have to use.
First get the tag name in which your id attribute has been defined.
java.util.List links = ff.findElements(By.tagName("span"));
ArrayList arrList = new ArrayList();
for (int i = 0;i < links.size();i++){
if(links.get(i).getAttribute("id").startsWith("u_") &&
links.get(i).getAttribute("id").endsWith("_5")){
arrList.add(links.get(i).getAttribute("id"));
}
}
Now you will find all the ids which are starts with "u_" and ends with"_5".
System.out.println("arrList elements : "+arrList);