Reach for the deep nested element using Selenium WebDriver (Java) - java

I looked through a lot of topics on Stackoverflow and tried several recommendations but could hardly succeed in resolving my particular case. I'm trying to automate Google Cloud Pricing Calculator using Selenium WebDriver + Java. I need insert the Number of instances (the first input area on the page) using Java code.
My Java code is following:
WebDriver driver = new ChromeDriver();
driver.get("https://cloud.google.com/products/calculator");
new WebDriverWait(driver, 10)
.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//iframe[contains (#name, 'goog_')]")));
WebElement document = driver.findElement(By.xpath("//iframe[contains (#name, 'goog_')]"));
var iframe = document.findElement(By.xpath("//iframe[#id='myFrame']"));
var input = iframe.findElement(By.xpath("//input[#id='input_66']"));
input.click();
input.sendKeys("4");
But NoSuchElementException is thrown when I launch the code: "no such element: Unable to locate element: {"method":"xpath","selector":"//iframe[#id='myFrame']"}.
Xpath is correct but this element is hidden deep into html tree. How can I reach for the element (Number of instances) in this particular case? Thank you in advance!

You first need to switch to the parent iframe element, then switch into the inner iframe and only after that try accessing the input element.
I see you tried to locate the iframe elements but you do not switch into them.
Try this:
WebDriver driver = new ChromeDriver();
driver.get("https://cloud.google.com/products/calculator");
//Find and switch to outer iframe
new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//iframe[contains(#src,'product')]")));
driver.switchTo().frame(driver.findElement(By.xpath("//iframe[contains(#src,'product')]")));
driver.switchTo().frame(driver.findElement(By.xpath("//iframe[#id='myFrame']")));
WebElement input = driver.findElement(By.xpath("//input[#id='input_66']"));
input.click();
input.sendKeys("4");

Can you try with the below line of code?
WebDriver driver = new ChromeDriver();
driver.get("https://cloud.google.com/products/calculator");
new WebDriverWait(driver, 10)
.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//iframe[contains (#name, 'goog_')]")));
WebElement document = driver.findElement(By.xpath("//iframe[contains (#name, 'goog_')]"));
driver.switchTo().frame(document).switchTo().frame("myFrame");
//var iframe = document.findElement(By.xpath("//iframe[#id='myFrame']"));
WebElement ele = driver.findElement(By.xpath("//input[#id='input_66']"));
ele.click();
ele.sendKeys("4");

Related

Unable To Click Paypal Button Continue With Selenium

