How to refresh WebElement in Selenium Webdriver without reload page? - selenium

I need to refresh WebElement in Selenium Webdriver without reload page.
When i use a while, the text of the page element is constantly updated because it is a chat, but the loop carries only the same text.
while (driver.FindElements(By.ClassName("chat")).Count() > 0)
{
{
var element = driver.FindElement(By.ClassName("_chat")).Text;
Console.WriteLine(element);
}
}
I am using a C# project.
Thanks!

Sorry i use java
If you get element outdated errors
you can use it
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.name("_chat")));
Instead of
wait.until(ExpectedConditions.visibilityOf(driver.findElement(By.name("_chat"))));
not use driver.findElement

Try this.
for (int i = 0; i < 5; i++) {
while (driver.FindElements(By.ClassName("chat")).Count() > 0)
{
{
var element = driver.FindElement(By.ClassName("_chat")).Text;
Console.WriteLine(element);
}
}
}

Related

How to click on the reCAPTCHA using Selenium and Java

Why am I getting errors when trying to get the driver to click on the reCAPTCHA button?
This is the site where I am trying to get it to work: https://rsps100.com/vote/760/
This is my current code so far:
WebElement iframeSwitch = driver.findElement(By.xpath("/html/body/div[1]/div/div[1]/div/div/div[2]/div/form/div/div/div/div/iframe"));
driver.switchTo().frame(iframeSwitch);
driver.findElement(By.cssSelector("div[class=recaptcha-checkbox-checkmark]")).click();
To invoke click() on the reCaptcha checkbox as the element is within an <iframe> you need to:
Induce WebDriverWait for the desired frameToBeAvailableAndSwitchToIt.
Induce WebDriverWait for the desired elementToBeClickable.
You can use the following solution:
Code Block:
public class ReCaptcha_click {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.addArguments("disable-infobars");
options.addArguments("--disable-extensions");
WebDriver driver = new ChromeDriver(options);
driver.get("https://rsps100.com/vote/760");
new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe[starts-with(#name, 'a-') and starts-with(#src, 'https://www.google.com/recaptcha')]")));
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("div.recaptcha-checkbox-checkmark"))).click();
}
}
Browser Snapshot:
Use WebDriverWait to identify the element.See if this help.
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe[starts-with(#name,'a-')]")));
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("div.recaptcha-checkbox-checkmark")));
element.click();
This worked for me. Please note that I am using Selenide. For regular selenium code look the same.
import static com.codeborne.selenide.Selenide.*;
void recaptchaTest() {
open("https://rsps100.com/vote/760");
switchTo().frame($x("//iframe[starts-with(#name, 'a-') and starts-with(#src, 'https://www.google.com/recaptcha')]"));
$("div.rc-anchor-content").click();
switchTo().defaultContent();
}
Here is the code that should work.
driver.switchTo().frame("a-9wt0e8vkopnm");
driver.findElement(By.xpath("//span[#id='recaptcha-anchor']")).click();
I solved this maybe on the stupid way. But hawe in mind that I am not in test environment and I practicing automatization of tests. So this is my solution:
Beside using
public void notABot( ) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds( 15 ));
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe[starts-with(#name,'a-') and starts-with (#src, 'https://www.google.com/recaptcha')]")));
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div [ #class = 'recaptcha-checkbox-border']"))).click( );
driver.switchTo().defaultContent();
}
this, I also added custom send keys method
public void inputEmail( ) {
inputEmail.click( );
String email = Strings.EMAIL_FOR_SIGNUP;
for (int i = 0; i < email.length(); i++) {
char c = email.charAt(i);
String s = new StringBuilder( ).append( c ).toString( );
inputEmail.sendKeys( s );
sleepSendKeys( );
}
}
Sleep is 300 millis. In 96 procent time I manage to cheat google reCaptcha that actually human is login to the page. Its work for me

Scrolling Google results using Selenium WebDriver 3.4.0

I am not able to scroll Google's results page to the end. Could anyone give me pointers on the below code 1. Tried to do using JS by the following
(a)j.executeScript("window.scrollTo(0,500)")
(b)j.executeScript("window.scrollBy(250,350)")
(c)j.executeScript("window.scrollTo(0,document.documentElement.scrollHeight")**
WebDriver driver = new ChromeDriver();
driver.navigate().to("https://www.google.com");
driver.manage().window().maximize();
// Google News
driver.findElement(By.id("lst-ib")).click();
driver.findElement(By.id("lst-ib")).sendKeys("News");
driver.findElement(By.id("lst-ib")).sendKeys(Keys.RETURN);
Thread.sleep(2000);
driver.findElement(By.xpath("//div[#class='rc']//a")).click();
Thread.sleep(4000);
JavascriptExecutor j = (JavascriptExecutor)driver;
for(int i=1;i<=3;i++)
{
j.executeScript("window.scrollTo(0,500)");
}
}
}
Use this:
((JavascriptExecutor) driver).executeScript("window.scrollBy(0,250)");
Scroll to particular element
js.executeScript("arguments[0].scrollIntoView(true);",element);
Here element is your Webelement from where you wanted to scroll
or you can use Robot class
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_PAGE_DOWN);
robot.keyRelease(KeyEvent.VK_PAGE_DOWN);
Change below code
for(var i=1;i<=3;i++)
{
j.executeScript("window.scrollTo(0,500)");
}
to
for(int i=1;i<=3;i++)
{
j.executeScript("window.scrollTo(0, arguments[0]*500)", i);
}
And it should work. 500 that you used is absolute value and not a delta for scroll. Or else use scrollBy
for(int i=1;i<=3;i++)
{
j.executeScript("window.scrollBy(0,500)");
}
j.executeScript("window.scrollBy(0,250)", "");
OR, you can do as follows:
j.executeScript("scroll(0, 250);");

