how to google search using dynamic xpath? - java

I am trying to automate the Google Search for "Java" and when it provides a list, I want to select "java interview questions".
I tried using the below xpath, but the script is failing.
List<WebElement> list = driver.findElements(By.xpath("//ul[#role ='listbox']//li/descendent::div[#class='sbl1']"));
Below is my code for the same -
public class GoogleSearchTest {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver" , "C:/Users/User/Desktop/Selenium Drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.google.com");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.findElement(By.name("q")).sendKeys("Java");
List<WebElement> list = driver.findElements(By.xpath("//ul[#role ='listbox']//li/descendent::div[#class='sbl1']"));
System.out.println("Total no of suggestions in search box::" +list.size());
for(int i=0; i<list.size();i++) {
System.out.println(list.get(i));
if(list.get(i).getText().contains("Java Tutorial")) {
list.get(i).click();
break;
}
}
}
}

I think you are using an invalid xpath locator and you need to give some delay before identifying & fetching the elements, try the below code :
driver.get("http://www.google.com");
driver.findElement(By.name("q")).sendKeys("Java");
Thread.sleep(1000);
List<WebElement> list = driver.findElements(By.xpath("//ul[#role ='listbox']//li"));
System.out.println("Total no of suggestions in search box :: " +list.size());
for(int i=0; i<list.size();i++) {
System.out.println(list.get(i));
if(list.get(i).getText().trim().contains("java interview questions") || list.get(i).getText().trim().equalsIgnoreCase("java interview questions")) {
list.get(i).click();
break;
}
}
Below is the screenshot which describes matching xpath:

No sure why you have to iterate through all the list items, when you can handle this with simple xpath. Here is the code that worked for me.
driver.get("http://www.google.com");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.findElement(By.name("q")).sendKeys("Java");
WebElement searchElement = driver.findElement(By.xpath("//div[#class='suggestions-inner-container']//span[.='java salon']"));
System.out.println(searchElement.getText());
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();",searchElement);
Thread.sleep(1000); // just added time to make sure you will see the page navigation is successful.
driver.quit();

simple. You have spelling mistake in the xpath. Its descendant and not descendant.
//ul[#role='listbox']//li/descendant::div[#class='sbtc']
Use Chropath, its shows you when the xpath is invalid

That xpath appears to be invalid. I think it would be easiest to find the elements by css using their class, like this:
List<WebElement> list = driver.findElements(By.cssSelector('li.sbct'));

Related

Unable to find locators(Xpath,Css) ,in the webpage

I am trying to automate application,tried first to find xpath or CSS locators unable to find looks no frame also inside the element.
I am able to handle using JavaScript but unable to enter full text in the search box,it's trimming some text,,please help me.
JavaScript which i tried.
((JavascriptExecutor)driver).executeScript("return document.querySelector('#app').shadowRoot.querySelector('#base > wego-search-form').shadowRoot.querySelector('div > wego-hotel-search-form').shadowRoot.querySelector('#loc').shadowRoot.querySelector('#item0 > div.disable-select.city-country-name').click();");
((JavascriptExecutor)driver).executeScript("return document.querySelector('#app').shadowRoot.querySelector('#base > wego-search-form').shadowRoot.querySelector('div > wego-hotel-search-form').shadowRoot.querySelector('#dates').shadowRoot.querySelector('#depart').shadowRoot.querySelector('#btn').click();");
My scenario i want to click search form and enter some destination details,If possible anyway i can handle this case using locators suggest me
Shadow DOM Elements are used in this website. Shadow DOM provides encapsulation for the JavaScript, CSS, and templating in a Web Component.
Shadow DOM allows hidden DOM trees to be attached to elements in the
regular DOM tree — this shadow DOM tree starts with a shadow root,
underneath which can be attached to any elements you want, in the same
way as the normal DOM.
Refer this To get details about it or for more details Google it.
Now handle Shadow element take reference from this blog. I've tried the below code to enter text as you expected and its working for me.
public static WebDriver driver;
public static void main(String[] args){
System.setProperty("webdriver.chrome.driver", "driver_path");
driver = new ChromeDriver();
driver.get("https://www.wego.com.my/hotels");
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.manage().window().maximize();
WebElement root1 = driver.findElement(By.id("app"));
WebElement shadowRoot1 = expandRootElement(root1);
WebElement root2 = shadowRoot1.findElement(By.tagName("wego-search-form"));
WebElement shadowRoot2 = expandRootElement(root2);
WebElement root3 = shadowRoot2.findElement(By.tagName("wego-hotel-search-form"));
WebElement shadowRoot3 = expandRootElement(root3);
WebElement root4 = shadowRoot3.findElement(By.id("loc"));
WebElement shadowRoot4 = expandRootElement(root4);
shadowRoot4.findElement(By.cssSelector("div.root-container div.container")).click();
WebElement element = shadowRoot4.findElement(By.id("searchKeywordInput"));
Actions action = new Actions(driver);
action.click(element).sendKeys(Keys.chord(Keys.CONTROL, "a"));
element.sendKeys(Keys.DELETE);
element.sendKeys("narendra");
}
public static WebElement expandRootElement(WebElement element) {
WebElement newElement = (WebElement) ((JavascriptExecutor) driver).executeScript("return arguments[0].shadowRoot", element);
return newElement;
}
Updated
As an alternative of sendKeys(), JavascriptExecutor can be used to set the value of text box. Use below code
WebElement element = shadowRoot4.findElement(By.id("searchKeywordInput"));
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
javascriptExecutor.executeScript("arguments[0].value='Your Text Goes Here';", element);
I've tested this so many time and this is working fine in each case.
Note: using JavascriptExecutor may not trigger the search result auto suggestion.