My code begins by signing me into PayPal, then signing into eBay and navigating to the pay fees page, then checking out with PayPal. The final "Continue" button I can't click/submit. I've tried by xpath, id and class. I even tried sending TAB 7x until the Continue button and then sending Enter but that didn't work.
I have found this discussion but I'm not sure how to make it work for me.
PayPal Sandbox checkout 'continue button' - Unable to locate element: - C# WebDriver
Here's a screenshot of the PayPal code and page I'm trying to do.
//Chrome WebDriver specific
System.setProperty("webdriver.chrome.driver", "C:\\automation\\drivers\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize(); //maximise webpage
WebDriverWait wait = new WebDriverWait(driver, 20);
//navigate to Paypal
driver.get("https://www.paypal.com/uk/signin");
//wait 2.5s for the page to load
try {
Thread.sleep(2500);
}
catch (Exception e) {
e.printStackTrace();
}
WebElement paypalEmail = driver.findElement(By.id("email"));
paypalEmail.sendKeys("******");
//wait 2.5s for the page to load
try {
Thread.sleep(2500);
}
catch (Exception e) {
e.printStackTrace();
}
WebElement paypalSubmit = driver.findElement(By.id("btnNext"));
paypalSubmit.click();
String URL = ("https://www.paypal.com/uk/signin");
driver.get(URL);
WebElement form2 = driver.findElement(By.cssSelector(".main form"));
WebElement username = form2.findElement(By.id("password"));
username.sendKeys("******");
WebElement paypalSubmit2 = driver.findElement(By.id("btnLogin"));
paypalSubmit2.click();
//navigate to Ebay
driver.get("https://signin.ebay.co.uk/ws/eBayISAPI.dll?SignIn&ru=https%3A%2F%2Fwww.ebay.com%2F");
// Enter user name , password and click on Signin button
WebElement form = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#mainCnt #SignInForm")));
form.findElement(By.cssSelector("input[type=text][placeholder='Email or username']")).sendKeys("******");
form.findElement(By.cssSelector("input[type=password]")).sendKeys("******");
form.findElement(By.id("sgnBt")).click();
driver.get("http://cgi3.ebay.co.uk/ws/eBayISAPI.dll?OneTimePayPalPayment");
//WebElement Pay =
driver.findElement(By.xpath("//input[#value='Pay']")).click();
WebDriverWait wait2 = new WebDriverWait(driver, 15);
wait2.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[#id=\"confirmButtonTop\"]")));
driver.findElement(By.xpath("//*[contains(#id,'confirmButtonTop')]")).click();
}
}
Based on your given screenshot one of following should work to click on continue button :
Method 1 :
WebElement paypalSubmit = driver.findElement(By.xpath("//input[#data-test-id='continueButton']"));
paypalSubmit.click();
Method 2:
By paypalButton=By.xpath("//input[#data-test-id='continueButton']"));
WebElement element=driver.findElement(paypalButton);
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView(true);",element);
js.executeScript("arguments[0].click();", element);
Try 2nd method if you feel your button require bit scroll to bottom to get clickable.
one more xpaths you can use for button if above don't work :
//input[#value='Continue' and #id='confirmButtonTop']
In my experience, paypal likes to use iFrames. If that's true in your case, that means unless you tell webdriver to switch frame contexts, that paypal form will be unavailable to you regardless of your xpath/css selectors.
You can get a list of all available frames currently loaded with this code:
String[] handles = driver.getWindowHandles()
Your actual page will always be the 0th index in that returned array. If paypal is your only iFrame, then you can target the 1th index. Here's a possible solution to that:
String mainPageHandle = handles[0];
String paypalHandle = handles[1];
driver.switchTo().window(paypalHandle);
// Do paypal interactions
driver.switchTo().window(mainPageHandle);
// Back to the main page
There are definitely more robust ways to handle this, and if your page unfortunately has more than one iFrame, then you may need to do more to verify which handle is which, such as test the presence of an element you know is contained within. In general, the frames will load in the same order every time. As a golden path to this problem, this will get you in and out of that iFrame to perform work.
Sometimes the conventional click() doesn't work. In that case, try using the Javascript Executor Click as below.
Make sure you import this class
org.openqa.selenium.JavascriptExecutor
And use this instead of click();
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].click();", driver.findElement(By.xpath(“//input[#data-test-id='continueButton']”)));
Try this and let me know if this works for you.

Cant sendKeys into ebay username field using WebDriver Selenium 3 with Java and chrome