Element not found - Selenium

I have written a piece of code to login into an application which is working fine. Now I have to click an add button, and I have tried it by Id, XPath, ClassName but it just gives me the exception of element not found. I thought I should apply an explicit wait, but it also did not work. Please check my code below:
public static void Login()
{
Browser.Url = "http://example.com";
_username = Browser.FindElement(By.Id("UserName"));
var password = Browser.FindElement(By.Id("Password"));
var loginbtn = Browser.FindElement(By.ClassName("btn-primary"));
_username.SendKeys("admin");
password.SendKeys("123");
loginbtn.Click();
var supplierTab = Browser.FindElement(By.Id("mainSupplier"));
supplierTab.Click();
WebDriverWait wait = new WebDriverWait(Browser, TimeSpan.FromSeconds(20));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
try
{
return d.FindElement(By.Id("btnAddSupplier_SupplierForm"));
}
catch
{
return null;
}
});
var addbtn = Browser.FindElement(By.Id("btnAddSupplier_SupplierForm"));
addbtn.Click();
}
This always gives an exception on the second last line of code that element not found.
Here is the HTML:
Try the following
public static void Login()
{
Browser.Url = "http://example.com";
_username = Browser.FindElement(By.Id("UserName"));
var password = Browser.FindElement(By.Id("Password"));
var loginbtn = Browser.FindElement(By.ClassName("btn-primary"));
_username.SendKeys("admin");
password.SendKeys("123");
loginbtn.Click();
//I think you have mentioned the iframe exist and assuming the element is inside the iframe do the following. If not skip the SwitchTo() part
//you can use name, css to identify the iframe
Browser.SwitchTo().Frame(Browser.FindElement(By.XPath("xpath for the iframe")));
var supplierTab = Browser.FindElement(By.Id("mainSupplier"));
supplierTab.Click();
WebDriverWait wait = new WebDriverWait(Browser, TimeSpan.FromSeconds(20));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id("btnAddSupplier_SupplierForm"));
});
//if you think the id is not unique try using xpath or css
//even though you added an explicit wait you never used it
myDynamicElement.Click();
}
Sometimes the element will be existing in the source code but will not be visible for selenium to perform a click operation. Try the below code which will wait until the element is visible:
WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(20));
IWebElement element = wait.Until(
ExpectedConditions.ElementIsVisible(By.Id("btnAddSupplier_SupplierForm")));
element.Click();
Not sure if this would help, but try calling this function before you click on Add button:
void waitForPageLoad(WebDriver driver)
{
ExpectedCondition<Boolean> pageLoadCondition = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
wait.until(pageLoadCondition);
}
A NoSuchElementException is thrown when the locating mechanism used is not available in the dom.
A TimeoutException is thrown when your expected condition fails to be true within the time limit. An expected condition can be anything, (exists,visibility,attribute value etc...).
First you want to figure out if the element's locating mechanism you are using is indeed not found in the dom. Here is a good way to manually find out.
Open chrome and navigate to the page.
Open chrome dev tools and click on the console tab.
In the text box type $x("//*[#id='btnAddSupplier_SupplierForm']") and hit enter. This will run an xpath query, basically you are looking for any element that has an id attribute with value "btnAddSupplier_SupplierForm".
If an element appears in the console and is the correct element then it's likely that you are trying to find an element in the dom before the dom is finished loading. If no element appears in the console then you have a bad locator.
Please report your findings.

Selenium Webdriver : I want an alternative and i want to click on the buttons continously