Search for button in iframe

I have an application with multiple iframes in the same screen. These iframes have different names every session, so I would like to search within the application for a button within one of the iframes with the name "Pesonal". This iframe-name should be saved to be used in another method. Anybody an idea how to do this?
Please close / delete this topic as I have found the solution:
public WebElement findElement(By locator) {
driver.switchTo().defaultContent();
//list all iframes
List<WebElement> iframeList = driver.findElements(By.tagName(("iframe")));
final List<WebElement> foundElements = new ArrayList<>();
iframeList.forEach(iframe -> {
driver.switchTo().frame(iframe);
List<WebElement> foundElementList = driver.findElements(locator);
if (foundElementList.size() > 0) {
foundElements.addAll(foundElementList);
} else driver.switchTo().defaultContent();
});
return foundElements.get(0);
}

Unable to select from the drop-down option

Unable to select "Delhi" from the drop down option.....the x-path might be wrong...
public class spicejet {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver","C:\\Users\\hp\\Desktop\\Colin\\chromedriver.exe");
WebDriver driver= new ChromeDriver();
driver.get("https://www.spicejet.com/");
driver.findElement(By.id("ctl00_mainContent_rbtnl_Trip_0")).click();
driver.findElement(By.id("ctl00_mainContent_ddl_originStation1_CTXT")).click();
driver.findElement(By.xpath("//a[contains(#text,'Kochi')]")).click();
driver.findElement(By.id("ctl00_mainContent_ddl_destinationStation1_CTXT")).click();
List<WebElement> list=driver.findElements(By.xpath("//div[contains(#class,'dropdownDiv')]//ul//li//a"));
System.out.println(list.size());
for(int i=0; i<list.size(); i++) {
System.out.println(list.get(i).getText());
if(list.get(i).getText().contains("Delhi (DEL)"));{
list.get(i).click();
break;
Your xpath is correct. However there is terminator ; used with your if condition like if(list.get(i).getText().contains("Delhi (DEL)")); because of which the if condition is getting terminated and the first element from the list is getting selected from the line of code mentioned in the next line. You need to remove ; from the if condition and then it would work just fine.
Addition to that, you can also improve your xpath with the one i am mentioning below:
List<WebElement> list=driver.findElements(By.xpath("//div[#class='dropdownDiv']//li"));

selenium dynamically click li item

I am trying to dynamically search an "li" tag item and double-click on this website: www.jstree.com (the right-top hierarchy tree sample). The code does find the WebElement but does not do anything. I am trying as follows. Can someone please point to what I am doing wrong? I am using Firefox 35.0.1 and selenium 2.44.0.
driver.get(baseUrl + "http://www.jstree.com/");
WebElement we = driver.findElement(By.xpath("/html/body/div/div/div[1]/div[1]/div[2]/div[1]/ul/li[1]/ul"));
Actions action = new Actions(driver);
List<WebElement> liItems = we.findElements(By.tagName("li"));
for(WebElement liItem:liItems)
{
System.out.println(liItem.getText());
if(liItem.getText().startsWith("initially open"))
{
System.out.println("Found it...");
liItem.click();
action.moveToElement(liItem).doubleClick().build().perform();
break;
}
}
I ended up doing this:
Modified the selector to make sure ONLY the expected elements are returned. It helps a lot in terms of execution time and reducing the number of unwanted loopings. And, then find the element in run time and use Action() on that to perform double click. I also update the Selenium binding as #alecxe suggested to work with latest Firefox
public void DemoTest() throws InterruptedException {
List<WebElement> liItems = driver.findElements(By.xpath("//*[contains(text(),'initially open')]"));
for(WebElement liItem:liItems)
{
Actions actions = new Actions(driver);
actions.moveToElement(liItem).doubleClick().build().perform();
}
}

How to find an Element by index in selenium webdriver for java

Im trying to automate the Google Images page:
https://www.google.com/search?q=pluralsight&biw=1416&bih=685&source=lnms&tbm=isch&sa=X&ei=qGd6VN6bEZTooAT7q4C4BQ&sqi=2&ved=0CAgQ_AUoAw
All the images have the same class but no id and the results are constantly changing. So I would like to be able to click on the images based on their index.
I know how to do it in C#...but I cant figure out how to specify in the index in Java. When I try to select an index beyond 0, I get and IndexOutOfBounds error, but i cant figure out why
WebElement image = chromeDriver.findElement(By.className("rg_di"));
WebElement imageLink = image.findElements(By.tagName("a")).get(1);
imageLink.click();
Here is the entire code im using...any help would be appreciated:
System.setProperty("webdriver.chrome.driver", "/Users/user/chromedriver");
WebDriver chromeDriver = new ChromeDriver();
chromeDriver.get("http://www.google.com");
WebElement searchBox = chromeDriver.findElement(By.id("gbqfq"));
searchBox.sendKeys("pluralsight");
searchBox.sendKeys(Keys.RETURN);
chromeDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
WebElement imagesLink = chromeDriver.findElement(By.linkText("Images"));
imagesLink.click();
WebElement image = chromeDriver.findElement(By.className("rg_di"));
WebElement imageLink = image.findElements(By.tagName("a")).get(1);
imageLink.click();
Any help would be greatly appreciated
In your code:
WebElement image = chromeDriver.findElement(By.className("rg_di"));
will return the first element found on the page with a class of "rg_di".
That element has only one <a href=... /a> tag in it.
You are getting an IndexOutOfBounds exception because you are asking for the second one (zero based indexing). If you change your final WebElement to:
WebElement imageLink = image.findElements(By.tagName("a")).get(0);
The code should work for you with that small change.
This is my quick version (note the lack of storing elements I only need to do one thing with as WebElements):
public static void main(String[] args) {
// I don't have Chrome installed >.<
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://www.google.com");
WebElement searchBox = driver.findElement(By.id("gbqfq"));
searchBox.sendKeys("pluralsight");
searchBox.sendKeys(Keys.RETURN);
driver.findElement(By.linkText("Images")).click();
WebElement image = driver.findElement(By.className("rg_di"));
image.findElements(By.tagName("a")).get(0).click();
// super-shortened version:
// driver.findElement(By.className("rg_di")).findElements(By.tagName("a")).get(0).click();
}
I'd do:
List<WebElement> we = chromeDriver.findElements(By.cssSelector(".your-class a"));
we.get(1) //should get first element in array
This code worked very well when we have similar object properties for same web buttons, then using
List<WebElement> we = webdriver.findElements(By.cssSelector(""));
and then getting
we.get(1).click();
Thank you so much for posting this answer.
Another solution may be like this:
If the class name and the index of the web element are known, then following code works:
driver.findElement(By.xpath("(//*[#class='android.widget.ImageView'])[18]")).click();

Categories