I'm trying to expand all comments, replies, see more in comment, and see more in post in Facebook.
1) The codes I have written below allows me to expand all contents that I want except for maybe a few replies in a post even though I have put the repliesbutton in a loop.
2) There will a Exception in thread "main" org.openqa.selenium.ElementNotVisibleException: Element is not currently visible and so may not be interacted with error at the .click() if there is no try-catch in all the smaller for loops.
//declare WebDriverWait variable, times out after 20 seconds
WebDriverWait wait = new WebDriverWait(dr, 20);
//check element is present on the DOM of a page and visible
wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("commentable_item")));
List<WebElement> comments = dr.findElements(By.className("commentable_item")); //get the comments
//iterate through the comments
for (WebElement comment : comments) {
boolean clickMore = true;
try {
while(clickMore == true) {
//find web elements by their respective class name
List<WebElement> commentsbutton = comment.findElements(By.className("UFIPagerLink")); //view more/previous comments
List<WebElement> repliesbutton = comment.findElements(By.className("UFIPagerIcon")); //replies
List<WebElement> seemorebutton = comment.findElements(By.className("_5v47")); //see more in comment
List<WebElement> seemorelinkbutton = dr.findElements(By.className("see_more_link")); //see more in link
//click more comments
if(commentsbutton.size() > 0) {
for (WebElement comments_element : commentsbutton) {
//comments_element.click(); //click on button if found
//Thread.sleep(5000); //pause for 5 seconds
try{
comments_element.click(); //click on button if found
Thread.sleep(5000); //pause for 5 seconds
} catch(Exception e){
}
}
for (WebElement replies_element : repliesbutton) {
//replies_element.click(); //click on button if found
//Thread.sleep(3000); //pause for 3 seconds
try{
replies_element.click(); //click on button if found
Thread.sleep(3000); //pause for 5 seconds
} catch(Exception e){
}
}
}
else clickMore = false;
for (WebElement seemorelinks_element : seemorelinkbutton) {
try{
seemorelinks_element.click(); //click on button if found
Thread.sleep(5000); //pause for 5 seconds
} catch(Exception e){
}
}
for (WebElement seemore_element : seemorebutton) {
try{
seemore_element.click(); //click on button if found
Thread.sleep(5000); //pause for 5 seconds
} catch(Exception e){
}
}
}
} catch (NoSuchElementException e) { //when no elements are found
System.out.println("Comments in this post not found");
}
}
}
//return the given element if it is visible and has non-zero size, otherwise null.
private static WebElement elementIfVisible(WebElement element) {
return element.isDisplayed() ? element : null;
}
public static ExpectedCondition<WebElement> visibilityOfElementLocated(final By locator) {
return new ExpectedCondition<WebElement>() {
#Override
public WebElement apply(WebDriver driver) {
try {
return elementIfVisible(dr.findElement(locator));
} catch (StaleElementReferenceException e) {
return null;
}
}
};
}
}
You can create a utility method and put it in some 'Utility.java' class something like below:
public void click(WebElement element)
{
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(500);
if(element.isDisplayed())
element.click();
}
Usage:
WebElement element=driver.findElement(//Locator);
Utility.click(element);
This will ensure every time before you click the element is scrolledIntoView.
Let me know if you need further help on this.
Related
I have a page that contains a bunch of tables. I loop through the tables in the outer loop and then loop through each row in the table in the inner loop. It all works fine. But some of the pages have a Next button. When I add code to click that after completing the page, then I start getting StaleElementReferenceException while looping through the rows of a table.
Here is the code:
WebDriverWait wait1 = new WebDriverWait(driver, 10000);
WebElement maxPage = null;
WebElement auctionsWaitingDiv = driver.findElement(By.cssSelector("div[class='Head_W']"));
if (auctionsWaitingDiv.isDisplayed() == false) return properties;
try {
maxPage = wait1.until(ExpectedConditions.visibilityOfElementLocated(By.id("maxWA")));
} catch (TimeoutException ex) {
return properties;
}
Integer maxPageNo = 1;
if (!maxPage.getText().isEmpty())
maxPageNo = Integer.parseInt(maxPage.getText());
for (int i = 1; i <= maxPageNo; i++) {
driver.findElement(By.cssSelector("div[id='Area_W']")); //only look at Auctions Waiting section
WebDriverWait wait2 = new WebDriverWait(driver, 10000);
List<WebElement> tables = null;
try {
tables = wait2.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("table[class='ad_tab']")));
} catch (TimeoutException ex) {
System.out.println("table not found in allotted time");
return properties;
} catch (StaleElementReferenceException ex) {
System.out.println("returning due to StaleElementReferenceException");
return properties;
}
for (WebElement table: tables) {
List<String> propAttributes = new ArrayList<>();
// StaleElementReferenceException: The element reference of
// <table class="ad_tab"> is stale; either the element is no
// longer attached to the DOM, it is not in the current
// frame context, or the document has been refreshed
List<WebElement> rows = table.findElements(By.cssSelector("tr"));
String parcelLink = "";
for (WebElement row : rows) {
WebElement key = row.findElement(By.cssSelector("th"));
WebElement val = row.findElement(By.cssSelector("td"));
String keyVal = key.getText() + val.getText();
propAttributes.add(keyVal);
if (key.getText().equals("Parcel ID:")) {
WebElement a = val.findElement(By.cssSelector("a"));
parcelLink = a.getAttribute("href");
}
}
}
driver.findElement(By.xpath(".//*[#class='PageRight']")).click(); //click the "Next" button
}
What I don't understand is why the stale element is happening at all? The page is not changing during the loop and I've waited until all elements have been fetched. How to avoid the StaleElementReferenceException?
Edit: The last stack trace shows it is happening in this line:
List<WebElement> rows = table.findElements(By.cssSelector("tr"));
and the error message above it shows:
SEVERE: null
org.openqa.selenium.StaleElementReferenceException: The element reference of <table class="ad_tab"> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed
The StaleElementReferenceException is thrown whenever you want to access an element reference which is not available anymore. This happens when the element is no longer attached to the DOM or if the page was updated.
The solution for this is just searching for the element again whenever this happens.
You could adapt all your tests or page objects. Or you write your own RobustWebDriver and RobustWebElement which refreshes the element if a SERE is thrown.
RobustWebDriver:
public class RobustWebDriver implements WebDriver {
private WebDriver originalWebDriver;
public RobustWebDriver(WebDriver webDriver) {
this.originalWebDriver = webDriver;
}
#Override
public void get(String url) {
this.originalWebDriver.get(url);
}
#Override
public String getCurrentUrl() {
return this.originalWebDriver.getCurrentUrl();
}
#Override
public String getTitle() {
return this.originalWebDriver.getTitle();
}
#Override
public List<WebElement> findElements(By by) {
List<WebElement> elements = new ArrayList<>();
for (WebElement element : this.originalWebDriver.findElements(by)) {
elements.add(new RobustWebElement(element, by, this));
}
return elements;
}
#Override
public WebElement findElement(By by) {
return new RobustWebElement(this.originalWebDriver.findElement(by), by, this);
}
#Override
public String getPageSource() {
return this.originalWebDriver.getPageSource();
}
#Override
public void close() {
this.originalWebDriver.close();
}
#Override
public void quit() {
this.originalWebDriver.quit();
}
#Override
public Set<String> getWindowHandles() {
return this.originalWebDriver.getWindowHandles();
}
#Override
public String getWindowHandle() {
return this.originalWebDriver.getWindowHandle();
}
#Override
public TargetLocator switchTo() {
return this.originalWebDriver.switchTo();
}
#Override
public Navigation navigate() {
return this.originalWebDriver.navigate();
}
#Override
public Options manage() {
return this.originalWebDriver.manage();
}
}
RobustWebElement:
public class RobustWebElement implements WebElement {
private WebElement originalElement;
private RobustWebDriver driver;
private By by;
private static final int MAX_RETRIES = 10;
public RobustWebElement(WebElement element, By by, RobustWebDriver driver) {
this.originalElement = element;
this.by = by;
this.driver = driver;
}
#Override
public void click() {
int retries = 0;
while (retries < MAX_RETRIES) {
try {
this.originalElement.click();
return;
} catch (StaleElementReferenceException ex) {
refreshElement();
}
retries++;
}
throw new StaleElementReferenceException(
String.format("Element is still stale after %s retries.", MAX_RETRIES));
}
#Override
public void sendKeys(CharSequence... keysToSend) {
int retries = 0;
while (retries < MAX_RETRIES) {
try {
this.originalElement.sendKeys(keysToSend);
return;
} catch (StaleElementReferenceException ex) {
refreshElement();
}
retries++;
}
throw new StaleElementReferenceException(
String.format("Element is still stale after %s retries.", MAX_RETRIES));
}
// TODO add other unimplemented methods with similar logic.
private void refreshElement() {
this.originalElement = driver.findElement(by);
}
And then you just need to wrap your WebDriver into the RobustWebDriver and you are ready to go:
WebDriver driver = new RobustWebDriver(new ChromeDriver());
EDIT:
Of course you need to take care of scrolling up and down by yourself.
Well after tearing my hair out for a day, I finally realized what was happening. It should have been obvious to me. When the "Next" button is clicked, it takes some time for the new page to load. By simply adding a delay, the new DOM is loaded and processing begins on it, not again on the previous one!
driver.findElement(By.xpath(".//*[#class='PageRight']")).click();
try {
Thread.sleep(4000); //provide some time for the page to load before processing it
} catch (InterruptedException ex) {
Logger.getLogger(RealAuction.class.getName()).log(Level.SEVERE, null, ex);
}
Now it runs to completion with no StaleElementReferenceException.
My Wait() method works in 'Chrome' & 'Firefox' but not in 'IE', any ideas?
I have tried using IEDriverServer.exe both the 32bit and the 64bit(Send keys acts slow), but the following method still dosnt click on the intended target.
Please note: I know the locators are fine as listed above works in both Chrome and firefox.
public void waitAndClickFirstDrivingExperiencesOption(WebElement element) throws Exception {
WebDriverWait wait2 = new WebDriverWait(driver, 30);
Base_Page basePage = new Base_Page(driver);
try {
System.out.println(basePage.browser_type);
Boolean elementPresent = wait2.until(ExpectedConditions.elementToBeClickable(element)).isEnabled();
if (elementPresent == true) {
if (!this.browser_type.equals("firefox")) {
// Provide a slight timeout before clicking on the element
basePage.scrollToElementByLocator(element);
Thread.sleep(1000);
basePage.actionMoveAndClick(element);
} else {
Thread.sleep(500);
basePage.scrollToElementByLocator(element);
Thread.sleep(1000);
element.click();
}
}
System.out.println("Clicked on the first supercars link, using locator: " + element.toString());
} catch (StaleElementReferenceException elementUpdated) {
element = this.driver.findElement(By.xpath(".//*[#id='prd_listing']/div/li[1]/a"));
Boolean elementPresent = wait2.until(ExpectedConditions.elementToBeClickable(element)).isEnabled();
if (elementPresent == true) {
if (!this.browser_type.equals("firefox")) {
basePage.scrollToElementByLocator(element);
Thread.sleep(1000);
basePage.actionMoveAndClick(element);
} else {
Thread.sleep(500);
basePage.scrollToElementByLocator(element);
Thread.sleep(1000);
element.click();
}
}
System.out.println(
"Clicked on the first supercars link (Stale Exception), using locator: " + element.toString());
} catch (Exception e) {
System.out.println("Exception! - could not click on the first supercars link, Exception: " + e.toString());
throw (e);
} finally {
}
I have code something like this
WebDriver driver = new FirefoxDriver();
driver.get(something URL);
WebDriverWait waiting = new WebDriverWait(driver, 10, 1000);
WebElement element = waiting.until(ExpectedConditions.presenceOfElementLocated(By.id(my_id)));//problem is here
But then i try to find element on my page, WebDriverWait waiting until the page has completely loaded and then starts searching.
If I'm trying something like this
WebDriverWait waiting = new WebDriverWait(driver, 10, 2700);
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
WebElement element;
try {
driver.get(something_url);
} catch (TimeoutException e) {
((JavascriptExecutor) driver).executeScript("window.stop();");
}finally {
element = waiting.until(ExpectedConditions.presenceOfElementLocated(By.id(my_id)));
}
It works, but if I go on like this
element.click();//go to another page
On this line doesn't throw a timeout exception, I have to wait for the full page load.
How to be in this situation ?
Solution is to wait for ajax refresh to complete on this page:
public void waitForAjaxRefresh() {
System.out.println("Waiting for Ajax Refresh");
try {
WebDriverWait wait = new WebDriverWait(driver,35);
final JavascriptExecutor javascript = (JavascriptExecutor) (driver instanceof JavascriptExecutor ? driver
: null);
wait.until(new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver d) {
boolean outcome = Boolean.parseBoolean(javascript
.executeScript("return jQuery.active == 0")
.toString());
return outcome;
}
});
} catch (TimeoutException ex) {
throw new TimeoutException("Timed out after "
+ 35
+ " seconds while waiting for Ajax to complete.");
} catch (WebDriverException e) {
System.out.println("JQuery libraries are not present on page "
+ driver.getCurrentUrl() + " - "
+ driver.getTitle());
}
}
I have written the below script where first i will click on FACEBOOK Sign in button then the pop up for FACEBOOK login page will open in a separate window.I am entering the id and password. But my issue is when i am clicking on the login button then that window will disappear and my parent window URL will change. How to handle the changed URL. I need to perform some operation on that. I am aware that i can move to parent window,but the issue is when i click on login the URL changes
private void facebookSignIn(){
WebElement element=null;
try{
element = driver.findElement(By.xpath(".//*[#id='signin_facebook_button']/div[2]"));
String mwh=driver.getWindowHandle();
element.click();
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
Set<String> set=driver.getWindowHandles();
Iterator<String> iterator=set.iterator();
while(iterator.hasNext())
{
String popupHandle=iterator.next().toString();
if(!popupHandle.contains(mwh))
{
driver.switchTo().window(popupHandle);
element = driver.findElement(By.xpath(".//*[#id='email']"));
element.sendKeys(account);
element = driver.findElement(By.xpath(".//*[#id='pass']"));
element.sendKeys(password);
element = driver.findElement(By.xpath(".//*[#id='u_0_2']"));
countDownLatch.countDown();
countDownLatch.await();
element.click();
System.out.println("Click Done");
//driver.switchTo().window(mwh);
}
}
start = System.currentTimeMillis();
counter++;
if(counter==1)
{
startTime=System.currentTimeMillis();
}
#SuppressWarnings("unused")
WebElement sso_logout = (new WebDriverWait(driver,30)).until(ExpectedConditions.visibilityOfElementLocated(By.id("sso_logout")));
end = System.currentTimeMillis();
endTime=System.currentTimeMillis();
try{
element = driver.findElement(By.id("sso_logout"));
element.click();
}
catch(Exception e)
{
System.out.println("Exception from SSO_Logout");
}
double temp=(double)(end-start)/1000;
latencyMap.put(Thread.currentThread().getName(),temp) ;
System.out.println(Thread.currentThread().getName()+"-->Done");
}
catch(Exception e){
countDownLatch.countDown();
totalNumberOfUsers--;
System.out.println(account);
System.out.println(e.getMessage());
}
}
WindowHandle is not based on url, so it shouldn't effect you. If you need to switch back do something like that:
String parentHandle = driver.getWindowHandle();
// switch to the new window
for (String winHandle : driver.getWindowHandles()) {
if (!winHandle.equals(parentHandle))
{
driver.switchTo().window(winHandle);
}
}
//do something with the new window
element = driver.findElement(By.xpath(".//*[#id='email']"));
element.sendKeys(account);
element = driver.findElement(By.xpath(".//*[#id='pass']"));
element.sendKeys(password);
element = driver.findElement(By.xpath(".//*[#id='u_0_2']"));
countDownLatch.countDown();
countDownLatch.await();
element.click();
System.out.println("Click Done");
// switch back to the old window
driver.switchTo().window(parentHandle);
// if the new window is closed by its on
driver.switchTo().window(driver.getWindowHandle());
WindowHandle example:
"CDwindow-0D7BB6F6-A7E0-4DCE-B4D0-F202E85D982D"
There is a table list of username, from these table I have edited the username "Pra" to "Pra1", but now when I come to the user table list its not finding a user with the name "Pra" because its updated with "Pra1".
So, what I want is after updating an username in the search filter it search with updated username (With "Pra1").
Below are the running code upto the updated username please help me after that:
public class InsSystemCenter {
public static void main(String[] args) {
// TODO Auto-generated method stub
WebDriver driver = new FirefoxDriver();
driver.get("URL");
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
// Verify the insfocus system center page has been opened or not by
// xpath//
if (driver.findElement(By.xpath("/html/body/table/tbody/tr[1]/td/h1")) != null) {
System.out.println("Center has been opened");
} else {
System.out.println("Center is not displaying");
}
WebElement userName = driver.findElement(By.name("username"));
userName.sendKeys("pra");
WebElement password = driver.findElement(By.name("password"));
password.sendKeys("123456");
WebElement signIn = driver
.findElement(By
.xpath("/html/body/table/tbody/tr[2]/td/table/tbody/tr[1]/td/form/center/div/table/tbody/tr[4]/td/input"));
signIn.click();
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
// Verify that welcome page is displayed or not//
WebElement welcomePageVerify = driver
.findElement(By
.xpath("/html/body/table/tbody/tr[3]/td/table/tbody/tr[1]/td/div[2]/span"));
if (welcomePageVerify.isDisplayed()) {
System.out.println("Welcome page is displaying");
} else {
System.out.println("Welcome page is not displaying");
}
// Try to click on the tab name "Settings" by xpath//
WebElement settings = driver.findElement(By
.xpath("/html/body/table/tbody/tr[2]/td/ul/li[3]/a"));
settings.click();
// Verifying that after clicking on "Setting" it opens a database page
// or not//
WebElement settingsVerify = driver
.findElement(By
.xpath("/html/body/form/table/tbody/tr[3]/td/table/tbody/tr[1]/td[2]/div/table/tbody/tr/td[2]/h1/span"));
if (settingsVerify.isDisplayed()) {
System.out
.println("Database page is displayed after clicking on Setting tab");
} else {
System.out.println("Database page is not displaying");
}
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
// Click on the button "Users" by xpath, so that it goes to the page
// where it show the list of users //
WebElement users = driver
.findElement(By
.xpath("/html/body/form/table/tbody/tr[3]/td/table/tbody/tr[1]/td[1]/p/a[2]"));
users.click();
// Verifying for users page opened or not//
WebElement usersPageVerify = driver
.findElement(By
.xpath("/html/body/table/tbody/tr[3]/td/table/tbody/tr[1]/td[2]/div/table/tbody/tr/td[2]/h1"));
if (usersPageVerify.isDisplayed()) {
System.out
.println("Users page is displayed after clicking on users button");
} else {
System.out.println("Users page is not displaying");
}
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
System.out.println("Total time take " + new Date());
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
System.out.println("Error in wait");
}
driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
System.out.println("Total time take " + new Date());
WebElement usUserName = driver.findElement(By.id("g_UserName"));
usUserName.sendKeys("Pra");
usUserName.sendKeys(Keys.ENTER);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("Error in wait");
}
usUserName.sendKeys(Keys.TAB);
System.out.println("Total time take " + new Date());
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
System.out.println("Error in wait");
}
driver.manage().timeouts().implicitlyWait(1, TimeUnit.MINUTES);
// Checked the checkbox of find elemet or user//
WebElement checkbox = driver.findElement(By.id("jqg_tblMainTable_243"));
checkbox.click();
// After checked the checkbox it enables the edit button for edit the
// user//
WebElement editButton = driver.findElement(By.id("btnEdit"));
editButton.click();
// ------------Edit user popup--------------//
// Verify edit popup opened or not//
String source = driver.getPageSource();
int a = source.indexOf("Edit User:");
if (a > 0) {
System.out.println("Edit user popup is displayed");
} else {
System.out.println("Edit user popup is not displaying");
}
// All the WebElement parameter is located here//
WebElement euUserName = driver.findElement(By.id("UserName"));
euUserName.clear();
euUserName.sendKeys("pra1");
WebElement euFullName = driver.findElement(By.id("txtFullName"));
euFullName.clear();
euFullName.sendKeys("pra1");
WebElement euPassword = driver.findElement(By.id("txtPassword"));
euPassword.sendKeys("123456");
WebElement euConfirmPassword = driver.findElement(By
.id("txtConfirmPassword"));
euConfirmPassword.sendKeys("123456");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("Error in wait");
}
WebElement dropdown = driver.findElement(By.id("RoleID"));
// Verify dropdown is displayed or not not //
if (dropdown.findElement(By.id("RoleID")) != null) {
System.out.println("Dropdown is displayed");
} else {
System.out.println("Dropdown is not displaying");
}
Select clickThis = new Select(dropdown);
clickThis.selectByVisibleText("Normal");
System.out.println("Drop down values "+clickThis.getOptions().get(0).getText());
WebElement euUserDetail = driver.findElement(By.id("UserDetails"));
euUserDetail.clear();
euUserDetail.sendKeys("pra1");
WebElement euOk= driver.findElement(By.xpath("/html/body/div[3]/div[3]/div/button[1]"));
euOk.click();
driver.manage().timeouts().implicitlyWait(1, TimeUnit.MINUTES);
driver.quit();
}
}
Just call clear() method before your calling sendKeys("your text").
This should work.
Just use the clear function before passing the value to the webelement
WebElement userName = driver.findElement(By.name("username"));
userName.clear();
userName.sendKeys("pra");
Same way you can use for all the elements.
ok i can't even be bothered trying to read a 7 million line long main method
1) refactor it in to separate logical methods (responsibility driven design)
2) when you have done that post us the code responsible for your issues
3) maybe look at assigning the value you want to search on to a temporary variable so you can find it again?