Selenium IDE generate code not using WebDriverWait.Until - selenium

When generating NUnit code from selenium ide, wait commands like clickAndWait generate an awkward pattern using a loop.
Wouldn't it be better to use a WebDriverWait.until?
Or am I getting something wrong?
UPDATE:
Sorry, wrote from memory, the code i was referring to is on the waitForElementcommand and not clickAndWait.
This is the code i'm referring to:
// waitForElementPresent | id=id |
for (int second = 0; ; second++)
{
if (second >= 60) Assert.Fail("timeout");
try
{
if (IsElementPresent(By.Id("id"))) break;
}
catch (Exception)
{ }
Thread.Sleep(1000);
}
private bool IsElementPresent(By by)
{
try
{
driver.FindElement(by);
return true;
}
catch (NoSuchElementException)
{
return false;
}
}
Reading various guides and other answers, it seems to me that a better solution would be this one:
// waitForElementPresent | id=id |
if (!WaitForElementPresent(By.Id("id"))) { Assert.Fail(); }
private bool WaitForElementPresent(By by)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
try
{
wait.Until(drv => drv.FindElement(by));
return true;
}
catch (Exception)
{
return false;
}
}

Yes, using WebDriverWait is the better approach to wait for element exist, But instead of creating own custom ExpectedConditions you should use selenium provided ExpectedConditions.ElementExists function to wait until element exist as below :-
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
IWebElement el = wait.Until(ExpectedConditions.ElementExists(by));
Hope it helps..:)

Related

How do I click on an element that appears sometimes 1 or sometimes 2 at different intervals

I have done this
List<WebElement> element= driver.findElements(By.xpath(""));
for(int i=0;element.size();i++)
{
driver.findElements(By.xpath("")).isDisplayed();
driver.findElements(By.xpath("")).click();
}
I am new to java and selenium , so I thought of doing this. Is this logic correct or am I wrong? If wrong(most probably) , can you please rectify and explain alongside , wud be very helpful.
I get element not interactable error on this.
In case you are looking for method to wait for one of two elements to appear and then to click on the appeared element you can use this method:
public String waitForOneOfTwoElements(String xpath1, String xpath2){
wait = new WebDriverWait(driver, 30);
try {
wait.until(ExpectedConditions.or(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath1)),
ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath2))));
if(waitForElementToBeVisible(xpath1)){
return xpath1;
}else if(waitForElementToBeVisible(xpath2)){
return xpath2;
}
}catch (Throwable t){
return null;
}
}
Where waitForElementToBeVisible is:
public boolean waitForElementToBeVisible(String xpath) {
wait = new WebDriverWait(driver, 30);
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));
return true;
}catch (Throwable t) {
return false;
}
}
Now, when you get the appeared element you can simply click it with:
String appearedElementXpath = waitForOneOfTwoElements(xpath1,xpath2);
driver.findElement(By.xpath(appearedElementXpath)).click();

I am not able to switch to IFrame using Internet Explorer

I have developed a s keyword driven framework. It has a action keyword to switch the frame.
It works fine with Mozilla. But when it comes to IE it is not switching. It logs error.
IE driver -IEDriverServer_x64_2.44.0
IE version -9
Selenium version -selenium-java-2.44.0
Thanks in advance.
public static void switchFrame(String object,String data)throws Exception{
try{
driver.switchTo().frame("Ifrm");
Log.info("Switched the frame");
}
catch(Exception e){
Log.error("Not able to switch the frame--- " + e.getMessage());
DriverScript.bResult = false;
}
}
Here exception occurs.
I assume, the value you specified in frame is id/name/etc. You have to access the frame by calling the driver with specified value. Code would be
driver.switchTo().frame(driver.findElement(By.id("Ifrm")));
Selenium won't let me switch to the iframe by ID on Internet Explorer, but it does allow me to switch by index. If you have some sort of property that you can check that it is only available on the iframe you can do the following
new WebDriverWait(driver, 5).until(
new Predicate<WebDriver>() {
#Override
public boolean apply(WebDriver input) {
try {
int i = 1;
while (true) {
driver.switchTo().defaultContent();
driver.switchTo().frame(i);
String aClass =
driver.findElement(By.xpath("/html/body"))
.getAttribute("class");
if (aClass.contains("modal")) {
return true;
}
++i;
}
} catch (NoSuchFrameException e) {
return false;
}
}
}
);
In my case I was looking for a body class of modal

selenium web driver should stop execution of last element