I have been unable to sendKeys text into the username and password field on ebay.
Here is the code:
WebDriver driver = null;
System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver");
driver = new ChromeDriver();
driver.get("http://www.ebay.co.uk");
WebElement myEbay = driver.findElement(By.linkText("My eBay"));
myEbay.click();
WebElement signInForm = driver.findElement(By.id("SignInForm"));
if (signInForm.isDisplayed())
System.out.println("Sign in form is displayed");
WebElement username;
username = driver.findElement(By.cssSelector("input[placeholder=\"Email or username\"]"));
It manages to find the My Ebay link, and verifies that the sign in form exists but the the username and password fields id's change after every refresh of the page.
The username cssSelector seems to be the problem??
EDIT: I have been successful using XPath but this excercise was to make the cssSelector work as there is no reason in theory why it shouldn't!
I have replaced the cssSelector locator with xpath and it is working fine with absolute xpath. Here is the modified code:
WebDriver driver = null;
System.setProperty("webdriver.chrome.driver", "C:\\Users\\vikas\\workspaceNeon\\Eclipse Soft\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("http://www.ebay.co.uk");
WebElement myEbay = driver.findElement(By.linkText("My eBay"));
myEbay.click();
WebElement signInForm = driver.findElement(By.id("SignInForm"));
if (signInForm.isDisplayed())
System.out.println("Sign in form is displayed");
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
WebElement username = driver.findElement(By.xpath("html/body/div[4]/div/div/div/div[5]/div/div[1]/div/div[1]/div[1]/div[2]/div/span/form/div[1]/div[5]/div/div[4]/span[2]/input"));
username.sendKeys("Vikas");
Select all inputs as a list and search for the right one:
// fld seems to be the class of the input field but looking at all input elements should work too
List<WebElement> inputs = driver.findElements(By.className("fld"));
for (WebElement input: inputs) {
if (inputs.getAttribute("placeholder") == "Email or username") {
// ...
}
}
if the username and password webelements changes frequently find div section in the page using xpath and get the exact xpath of username weblement.
Hope this help..

google search results using selenium web driver

I am setting up a test to perform a search and after the search is complete, i want to capture the results line that says "About xxx results (x.xx seconds)"
Here's the code snippet
FirefoxDriver driver = new FirefoxDriver();
driver.get("http://google.com");
driver.manage().window().maximize();
WebElement searchBox = driver.findElementById("lst-ib");
searchBox.sendKeys("search text");
WebElement clickSearch = driver.findElementByXPath("html/body/div/div[3]/form/div[2]/div[2]/div[1]/div[1]/div[2]/div/div/div/button");
clickSearch.click();
WebElement results = driver.findElementByXPath("html/body/div[1]/div[5]/div[4]/div[5]/div[1]/div[1]/div/div/div");
System.out.println(results);
You need to use getText() method to get the text form a element. In your case you need to do something like below,
WebElement results = driver.findElement(By.xpath("html/body/div[1]/div[5]/div[4]/div[5]/div[1]/div[1]/div/div/div"));
System.out.println(results.getText());
The line you need to capture would have the selector:
Css:
#resultStats
Xpath:
//div[#id='resultStats']
If you need to return the text:
//div[#id='resultStats']//text()
Or use find and getText() method.

Drag and drop functionality not working properly in selenium webdriver for chrome browser

I have written below code to drag an element and add it in workspace. There is no error in console window however drap drop is not performed on chrome browser.
WebElement dragElement = driver.findElement(By.xpath("//*[#id='sidebar-wrapper']/div/div/nginclude/div[2]/accordion/div/div[1]/div[2]/div/div/div[1]/div[2]"));
Thread.sleep(4000);
System.out.println("Element Selected to Drag");
WebElement dropElement = driver.findElement(By.xpath("//*[#id='workspace']/div/div/div/div[2]/div/div/div/div[2]/span"));
Thread.sleep(4000);
act.clickAndHold(dragElement).moveToElement(dropElement).release().build().perform();
I have tried multiple times but not able to succeed. Please provide your inputs
You can try give the location of the element
act.clickAndHold(dragElement).perform();
act.moveToElement(dropElement, dropElement.getLocation().getX(), dropElement.getLocation().getY()).perform();
act.release(dropElement).perform();
This is another method provided in the Selenium documentation here: http://www.seleniumhq.org/docs/03_webdriver.jsp#drag-and-drop.
WebElement dragElement = driver.findElement(By.xpath("//*[#id='sidebar-wrapper']/div/div/nginclude/div[2]/accordion/div/div[1]/div[2]/div/div/div[1]/div[2]"));
WebElement dropElement = driver.findElement(By.xpath("//*[#id='workspace']/div/div/div/div[2]/div/div/div/div[2]/span"));
(new Actions(driver)).dragAndDrop(dragElement, dropElement).perform();
You can use below code for drag and drop but I suggest you to optimize your xpath. It might be the real problem for you.
WebElement source = driver.findElement(By.xpath("//*[#id='sidebar-wrapper']/div/div/nginclude/div[2]/accordion/div/div[1]/div[2]/div/div/div[1]/div[2]"));
Thread.sleep(4000);
System.out.println("Element Selected to Drag");
WebElement target = driver.findElement(By.xpath("//*[#id='workspace']/div/div/div/div[2]/div/div/div/div[2]/span"));
Thread.sleep(4000);
Actions builder = new Actions(driver);
Action mouseOverHome = builder.dragAndDrop(source, target).build();
mouseOverHome.perform();
I had a similar issue in Firefox and resolved it by adding an extra movement instruction in front of the moveToElement() instruction, like this:
private void dragAndDrop(WebElement element, WebElement target) {
Actions builder = new Actions(driver);
builder.clickAndHold(element);
builder.moveByOffset(20,20); // THIS was the critical part for me
builder.moveToElement(target);
builder.release();
builder.perform();
}

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();

Categories