Reputation: 31
What I am trying to do is after logging in, driver will click on Property dropdown, select an option and click on submit and repeat the process until the loop is complete.
Below is my code:
package com.genericlibrary;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import com.util.Highlighter;
public class MobopsSearchJobsFromDropDown {
WebDriver driver;
Highlighter color;
public void getSetup() {
String path = System.getProperty("user.dir");
String driverPath = path + "\\Driver\\chromedriver.exe";
System.setProperty("webdriver.chrome.driver", driverPath);
driver = new ChromeDriver();
driver.navigate().to("http://mobops-test.jcdecauxna.com/");
driver.manage().window().maximize();
}
public void logIntoMobops() {
WebElement userName = driver.findElement(By.xpath("//*[contains(@id,'username')]"));
WebElement passWord = driver.findElement(By.xpath("//*[contains(@id,'password')]"));
WebElement loginButton = driver.findElement(By.xpath("//*[contains(text(),'Login')]"));
userName.sendKeys("test2");
passWord.sendKeys("1234");
loginButton.click();
}
public void selectEachPropertyAndSeachJob() {
WebElement dateRange = driver.findElement(By.xpath("//*[contains(@name,'date_range')]"));
WebElement last7days = driver.findElement(By.xpath("(//*[contains(text(),'Last 7 Days')])[2]"));
WebElement searchJobs = driver.findElement(By.xpath("//*[contains(@name,'layout')]"));
WebElement propertyDropdown = driver.findElement(By.xpath("//*[contains(@id,'property_id')]"));
Select dropdown = new Select(propertyDropdown);
List<WebElement> optionsInPropertyDropdown = dropdown.getOptions();
for (int i = 0; i < optionsInPropertyDropdown.size(); i++) {
if (propertyDropdown.isDisplayed() && propertyDropdown.isEnabled()) {
try {
propertyDropdown.click();
dropdown.selectByVisibleText(optionsInPropertyDropdown.get(i).getText());
dateRange.click();
last7days.click();
searchJobs.click();
System.out.println("Option Search is " + optionsInPropertyDropdown.get(i).getText());
} catch (org.openqa.selenium.StaleElementReferenceException ex) {
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.visibilityOf(propertyDropdown));
}
}
}
}
public static void main(String[] args) {
MobopsSearchJobsFromDropDown obj = new MobopsSearchJobsFromDropDown();
obj.getSetup();
obj.logIntoMobops();
obj.selectEachPropertyAndSeachJob();
}
}
Right now it driver just select the first option and clicks on submit. Right after the page loads after the search completes I get the following error:
Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
I have tried to implement the following code in my code, but since I am a novice, I have no idea how to implement the following to fix the issue:
new WebDriverWait(driver, timeout)
.ignoring(StaleElementReferenceException.class)
.until((WebDriver d) -> {
d.findElement(By.xpath("//*[contains(@id,'property_id')]")).click();
return true;
});
Any help to overcome this issue is greatly appreciated. Thanks.
Upvotes: 2
Views: 6739
Reputation: 31
Someone helped me with the problem. Below is the solution:
public class MobopsSearchJobsFromDropDown {
WebDriver driver;
HighLighter color;
public void getSetup() throws Throwable {
String path = System.getProperty("user.dir");
String driverPath = path + "\\driver\\chromedriver.exe";
System.setProperty("webdriver.chrome.driver", driverPath);
driver = new ChromeDriver();
driver.navigate().to("http://mobops-test.jcdecauxna.com/");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
public void logIntoMobops() throws Throwable {
WebElement userName = driver.findElement(By.xpath("//*[contains(@id,'username')]"));
WebElement passWord = driver.findElement(By.xpath("//*[contains(@id,'password')]"));
WebElement loginButton = driver.findElement(By.xpath("//*[contains(text(),'Login')]"));
userName.sendKeys("test2");
passWord.sendKeys("1234");
loginButton.click();
}
public void selectEachPropertyAndSeachJob() throws Throwable {
WebDriverWait wait = new WebDriverWait(driver, 30);
List<WebElement> dropdownoptions = driver.findElements(By.xpath("//select[@id = 'property_id']//option"));
for(int i =0; i<dropdownoptions.size(); i++) {
String propertyDropdown = "//*[contains(@id,'property_id')]";
String dateRange = "//*[contains(@name,'date_range')]";
String last7days = "(//*[contains(text(),'Last 7 Days')])[2]";
String searchJobs = "//*[contains(@name,'layout')]";
Select dropdown = new Select(waitMethod(propertyDropdown));
WebElement option = dropdown.getOptions().get(i);
wait.until(ExpectedConditions.not(ExpectedConditions.stalenessOf(option)));
dropdown.selectByVisibleText(option.getText());
System.out.println(option.getText());
waitMethod(dateRange).click();
waitMethod(last7days).click();
waitMethod(searchJobs).click();
driver.navigate().refresh();
}
}
public WebElement waitMethod(String waiting) {
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement waitForRefresh =wait.until(ExpectedConditions.refreshed(ExpectedConditions.presenceOfElementLocated(By.xpath(waiting))));
return waitForRefresh;
}
public static void main(String[] args) throws Throwable {
MobopsSearchJobsFromDropDown obj = new MobopsSearchJobsFromDropDown();
obj.getSetup();
obj.logIntoMobops();
obj.selectEachPropertyAndSeachJob();
}
}
Upvotes: 1
Reputation: 384
After you execute searchJobs.click(); your page reloads, so all references to previously found elements are lost. You need to get all your WebElements, Select dropdown, and list of options again after searchJobs.click(); before using them second time. So do not save webelements.
Something like this should work:
public void selectEachPropertyAndSeachJob() {
Select dropdown = new Select(driver.findElement(By.xpath("//*[contains(@id,'property_id')]")));
List<WebElement> optionsInPropertyDropdown = dropdown.getOptions();
for (int i = 0; i < optionsInPropertyDropdown.size(); i++) {
if (driver.findElement(By.xpath("//*[contains(@id,'property_id')]")).isDisplayed()) {
//propertyDropdown.click(); no need to click
dropdown.selectByVisibleText(optionsInPropertyDropdown.get(i).getText());
driver.findElement(By.xpath("//*[contains(@name,'date_range')]")).click();
driver.findElement(By.xpath("(//*[contains(text(),'Last 7 Days')])[2]")).click();
driver.findElement(By.xpath("//*[contains(@name,'layout')]")).click();
// Need to find it again
dropdown = new Select(driver.findElement(By.xpath("//*[contains(@id,'property_id')]")));
optionsInPropertyDropdown = dropdown.getOptions();
System.out.println("Option Search is " + optionsInPropertyDropdown.get(i).getText());
}
}
}
Instead of using driver.findElement every time, you can save your locators as By elements and create custom find method.
Upvotes: 0