I am new to selenium and was trying to make my work automated. My results consists of pagination like next page. At last page "Next" button is disabled and my code should not access that particular element.
List<WebElement> pagesize = driver.findElements(By.xpath("html/body/div[1]/div[3]/div[3]/div/span"));
while(true) {
for(int i=5; i<=pagesize.size(); i++) {
WebElement Analystelem = driver.findElement(By.xpath("html/body/div[1]/div[3]/div[3]/div["+i+"]/span"));
List<WebElement> pagesize = driver.findElements(By.xpath("html/body/div[1]/div[3]/div[3]/div/span"));
System.out.println(pagesize.size());
while(true) {
for(int i=5;i<=pagesize.size();i++) {
WebElement Analystelem = driver.findElement(By.xpath("html/body/div[1]/div[3]/div[3]/div["+i+"]/span"));
if(elementpage.isEnabled()) {
elementpage.click();
}
else {
System.exit(1);
}
note: older search is the next button here.
at last page of results i am getting an exception as
"Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"xpath","selector":"html/body/div[1]/div[3]/div[3]/div[10]/span"}"
First of all I doubt that you have searched for a span and stored its reference to 'Analystelem' but you are calling a click action on 'elementpage'.
If the code you provided is working than below given code will work fine. When Selenium will find the element and tries to click on it; it will throw exception, handle the exception as you feel best but it will not break your execution.
Just put your code in Try Catch block like this:
while(true)
{
for(int i=5;i<=pagesize.size();i++)
{
WebElement Analystelem=driver.findElement(By.xpath("html/body/div[1]/div[3]/div[3]/div["+i+"]/span"));
if(elementpage.isEnabled())
{
Try
{
elementpage.click();
}
Catch (Exception ex)
{
//Do whatever you want to do here
}
}
else
{
System.exit(1);
}
}
}
Additionally, you do not have to check weather the element is enabled or not. Let the try catch do its work. More suited code:
while(true)
{
for(int i=5;i<=pagesize.size();i++)
{
WebElement Analystelem=driver.findElement(By.xpath("html/body/div[1]/div[3]/div[3]/div["+i+"]/span"));
Try
{
elementpage.click();
}
Catch (Exception ex)
{
System.exit(1);
//Do whatever you want to do here
}
}
}

checking for element present or not using Selenium WebDriver page factory?

Checking for elements with findElements using normal WebDriver method is easy like:
boolean exists = driver.findElements( By.id("...") ).size() != 0
Elements initialized by Page Factory are like:
#FindBy(name = "filter")
private WebElement filterText;
But how can we check in our page that this element is present on the page or not ??
The isDisplayed() method should do the job:
if (filterText.isDisplayed()) {
filterText.doStuff();
}
here's something i came up with:
public boolean isElementPresent(WebElement we)
{
try {
we.getTagName();
} catch (NoSuchElementException e) {
flag = 1;
}
if (flag == 1)
return true;
else
return false;
}
which is pretty basic but effective way to do it..

Selenium refresh

I am working on project where everything is saved in events so it took some time for server to respond for new data. I am using Fluent wait for pages using ajax, but this one doesn't use any ajax. So I want to refresh page check if new item is there if not refresh again. How this is achieved in Selenium 2?
I did this :
def accountsAfterCreating = 0
while (accountsAfterCreating <= existingAccounts) {
driver.navigate().refresh()
WebElement table = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.className("table"))
}
})
accountsAfterCreating = table.findElements(By.className("amount")).size()
}
Is it correct way?
Use Explicit wait like this In try catch block
try{
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));
}
catch()
{
driver.navigate().refresh()
}
I usually use this method to wait for any html tag. We can also specify the wait time.
public boolean waitForElement(WebElement ele, String xpath, int seconds) throws InterruptedException{
//returns true if the element appears within the time
//false when timed out
int t=0;
while(t<seconds*10){
if(ele.findElements(By.xpath(xpath)).size()>0)
return true;
else{
Thread.sleep(100);
t++;
continue;
}
}
System.out.println("waited for "+seconds+"seconds. But couldn't find "+xpath+ " in the element specified");
return false;
}
I came up with answer like this. This will work only on groovy because it is using closure
private boolean refreshUntil(Closure<Boolean> condition) {
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(8, TimeUnit.SECONDS)
.pollingEvery(200, TimeUnit.MILLISECONDS)
.ignoring(NoSuchElementException)
wait.until(new Predicate<WebDriver>() {
boolean apply(WebDriver driver) {
driver.navigate().refresh()
if (condition()) {
return true
}
return false
}
})
return true
}
and calling this method
refreshUntil {
accountsBeforeCreation + 1 == driver.findElements(By.tagName("tr"))).size()
}