I am trying to write a code where an user has typed in Python, hit enter and this app "Python tutorial Tutorials Point" is on the 4th page. My logic is: locate this item using getPageSource and keep on clicking on Next button. However 2 problems I see:
1)Pages found 0- I am expecting a lot more pages and the xpath shows 56+
2) It keeps on clicking on next button and goes to page 6 meaning it did not find that book on page 4.
public class AmazonProductSearchTest {
public static WebDriver driver;
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "C:\\Users\\Downloads\\chromedriver_win32\\chromedriver.exe");
driver= new ChromeDriver();
//WebDriverWait wait = new WebDriverWait(driver,30);
driver.get("https://www.amazon.com/");
driver.findElement(By.xpath("//input[#id='twotabsearchtextbox']")).sendKeys("Python");
driver.findElement(By.xpath("//input[#value='Go']")).click();
//Implicit wait till page loads
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
//Scroll down to find pagination
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("window.scrollBy(0,5000)", "");
//Number of Pages
List<WebElement> pagesFound=driver.findElements(By.xpath("//a[contains(#href, '/s?k=python')]"));
System.out.println("Pages found "+ pagesFound.size());
//Will click on Next link until we find a specific book-using page source
while(!driver.getPageSource().equals("Python tutorial Tutorials Point")){
driver.findElement(By.xpath("//a[contains(text(),'Next')]")).click();
if(driver.getPageSource().equals("Python tutorial Tutorials Point")){
System.out.println("Found searched item");
break;
}
}
}
}
I could use some hint/help. Thanks for your time.
pagesFound is referring to Next button (//a[contains(#href, '/s?k=python')]). I believe the pagesFound should use the last disabled number which refer to actual number of pagesFound and not the Next button. Copy pasted above code and the list was empty.
Related
I am trying to move through website pages using the website's page navigator, but it always stops clicking at page 13.
This is the page navigator:
This is my code:
for (int i = 1; i <= numOfPages; i++) {
customWebDriver.getWebDriver().findElement(By.className("css-3a6490")).click();
Thread.sleep(3000);
}
This is the HTML structure:
I have also tried using the element under css-3a6490, css-15a7b5o:
for (int i = 1; i <= numOfPages; i++) {
customWebDriver.getWebDriver().findElement(By.className("css-15a7b5o")).click();
Thread.sleep(3000);
}
but it also didn't work.
Does someone knows what is the problem?
Thanks
Try with:
customWebDriver.getWebDriver().findElement(By.xpath("//button[#class='css-19a323y']//following-sibling::button[1]")).click();
Explanation of Xpath: A button with class css-19a323y (Which is the current selected page) and then selecting the following button (Which is the next available page)
Also use more time for Thread.sleep(3000); because sometimes when you make pagination it takes more time, so better add more time, or using WebdriverWait and Expected conditions, here an example:
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.elementToBeClickable(By.id<locator>));
Summary
I am trying to scrape all first connections' profile links of an account on LinkedIn search page. But since the page loads the rest of the content dynamically (as you scroll down) I can not get the 'Next' page button which is at the end of the page.
Problem description
https://linkedin.com/search/results/people/?facetGeoRegion=["tr%3A0"]&facetNetwork=["F"]&origin=FACETED_SEARCH&page=YOUR_PAGE_NUMBER
I can navigate to the search page using selenium and the link above. I want to know how many pages there are to navigate them all just changing the page= variable of the link above.
To implement that I wanted to check for the existence of Next button. As long as there is next button I would request the next page for scraping. But if you do not scroll down till the bottom of the page -which is where the 'Next' button is- you can not find the Next button nor you can find the information about other profiles because they are not loaded yet.
Here is how it looks when you do not scroll down and take a screenshot of the whole page using firefox screenshot tool.
How I implemented
I can fix this by hard coding a scroll down action into my code and making the driver wait for visibilityOfElementLocated. But I was wondering whether there is any other way better than my approach. And if by the approach the driver can not find the Next button somehow the program exits with the exit code 1.
And when I inspect the requests when I scroll down the page, it is just requests for images and etc as you can see below. I couldn't figure out how the page loads more info about profiles as I scroll down the page.
Source code
Here is how I implemented it in my code. This app is just a simple implementation which is trying to find the Next button on the page.
package com.andreyuhai;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class App
{
WebDriver driver;
public static void main( String[] args )
{
Bot bot = new Bot("firefox", false, false, 0, 0, null, null, null);
int pagination = 1;
bot.get("https://linkedin.com");
if(bot.attemptLogin("username", "pw")){
bot.get("https://www.linkedin.com/" +
"search/results/people/?facetGeoRegion=" +
"[\"tr%3A0\"]&origin=FACETED_SEARCH&page=" + pagination);
JavascriptExecutor js = (JavascriptExecutor) bot.driver;
js.executeScript("scrollBy(0, 2500)");
WebDriverWait wait = new WebDriverWait(bot.driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//button[#class='next']/div[#class='next-text']")));
WebElement nextButton = bot.driver.findElement(By.xpath("//button[#class='next']/div[#class='next-text']"));
if(nextButton != null ) {
System.out.println("Next Button found");
nextButton.click();
}else {
System.out.println("Next Button not found");
}
}
}
}
Another tool for that which I wonder about : LinkedIn Spider
There is this chrome extension called linkedIn Spider
This also does exactly what I am trying to achieve but using JavaScript I guess, I am not sure. But when I run this extension on the same search page. This does not do any scrolling down or loading other pages one by one extract the data.
So my questions are:
Could you please explain me how LinkedIn achieves this? I mean how does it load profile information as I scroll down if not making any request or etc. I really don't know about this. I would appreciate any source links or explanations.
Do you have any better (faster I mean) idea to implement what I am trying to implement?
Could you please explain me how LinkedIn Spider could be working without scrolling down and etc.
I have checked the div structure and the way linkedin is showing the results. So, if you hit the url directly and check the by following xpath: //li[contains(#class,'search-result')] You would find out that all the results are already loaded on the page, but linkedin are showing only 5 results in one go and on scrolling, it shows the next 5 results, however all the results are already loaded on the page and can be found out by the mentioned xpath.
Refer to this image which highlights the div structure and results when you find the results on entering the xpath on hitting the url: https://imgur.com/Owu4NPh and
Refer to this image which highlights the div structure and results after scrolling the page to the bottom and then finding the results using the same xpath: https://imgur.com/7WNR830
You could see the result set is same however there is an additional search-result__occlusion-hint part in the < li > tag in the last 5 results and through this linkedin is hiding the next 5 results and showing only the first 5 results on the first go.
Now comes the implementation part, i have checked "Next" button comes only when you scroll through whole results on the page, so instead of scrolling to a definite coordinates because that can be changed for different screensizes and windows, you can take the results in a list of webelement and get it's size and then scroll to the last element of that list. In this case, if there are total 10 results then the page will be scrolled to the 10th results and if there are only 4 results then the page will be scrolled to the 4th result and after scrolling you can check if the Next button is present on the page or not. For this, you can check the list size of the "Next" button web element list, if the list size is greater than 0, it means the next button is present on the page and if its not greater than 0, that means the Next button is not present on the list and you can stop your execution there.
So to implement it, i have taken a boolean which has an initial value as true and the code will be run in a loop till that boolean becomes false and it will become false when the Next button list size becomes equal to 0.
Please refer to the code below:
public class App
{
WebDriver driver;
// For initialising javascript executor
public Object executeScript(String script, Object... args) {
JavascriptExecutor exe = (JavascriptExecutor) driver;
return exe.executeScript(script, args);
}
// Method for scrolling to the element
public void scrollToElement(WebElement element) {
executeScript("window.scrollTo(arguments[0],arguments[1])", element.getLocation().x, element.getLocation().y);
}
public static void main(String[] args) {
// You can change the driver to bot according to your usecase
driver = new FirefoxDriver();
// Add your direct URL here and perform the login after that, if necessary
driver.get(url);
// Wait for the URL to load completely
Thread.sleep(10000);
// Initialising the boolean
boolean nextButtonPresent = true;
while (nextButtonPresent) {
// Fetching the results on the page by the xpath
List<WebElement> results = driver.findElements(By.xpath("//li[contains(#class,'search-result')]"));
// Scrolling to the last element in the list
scrollToElement(results.get(results.size() - 1));
Thread.sleep(2000);
// Checking if next button is present on the page
List<WebElement> nextButton = driver.findElements(By.xpath("//button[#class='next']"));
if (nextButton.size() > 0) {
// If yes then clicking on it
nextButton.get(0).click();
Thread.sleep(10000);
} else {
// Else setting the boolean as false
nextButtonPresent = false;
System.out.println("Next button is not present, so ending the script");
}
}
}
}
What I have observed was, the content is already loaded in the page and it will be displayed to us when we do the scroll down.
But if we inspect the 'Next >' button by loading the page manually by using the class name 'next' for example like below,
//button[#class='next']
we cannot locate it until we do the scroll down because it is not visible to us. But by using the below XPath, we can identify all the profile links count irrespective of whether they are displayed or not?
//h3[contains(#class, 'search-results__total')]/parent::div/ul/li
As you want to fetch all the profile links from the page, we can use the above XPath help to do that. We will get the links count using the above XPath then we will scroll into each element view at a time and then we will fetch the profile links on the way like below :
// Identifying the all the profile links
List<WebElement> totalProfileLinks = driver.findElements(By.xpath("//h3[contains(#class, 'search-results__total')]/parent::div/ul/li"));
// Looping for getting the profile link
for(int i=1;i<totalProfileLinks.size();i++) {
// Scrolling so that it will be visible
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", totalProfileLinks.get(i));
// Fetching the anchor node
final WebElement link = driver.findElement(By.xpath("(//h3[contains(#class, 'search-results__total')]/parent::div/ul/li//div[contains(#class, 'search-result__info')]//a)["+i+"]"));
// Avoiding the StaleElementReferenceException
new FluentWait<WebDriver>(driver).withTimeout(1, TimeUnit.MINUTES).pollingEvery(1, TimeUnit.SECONDS).ignoring(StaleElementReferenceException.class).until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver arg0) {
return link;
}
});
// Fetching and printing the link from anchor node
System.out.println(link.getAttribute("href").trim());
}
So, if we want to click on the 'Next >' button first we need to check if its present or not(As we have scrolled while fetching the profile links, the 'next' button also get displyed). We can use the help of `driver.findElements();` method to get the matches of that element count and can store it in some List(Because it returns List of WebElements) like below :
List<WebElement> nextButton = driver.findElements(By.className("next"));
The benefit of using the above technique is, the script won't fail if there are no element matches also and we will have an empty list if there are no matches.
Then we can use the size() method of the List interface to get the matches count like below :
int size = nextButton.size();
And if the size is more than 0 then that element is present otherwise not, we can check that condition like below :
if(size > 0) {
nextButton.get(0).click(); // Do some operation like clicking on it
System.out.println("=> 'Next >' button is there and clicked on it...");
} else {
System.out.println("=> 'Next >' button is NOT there...");
}
As the content is loaded and the element is view-able, we will use the JavaScriptExecutor which will locate and clicks on it.
Wrap the above code in while loop and check the presence of the 'Next >' button every time after clicking on the previous 'Next >' button like below :
boolean next = true;
while(next) {
// Checking 'Next >' button is there or not in the page
List<WebElement> nextButton = driver.findElements(By.className("next"));
// If the 'Next >' button is there then clicking on it otherwise stopping the execution
if(nextButton.size() > 0) {
doClickUsingJSE(nextButton.get(0));
System.out.println("=> 'Next >' button is there and clicked on it...");
} else {
next = false;
System.out.println("=> 'Next >' button is NOT there so stopping the execution...");
}
Thread.sleep(1000);
}
Loop will break if the 'if' condition fails in the above code because 'next' will becomes 'false'. And if we use the Fluent Wait then it will help us in avoiding some 'Exceptions' like 'WebDriverException' and 'StaleElementReferenceException'. So I have written one separate method which will wait for an element by avoiding some exceptions and clicks on it if the conditions get satisfied.
Check the code below :
private static void doClickUsingJSE(final WebElement element) {
// Using the Fluent Wait to avoid some exceptions like WebDriverException and StaleElementReferenceException
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(1, TimeUnit.MINUTES).pollingEvery(1, TimeUnit.SECONDS).ignoring(WebDriverException.class, StaleElementReferenceException.class);
WebElement waitedElement = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return element;
}
});
wait.until(ExpectedConditions.visibilityOf(waitedElement));
wait.until(ExpectedConditions.elementToBeClickable(waitedElement));
// Clicking on the particular element using the JavaScriptExcecutor
((JavascriptExecutor) driver).executeScript("arguments[0].click();", waitedElement);
}
As I mentioned about the JavaScriptExecutor earlier, I have included use of that also in the above method only.
Try the below end to end working code :
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import com.google.common.base.Function;
public class BasePage
{
// Declaring WebDriver
private static WebDriver driver;
private static void doClickUsingJSE(final WebElement element) {
// Using the Fluent Wait to avoid some exceptions like WebDriverException and StaleElementReferenceException
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(1, TimeUnit.MINUTES).pollingEvery(1, TimeUnit.SECONDS).ignoring(WebDriverException.class, StaleElementReferenceException.class);
WebElement waitedElement = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return element;
}
});
wait.until(ExpectedConditions.visibilityOf(waitedElement));
wait.until(ExpectedConditions.elementToBeClickable(waitedElement));
// Clicking on the particular element using the JavaScriptExcecutor
((JavascriptExecutor) driver).executeScript("arguments[0].click();", waitedElement);
}
public static void main( String[] args ) throws Exception
{
System.setProperty("webdriver.chrome.driver", "C:\\NotBackedUp\\chromedriver.exe");
// Initializing the Chrome Driver
driver = new ChromeDriver();
// Launching the LinkedIn site
driver.get("https://linkedin.com/search/results/people/?facetGeoRegion=[\"tr%3A0\"]&facetNetwork=[\"F\"]&origin=FACETED_SEARCH&page=YOUR_PAGE_NUMBER");
// You can avoid this and it to your convience way
// As there are no connections in my page, I have used like this
//------------------------------------------------------------------------------------
// Switching to the login from - iframe involved
driver.switchTo().frame(driver.findElement(By.className("authentication-iframe")));
// Clicking on the Sign In button
doClickUsingJSE(driver.findElement(By.xpath("//a[text()='Sign in']")));
// Entering the User Name
WebElement element = driver.findElement(By.id("username"));
doClickUsingJSE(element);
element.sendKeys("something#gmail.com");
// Entering the Password
element = driver.findElement(By.id("password"));
doClickUsingJSE(element);
element.sendKeys("anything"+Keys.ENTER);
// Clicking on the People drop down
Thread.sleep(8000);
element = driver.findElement(By.xpath("//span[text()='People']"));
doClickUsingJSE(element);
// Selecting the All option
Thread.sleep(2000);
element = driver.findElement(By.xpath("//ul[#class='list-style-none']/li[1]"));
element.click();
// Searching something in the LinkedIn search box
Thread.sleep(3000);
element = driver.findElement(By.xpath("//input[#role='combobox']"));
doClickUsingJSE(element);
element.sendKeys("a"+Keys.ENTER);
Thread.sleep(8000);
//------------------------------------------------------------------------------------
boolean next = true;
while(next) {
// Identifying the all the profile links
List<WebElement> totalProfileLinks = driver.findElements(By.xpath("//h3[contains(#class, 'search-results__total')]/parent::div/ul/li"));
// Looping for getting the profile link
for(int i=1;i<totalProfileLinks.size();i++) {
// Scrolling so that it will be visible
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", totalProfileLinks.get(i));
// Fetching the anchor node
final WebElement link = driver.findElement(By.xpath("(//h3[contains(#class, 'search-results__total')]/parent::div/ul/li//div[contains(#class, 'search-result__info')]//a)["+i+"]"));
// Avoiding the StaleElementReferenceException
new FluentWait<WebDriver>(driver).withTimeout(1, TimeUnit.MINUTES).pollingEvery(1, TimeUnit.SECONDS).ignoring(StaleElementReferenceException.class).until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver arg0) {
return link;
}
});
// Fetching and printing the link from anchor node
System.out.println(link.getAttribute("href").trim());
}
// Checking 'Next >' button is there or not in the page
List<WebElement> nextButton = driver.findElements(By.className("next"));
// If the 'Next >' button is there then clicking on it otherwise stopping the execution
if(nextButton.size() > 0) {
doClickUsingJSE(nextButton.get(0));
System.out.println("=> 'Next >' button is there and clicked on it...");
} else {
next = false;
System.out.println("=> 'Next >' button is NOT there so stopping the execution...");
}
Thread.sleep(1000);
}
}
}
I hope it helps... Happy Coding...
I am trying to implement the following scenario
1. Open Chrome browser and open greyhound.com
2. Search a trip by picking a source, destination.
3. Pick a start date, return date.
4. Finally, click on search button to find available buses.
First four fields work fine. After picking the return date, the calendar won't close, which is causing a problem for clicking the search button.
The calendar is overlapping with the search button and makes it non-clickable.
To overcome this, I have used Thread.sleep() to allow some time for the calendar to close and it works fine.
How can I achieve this using selenium wait concept?
Both implicit and explicit waits won't work for me.
public class UsingChrome {
public static void main(String args[]) throws InterruptedException {
//Chrome Driver
System.setProperty("webdriver.chrome.driver", "Y:\\Selenium\\chromedriver.exe");
//Creating driver element
WebDriver driver = new ChromeDriver();
//Implicit Wait
//driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
//To maximize browser window
driver.manage().window().maximize();
//Open webpage
driver.get("https://www.greyhound.com/");
//Scroll
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("window.scrollBy(0,300)", "");
//Select an origin and destination
driver.findElement(By.id("fromLocation")).sendKeys("New York, NY");
driver.findElement(By.id("toLocation")).sendKeys("Boston, MA");
// To input a date using 'sendKeys'
//Choose a Start Date
driver.findElement(By.id("datepicker-from")).click();
driver.findElement(By.id("datepicker-from")).sendKeys("10/22/2017");
//Choose an End Date
driver.findElement(By.id("datepicker-to")).click();
driver.findElement(By.id("datepicker-to")).sendKeys("10/27/2017");
driver.findElement(By.id("datepicker-to")).sendKeys(Keys.ENTER);
//Explicit wait
WebDriverWait wait = new WebDriverWait(driver, 300);
WebElement search = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(".//*[#id=\'fare-search-btn\']")));
search.click();
//Search
//Thread.sleep(3000);
driver.findElement(By.id("fare-search-btn")).click();
//driver.quit();
}
}
In this case you need to wait for the return trip datepicker to close. The return trip datepicker element is
<table class="ui-datepicker-calendar">...</table>
The code to wait for it to close is to wait for the element to be invisible.
new WebDriverWait(driver, 10).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("table.ui-datepicker-calendar")));
Your code was waiting for the Search button to be visible. Technically it's already visible, it's just covered by the datepicker dropdown. Visibility in Selenium has to do with not invisible (display: none, etc.) rather than I can't see it because it's covered by another element.
I am trying to dynamically select items from a drop down menu based on input. This isn't really a problem unless values share a name. For instance if this is my Cucumber statement
When I go to the "Inventory" / "Inventory" application
When I call this method:
#When("^I go to the \"([^\"]*)\" / \"([^\"]*)\" application$")
public void i_go_to_the_application(String hoverMenu, String subMenuName) throws Throwable {
Actions actions = new Actions(driver);
WebElement menuHoverLink = driver.findElement(By.linkText(hoverMenu));
actions.moveToElement(menuHoverLink);
Thread.sleep(1000);
WebElement submenu = driver.findElement(By.xpath("//span[.='" + subMenuName + "']"));
actions.moveToElement(submenu);
actions.click().perform();
Thread.sleep(4000);
My test crash because it cannot find the subMenuElement. This code works swimmingly if the menu names are different such as Inventory > Items.
Now I've already checked this question
Selenium: handling multiple inputs with same xpath
However the solution provide doesn't seem to be helpful since both elements are in the drop down menu with one being a submenu to that one: Inventory > Inventory
I ran this through the selenium IDE and no matter how many ways I've tried to "find" the Inventory element it only ever finds one item. Since the user of my tests can select any number of items from a drop down menu and then subsequent submenus, I can't rely on IDs. Is there a way to select the first menu item for sure and then select the submenu item.
Change this from a partial link text to a xpath search
WebElement menuHoverLink = driver.findElement(By.linkText(hoverMenu));
to below
WebElement menuHoverLink = driver.findElement("//a[.='" + hoverMenu + "']");
You just need the 2 xpaths to be different so even if the names are same you will get your result.
It seems submemu Inventory element existing inside main menu Inventory element. Then you should try to find submemu element on the main menu context as below :-
Actions actions = new Actions(driver);
WebElement menuHoverLink = driver.findElement(By.linkText(hoverMenu));
actions.moveToElement(menuHoverLink);
WebElement submenu = new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfNestedElementLocatedBy(menuHoverLink, By.xpath(".//span[.='" + subMenuName + "']")))
actions.moveToElement(submenu);
actions.click().perform();
I want to do mouseover function over a drop down menu. When we hover over the menu, it will show the new options.
I tried to click the new options using the xpath. But cannot click the menus directly.
So, as the manual way I am trying to hover over the drop down menu and then will click the new options.
Actions action = new Actions(webdriver);
WebElement we = webdriver.findElement(By.xpath("//html/body/div[13]/ul/li[4]/a"));
action.moveToElement(we).build().perform();
Its not really possible to perform a 'mouse hover' action, instead you need to chain all of the actions that you want to achieve in one go. So move to the element that reveals the others, then during the same chain, move to the now revealed element and click on it.
When using Action Chains you have to remember to 'do it like a user would'.
Actions action = new Actions(webdriver);
WebElement we = webdriver.findElement(By.xpath("html/body/div[13]/ul/li[4]/a"));
action.moveToElement(we).moveToElement(webdriver.findElement(By.xpath("/expression-here"))).click().build().perform();
None of these answers work when trying to do the following:
Hover over a menu item.
Find the hidden element that is ONLY available after the hover.
Click the sub-menu item.
If you insert a 'perform' command after the moveToElement, it moves to the element, and the sub-menu item shows for a brief period, but that is not a hover. The hidden element immediately disappears before it can be found resulting in a ElementNotFoundException. I tried two things:
Actions builder = new Actions(driver);
builder.moveToElement(hoverElement).perform();
builder.moveToElement(clickElement).click().perform();
This did not work for me. The following worked for me:
Actions builder = new Actions(driver);
builder.moveToElement(hoverElement).perform();
By locator = By.id("clickElementID");
driver.click(locator);
Using the Actions to hover and the standard WebDriver click, I could hover and then click.
Based on this blog post I was able to trigger hovering using the following code with Selenium 2 Webdriver:
String javaScript = "var evObj = document.createEvent('MouseEvents');" +
"evObj.initMouseEvent(\"mouseover\",true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);" +
"arguments[0].dispatchEvent(evObj);";
((JavascriptExecutor)driver).executeScript(javaScript, webElement);
This code works perfectly well:
Actions builder = new Actions(driver);
WebElement element = driver.findElement(By.linkText("Put your text here"));
builder.moveToElement(element).build().perform();
After the mouse over, you can then go on to perform the next action you want on the revealed information
Check this example how we could implement this.
public class HoverableDropdownTest {
private WebDriver driver;
private Actions action;
//Edit: there may have been a typo in the '- >' expression (I don't really want to add this comment but SO insist on ">6 chars edit"...
Consumer < By > hover = (By by) -> {
action.moveToElement(driver.findElement(by))
.perform();
};
#Test
public void hoverTest() {
driver.get("https://www.bootply.com/render/6FC76YQ4Nh");
hover.accept(By.linkText("Dropdown"));
hover.accept(By.linkText("Dropdown Link 5"));
hover.accept(By.linkText("Dropdown Submenu Link 5.4"));
hover.accept(By.linkText("Dropdown Submenu Link 5.4.1"));
}
#BeforeTest
public void setupDriver() {
driver = new FirefoxDriver();
action = new Actions(driver);
}
#AfterTest
public void teardownDriver() {
driver.quit();
}
}
For detailed answer, check here - http://www.testautomationguru.com/selenium-webdriver-automating-hoverable-multilevel-dropdowns/
I found this question looking for a way to do the same thing for my Javascript tests, using Protractor (a javascript frontend to Selenium.)
My solution with protractor 1.2.0 and webdriver 2.1:
browser.actions()
.mouseMove(
element(by.css('.material-dialog-container'))
)
.click()
.perform();
This also accepts an offset (i'm using it to click above and left of an element:)
browser.actions()
.mouseMove(
element(by.css('.material-dialog-container'))
, -20, -20 // pixel offset from top left
)
.click()
.perform();
Sample program to mouse hover using Selenium java WebDriver :
public class Mhover {
public static void main(String[] args){
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://www.google.com");
WebElement ele = driver.findElement(By.id("gbqfba"));
Actions action = new Actions(driver);
action.moveToElement(ele).build().perform();
}
}
You can try:
WebElement getmenu= driver.findElement(By.xpath("//*[#id='ui-id-2']/span[2]")); //xpath the parent
Actions act = new Actions(driver);
act.moveToElement(getmenu).perform();
Thread.sleep(3000);
WebElement clickElement= driver.findElement(By.linkText("Sofa L"));//xpath the child
act.moveToElement(clickElement).click().perform();
If you had case the web have many category, use the first method. For menu you wanted, you just need the second method.
Try this re-usable method,
public void MoveThePoiterToElement(By by){
log.info("Moving the cursor to the element");
Actions action = new Actions(driver);
action.moveToElement(driver.findElement(by));
action.build().perform();
log.info("Cursor moved to the element");
}
I tried that and it worked normal
action = ActionChains(driver)
element = driver.find_element_by_xpath("XPath_selector")
action.move_to_element(element).perform()