WebdriverIO & Java - org.openqa.selenium.NoSuchElementException in IFrame - java

I'm facing an exception (org.openqa.selenium.NoSuchElementException) when I try to get element "email". Since I just started playing with WebDriver I'm probably missing some important concept about those race conditions.
WebElement login = driver.findElement(By.id("login"));
login.click();
WebElement iFrame = driver.findElement(By.id("iFrame"));
driver.switchTo().frame(iFrame);
WebElement email = driver.findElement(By.id("email"));
email.sendKeys(USERNAME);
Few things that I've tried but with no success:
Set an implicitly wait:
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
Create a WebDriverWait:
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement login = driver.findElement(By.id("login"));
login.click();
WebElement iFrame = driver.findElement(By.id("iFrame"));
driver.switchTo().frame(iFrame);
WebElement email = wait.until(presenceOfElementLocated(By.id("email")));
// and WebElement email = wait.until(visibilityOf(By.id("email")));
email.sendKeys(USERNAME);
Create a FluentWait:
WebElement login = driver.findElement(By.id("login"));
login.click();
WebElement iFrame = driver.findElement(By.id("iFrame"));
driver.switchTo().frame(iFrame);
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(5))
.ignoring(NoSuchElementException.class);
WebElement email = wait.until(d ->
d.findElement(By.id("email")));
email.sendKeys(USERNAME);
The only way I managed to make it work was using the old and good Thread.sleep() (ugly as well)
WebElement login = driver.findElement(By.id("login"));
login.click();
WebElement iFrame = driver.findElement(By.id("iFrame"));
driver.switchTo().frame(iFrame);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
WebElement email = driver.findElement(By.id("email"));
email.sendKeys(USERNAME);

To send a character sequence to the email element as the the desired element is within an <iframe> so you have to:
Induce WebDriverWait for the desired frameToBeAvailableAndSwitchToIt().
Induce WebDriverWait for the desired elementToBeClickable().
You can use the following Locator Strategies
driver.findElement(By.id("login")).click();
new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("iFrame")));
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.id("email"))).sendKeys(USERNAME);
Here you can find a relevant discussion on Ways to deal with #document under iframe

It turns out that the code is ok, but Chrome driver 78 linux 64 bits is messed up. I've tried with Firefox (geckodriver-0.26.0) and it worked like a charm.
Thanks for the help #DebanjanB

Related

I can't click on an element