I want to click on the items, but i want to reduce the number of lines in code. How do i do it. Also i want to run the click operation for 5 times on all the elements below.
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[1]/a/span")).click();
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[2]/a/span")).click();
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[3]/a/span")).click();
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[4]/a/span")).click();
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[5]/a/span")).click();
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[6]/a/span")).click();
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[7]/a/span")).click();
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[8]/a/span")).click();
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[9]/a/span")).click();
driver.findElement(By.xpath(".//*[#id='fp-nav']/ul/li[10]/a/span")).click();
Assuming you are using JAVA as the language , please see if the below code helps you out:
int i;
try{
WebElement ele;
//Iterating through all the 10 elements
for(i=1;i<=10;i++){
ele = driver.findElement(By.xpath("//*[#id='fp-nav']/ul/li["+i+"]/a/span"));
//Clicking 5 times on the element
for(int j=1;j<=5;j++){
ele.click();
}
}
}catch(Throwable e){
System.out.println("Error came up while clicking the element with xpath: '"+"//*[#id='fp-nav']/ul/li["+i+"]/a/span'"+". "+e.getMessage());
}
NOTE: It will iterate through all the 10 elements and click on each element 5 times. The only problem that might come up here is, in case the click results in a DOM change then the StaleElementReferenceException might come into fray.
I've used array concept in code below. It will click 10 items in each set(5 times).
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class clickitems
{
public static void main(String[] args)
{
String[] element={".//*[#id='fp-nav']/ul/li[1]/a/span", ".//*[#id='fp-nav']/ul/li[2]/a/span",".//*[#id='fp-nav']/ul/li[3]/a/span", ".//*[#id='fp-nav']/ul/li[4]/a/span", ".//*[#id='fp-nav']/ul/li[5]/a/span", ".//*[#id='fp-nav']/ul/li[6]/a/span", ".//*[#id='fp-nav']/ul/li[7]/a/span", ".//*[#id='fp-nav']/ul/li[8]/a/span", ".//*[#id='fp-nav']/ul/li[9]/a/span", ".//*[#id='fp-nav']/ul/li[10]/a/span"};
WebDriver driver = new ChromeDriver(); // Modify according to your browser
for(int i = 1; i < 6 ; i++){
System.out.println("Count : "+ i);
for(int j = 0; j < element.length ; j++)
{
System.out.println(element[j]);
driver.findElement(By.xpath(element[j])).click();
}
}
}
}

StaleElementReferenceException when trying to reidentify the object

I am facing problem to identify the object when i move forward and comeback to parent page.
Here is the scenario. I would like to click on each link in a home page and print page title and navigate back to home page.
Following is the code which i tried. It works fine clicking on the first link and coming back to HomePage. At this point of time, the List Object needs to be identified excluding already visited links. How to do that?
In QTP, we have RefreshObject and Init to do this. Is there a similar method in WebDriver?
WebDriver driver = new FirefoxDriver();
driver.get("http://www.googl.com/");
driver.manage().window().maximize();
List<WebElement> objWEs = driver.findElements(By.tagName("a"));
for(WebElement e:objWEs)
{
if(!e.getText().isEmpty())
{
e.click();
System.out.println(driver.getTitle());
driver.navigate().back();
}
}
driver.close();
As soon as you navigate to another web-page, or even switch into an iframe in the same web-page, any WebElement object that you have in memory is potentially "stale".
One optional solution, is to list down all the element IDs, and then iterate that list instead:
Set<String> linkIds = new HashSet<String>();
List<WebElement> links = driver.findElements(By.tagName("a"));
for (WebElement link : links)
{
if(!link.getText().isEmpty())
linkIds.add(link.getAttribute("id"));
}
for (String linkId : linkIds)
{
driver.findElement(By.id(linkId)).click();
System.out.println(driver.getTitle());
driver.navigate().back();
}
Please note, however, that all the above is under the assumption that each link has a unique ID, and that all the links remain in the web-page when you navigate back into it. If this is not the case in the specific web-page that you are accessing, then an alternative approach is required here.
Instead of iterating the link-IDs, you can iterate the link-indexes, assuming that the links remain in the same order when you navigate in and out of the web-page. This is somewhat less efficient though, because you have to retrieve the entire list of all the links at the beginning of each iteration.
for (int i=0; true; i++)
{
List<WebElement> links = driver.findElements(By.tagName("a"));
if (i >= links.size())
break;
links.get(i).click();
System.out.println(driver.getTitle());
driver.navigate().back();
}
The code above should work even if the links do not remain in the same order when you navigate back into the web-page. However, under such scenario, you will most likely miss out on some of them.
Here is the complete code for my above problem.
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(1, TimeUnit.MINUTES);
driver.get("http://www.googl.com/");
driver.manage().window().maximize();
for (int i=0; true; i++)
{
List<WebElement> links = driver.findElements(By.tagName("a"));
if (i >= links.size())
break;
WebElement ele=links.get(i);
if(!ele.getText().isEmpty())
{
ele.click();
System.out.println(driver.getTitle());
driver.navigate().back();
}
}
driver.close();