the page is fully loaded and the element is located, but for some reason it can't be clicked, I can't understand why.
My test:
#Test
public void test(){
chromeDriver.get("https://alfabank.ru/currency/");
WebDriverWait wait = new WebDriverWait(chromeDriver, 8);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//button[contains(#class, 'j1I7k')]//p[contains(text(), 'USD')]")));
WebElement clicking = chromeDriver.findElement(By.xpath("//button[contains(#class, 'j1I7k')]//p[contains(text(), 'USD')]"));
clicking.click();
}
Full xpatch it doesn't work either:
WebElement clicking = chromeDriver.findElement(By.xpath("/html/body/div[1]/div/div[6]/div/div/div/div/div[1]/div[1]/button[2]"));
Exception:
org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element is not clickable at point (539, 1199)
None of the existing answer really explain what is their code is about.
Even if you launch the screen in full screen, USD is not in Selenium view port.
Also JS is only recommended when nothing works.
I am doing with Selenium class, actions, please see below :
driver.manage().window().maximize();
WebDriverWait wait = new WebDriverWait(driver, 30);
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
driver.get("https://alfabank.ru/currency/");
boolean b = wait.until(ExpectedConditions.titleIs("Курсы валют — «Альфа-Банк»"));
if (b) {
new Actions(driver).moveToElement(wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div[data-test-id='caption']")))).build().perform();
WebElement clicking = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//button[contains(#class, 'j1I7k')]//p[contains(text(), 'USD')]")));
((JavascriptExecutor)driver).executeScript("arguments[0].click();", clicking);
}
I use JS click, don't know why cannot click normally.
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//button[contains(#class, 'j1I7k')]//p[contains(text(), 'USD')]")));
WebElement clicking = driver.findElement(By.xpath("//button[contains(#class, 'j1I7k')]//p[contains(text(), 'USD')]"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true); arguments[0].click()", clicking);
Apply scrollIntoView and then click on the USD using JavascriptExecutor.
JavascriptExecutor js = (JavascriptExecutor) driver;
WebDriverWait wait = new WebDriverWait(driver,30);
driver.get("https://alfabank.ru/currency/");
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//button[contains(#class, 'j1I7k')]//p[contains(text(), 'USD')]")));
WebElement usdoption = driver.findElement(By.xpath("//button[contains(#class, 'j1I7k')]//p[contains(text(), 'USD')]"));
js.executeScript("arguments[0].scrollIntoView(true);", usdoption);
js.executeScript("arguments[0].click();", usdoption);

Selenium: ElementNotVisibleException while trying to click the element with text as My Account onhttps://www.phptravels.net/

When I tested phptravel website and tried to click on the myaccount link with the below code.
Selenium returns ElementNotVisibleException during the execution. What is the thing that I missed?
Source code
public void login(WebDriver driver) {
driver.navigate().to("https://www.phptravels.net/");
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("/html/body/nav/div/div[1]/a")));
// Error on here
myAccount.click();
WebDriverWait myAccountWait = new WebDriverWait(driver, 10);
myAccountWait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[#id=\"li_myaccount\"]/ul")));
loginLink.click();
WebDriverWait loginWait = new WebDriverWait(driver, 10);
//loginWait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id=\\\"loginfrm\\\"]/div[1]/div[5]/div/div[1]/input")));
username.sendKeys("user#phptravels.com");
password.sendKeys("demouser");
loginBtn.click();
}
myAccount webElement is not initialized in your code.
In case you want to click on My account link you can use this :
WebElement myAccount = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[#id='collapse']/descendant::ul[3]/li[#id='li_myaccount']/a")));
myAccount.click();
Note that you can't use link Text as that is text nodes .
Modify the code as below:
On your WebDriverWait keep the xpath as below with By type:
By myAccountBy = By.xpath("//ul[#class='nav navbar-nav navbar-right']/ul/li[1]/a");
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(myAccountBy));
OR
Hardcode the xpath like below.
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.Xpath("//ul[#class='nav navbar-nav navbar-right']/ul/li[1]/a")));
Then keep the same xpath for myAccount WebElement as below
#FindBy(xpath="//ul[#class='nav navbar-nav navbar-right']/ul/li[1]/a")
public WebElement myAccount;
In short, to click the MyAccount you have to keep this xpath
//ul[#class='nav navbar-nav navbar-right']/ul/li[1]/a
First you need to create WebElement then use elementToBeClickable Expected Condition for the same this way you can resolve the issue
WebElement myAccount = driver.findElement("Your locator");
Now use wait
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(myAccount));
myAccount.click();
Also maximize the browser.
It is always a best practice to add the explicit wait after loading the URL. I am able to click the Account link based on the below modified XPath.
Xpath: //nav//li[#id='li_myaccount']//a
Working Code:
driver.get("https://www.phptravels.net/");
WebDriverWait wait=new WebDriverWait(driver,10);
//wait is added in order to complete the page loading
wait.until(ExpectedConditions.titleContains("PHPTRAVELS"));
driver.findElement(By.xpath("//nav//li[#id='li_myaccount']//a")).click();
To click() on the element with text as My Account instead of visibilityOfElementLocated() you need to induce WebDriverWait through elementToBeClickable() method and you can use the following solution:
Code Block:
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver=new FirefoxDriver();
driver.get("http://www.phptravels.net");
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//nav[#class='navbar navbar-default']//li[#id='li_myaccount']/a[normalize-space()='My Account']"))).click();
Browser Snapshot:

StaleElementReferenceException Error on Java- selenium

I am getting StaleElementReferenceException when I run my code for selecting "Buy NOW" from flipkart.com. This is what I have, but its not working for me.
public void SelectItemfromPage(){
WebDriver wd = new FirefoxDriver();
wd.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
wd.get("http://www.flipkart.com");
WebElement element = wd.findElement(By.xpath(".//*[#id='fk-top-search-box']"));
element.sendKeys("moto g");
element.submit();
element.findElement(By.xpath(".//*[#id='products']/div/div[1]/div[1]/div/div[1]/a[1]/img")).click();
element.findElement(By.xpath(".//*[#id='fk-mainbody-id']/div/div[7]/div/div[3]/div/div/div[6]/div/div[3]/div[1]/div/div[2]/div/div[2]/form/input[9]")).click();
}
Your approach is all wrong.
You are saving an WebElement and reusing it, that's not the way to go.
When you save a WebElement in an object, in this case element, the WebElement will become stale whenever the DOM changes.
What you need to do is the following:
WebDriver wd = new FirefoxDriver();
wd.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
wd.get("http://www.flipkart.com");
WebElement element = wd.findElement(By.xpath(".//*[#id='fk-top-search-box']"));
element.sendKeys("moto g");
element.submit();
wd.findElement(By.xpath(".//*[#id='products']/div/div[1]/div[1]/div/div[1]/a[1]/img")).click();
wd.findElement(By.xpath(".//*[#id='fk-mainbody-id']/div/div[7]/div/div[3]/div/div/div[6]/div/div[3]/div[1]/div/div[2]/div/div[2]/form/input[9]")).click();

Selenium webdriver :org.openqa.selenium.InvalidElementStateException: Element is disabled and so may not be used for actions

I am getting this error while trying to write to simple code in selenium webdriver to enter a value in google search page and enter.
Following is my code -:
WebDriver driver = new FirefoxDriver(profile);
driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
driver.get("http://www.google.com");
WebElement element=driver.findElement(By.xpath("//input[#id='gs_htif0']"));
boolean b = element.isEnabled();
if (b){
System.out.println("Enabled");
}
element.sendKeys("Test Automation");
element.submit();
Can anyone please help me out with this? How to enable a disabled element?
You are using the wrong 'input' for entering the text. You should be using the following XPath:
//input[#name='q']
Like
WebElement element=driver.findElement(By.xpath("//input[#name='q']"));
This 'input' element accepts the input text just fine.
You can try to run javascript on page:
((JavascriptExecutor) driver).executeScript("document.getElementById('gs_htif0').disabled = false");
or
((JavascriptExecutor) driver).executeScript("arguments[0].disabled = false", element);
See, if this might help,
WebDriver driver = new FirefoxDriver(profile);
driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
driver.get("http://www.google.com");
WebElement element = driver.findElement(By.name("q"));
if(element.isEnabled()) {
System.out.println("Enabled");
element.sendKeys("Test Automation");
element.submit();
}
Try this:
WebDriverWait wait = new WebDriverWait(driver, 40);
driver.get("http://www.google.com");
wait.until(ExpectedConditions.visibilityOfElementLocated(By
.xpath("//input[#id='gs_htif0']")));
driver.findElement(By.xpath("//input[#id='gs_htif0']"))
.sendKeys("Test Automation" + Keys.ENTER);
Or:
public boolean isElementPresent(WebDriver driver, By by)
{
try {
driver.findElement(by);
System.out.print("Enabled");
return true;
} catch (NoSuchElementException ignored) {
return false;
}
}
isElementPresent = isElementPresent(
driver, By.xpath("//input[#id='gs_htif0']"));
if (isElementPresent) {
element.sendKeys("Test Automation");
element.submit();
}
Or change xPath to name selector.
If i am correct then you are using the firebug add-on in the firefox driver to get the path for the searchbox. But the firebug seems to provide a path where the Id for the searchbox is not correct. If you use the inspect element option you can see the difference (in the below image you can spot the difference yourself).

WebDriverWait is not working

I am using Windows 8, IE 10 (java - WebDriver 2.37.0) and I am trying to wait until the element is loaded on the page. I used following code:
WebDriver driver = new FirefoxDriver();
driver.get("http://abc.com");
WebElement myDynamicElement = (
new WebDriverWait(driver, 10).until(
ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));
But it's throwing a timeout exception. If I remove this code, it's able to identify the element on the webdriver.
I tried the same code in other browsers as FireFox, Chrome but its still throwing error.
Any help is appreciated.
Thanks
You're assigning that wait to the variable myDynamicElement. If you don't give the WebElement variable something to do, Selenium will throw that timeout exception. If you just want to wait for the element to be present then there is no need to assign it to a WebElement variable.
WebDriver driver = new FirefoxDriver();
driver.get("http://abc.com");
new WebDriverWait(driver, 10).until(
ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));
If you need to assign that variable for later use then do something with the element.
WebElement myDynamicElement =
new WebDriverWait(driver, 10).until(
ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));
myDynamicElement.isDisplayed();
public static void waitForElementToAppear(Driver driver, By selector, long timeOutInSeconds) {
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
}

Categories