I want to click the 'Download' button on the pdf-viewer page using Selenium. This is html code of that page.
I suppose I need to use switchTo().frame() to reach for the element marked with red frame. I use the following Java code for that.
driver.switchTo().frame(driver.findElement(By.xpath("//*[#id='viewer']")));
driver.switchTo().frame(driver.findElement(By.xpath("//*[#id='toolbar']")));
driver.switchTo().frame(driver.findElement(By.xpath("//*[#id='downloads']")));
driver.findElement(By.xpath("//*[#id='download']")).click();
But it doesn't work :( Please, give me some ideas how to solve the problem. Thank you in advance!
As per the screen shot, the Element is in a shadow-root with Mode open.
To get the required element inside the shadow DOM, we need to make use of Javascript.
You can refer This Link about interacting with Shadom DOM
The code would be something like this:
public class shadowdomexample {
WebElement root1 = driver.findElement(By.id("viewer"));
//Get shadow root element
WebElement shadowRoot1 = expandRootElement(root1);
WebElement root2 = shadowRoot1.findElement(By.id("toolbar"));
WebElement shadowRoot2 = expandRootElement(root2);
WebElement root3 = shadowRoot2.findElement(By.id("downloads"));
WebElement shadowRoot3 = expandRootElement(root3);
//This should return the required Element.
WebElement DownloadsElement = shadowRoot3.findElement(By.cssSelector("cr-icon-button[id=downloads]"));
}
//Returns webelement
public WebElement expandRootElement(WebElement element) {
WebElement ele = (WebElement) ((JavascriptExecutor) driver)
.executeScript("return arguments[0].shadowRoot",element);
return ele;
}
I used explicit waits and I have the warning:
org.openqa.selenium.WebDriverException:
Element is not clickable at point (36, 72). Other element would receive
the click: ...
Command duration or timeout: 393 milliseconds
If I use Thread.sleep(2000) I don't receive any warnings.
#Test(dataProvider = "menuData")
public void Main(String btnMenu, String TitleResultPage, String Text) throws InterruptedException {
WebDriverWait wait = new WebDriverWait(driver, 10);
driver.findElement(By.id("navigationPageButton")).click();
try {
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(btnMenu)));
} catch (Exception e) {
System.out.println("Oh");
}
driver.findElement(By.cssSelector(btnMenu)).click();
Assert.assertEquals(driver.findElement(By.cssSelector(TitleResultPage)).getText(), Text);
}
WebDriverException: Element is not clickable at point (x, y)
This is a typical org.openqa.selenium.WebDriverException which extends java.lang.RuntimeException.
The fields of this exception are :
BASE_SUPPORT_URL : protected static final java.lang.String BASE_SUPPORT_URL
DRIVER_INFO : public static final java.lang.String DRIVER_INFO
SESSION_ID : public static final java.lang.String SESSION_ID
About your individual usecase, the error tells it all :
WebDriverException: Element is not clickable at point (x, y). Other element would receive the click
It is clear from your code block that you have defined the wait as WebDriverWait wait = new WebDriverWait(driver, 10); but you are calling the click() method on the element before the ExplicitWait comes into play as in until(ExpectedConditions.elementToBeClickable).
Solution
The error Element is not clickable at point (x, y) can arise from different factors. You can address them by either of the following procedures:
1. Element not getting clicked due to JavaScript or AJAX calls present
Try to use Actions Class:
WebElement element = driver.findElement(By.id("navigationPageButton"));
Actions actions = new Actions(driver);
actions.moveToElement(element).click().build().perform();
2. Element not getting clicked as it is not within Viewport
Try to use JavascriptExecutor to bring the element within the Viewport:
WebElement myelement = driver.findElement(By.id("navigationPageButton"));
JavascriptExecutor jse2 = (JavascriptExecutor)driver;
jse2.executeScript("arguments[0].scrollIntoView()", myelement);
3. The page is getting refreshed before the element gets clickable.
In this case induce ExplicitWait i.e WebDriverWait as mentioned in point 4.
4. Element is present in the DOM but not clickable.
In this case induce ExplicitWait with ExpectedConditions set to elementToBeClickable for the element to be clickable:
WebDriverWait wait2 = new WebDriverWait(driver, 10);
wait2.until(ExpectedConditions.elementToBeClickable(By.id("navigationPageButton")));
5. Element is present but having temporary Overlay.
In this case, induce ExplicitWait with ExpectedConditions set to invisibilityOfElementLocated for the Overlay to be invisible.
WebDriverWait wait3 = new WebDriverWait(driver, 10);
wait3.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("ele_to_inv")));
6. Element is present but having permanent Overlay.
Use JavascriptExecutor to send the click directly on the element.
WebElement ele = driver.findElement(By.xpath("element_xpath"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", ele);
In case you need to use it with Javascript
We can use arguments[0].click() to simulate click operation.
var element = element(by.linkText('webdriverjs'));
browser.executeScript("arguments[0].click()",element);
I ran into this error while trying to click some element (or its overlay, I didn't care), and the other answers didn't work for me. I fixed it by using the elementFromPoint DOM API to find the element that Selenium wanted me to click on instead:
element_i_care_about = something()
loc = element_i_care_about.location
element_to_click = driver.execute_script(
"return document.elementFromPoint(arguments[0], arguments[1]);",
loc['x'],
loc['y'])
element_to_click.click()
I've also had situations where an element was moving, for example because an element above it on the page was doing an animated expand or collapse. In that case, this Expected Condition class helped. You give it the elements that are animated, not the ones you want to click. This version only works for jQuery animations.
class elements_not_to_be_animated(object):
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
try:
elements = EC._find_elements(driver, self.locator)
# :animated is an artificial jQuery selector for things that are
# currently animated by jQuery.
return driver.execute_script(
'return !jQuery(arguments[0]).filter(":animated").length;',
elements)
except StaleElementReferenceException:
return False
You can try
WebElement navigationPageButton = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.id("navigationPageButton")));
navigationPageButton.click();
Scrolling the page to the near by point mentioned in the exception did the trick for me. Below is code snippet:
$wd_host = 'http://localhost:4444/wd/hub';
$capabilities =
[
\WebDriverCapabilityType::BROWSER_NAME => 'chrome',
\WebDriverCapabilityType::PROXY => [
'proxyType' => 'manual',
'httpProxy' => PROXY_DOMAIN.':'.PROXY_PORT,
'sslProxy' => PROXY_DOMAIN.':'.PROXY_PORT,
'noProxy' => PROXY_EXCEPTION // to run locally
],
];
$webDriver = \RemoteWebDriver::create($wd_host, $capabilities, 250000, 250000);
...........
...........
// Wait for 3 seconds
$webDriver->wait(3);
// Scrolls the page vertically by 70 pixels
$webDriver->executeScript("window.scrollTo(0, 70);");
NOTE: I use Facebook php webdriver
If element is not clickable and overlay issue is ocuring we use arguments[0].click().
WebElement ele = driver.findElement(By.xpath("//div[#class='input-group-btn']/input"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", ele);
The best solution is to override the click functionality:
public void _click(WebElement element){
boolean flag = false;
while(true) {
try{
element.click();
flag=true;
}
catch (Exception e){
flag = false;
}
if(flag)
{
try{
element.click();
}
catch (Exception e){
System.out.printf("Element: " +element+ " has beed clicked, Selenium exception triggered: " + e.getMessage());
}
break;
}
}
}
In C#, I had problem with checking RadioButton,
and this worked for me:
driver.ExecuteJavaScript("arguments[0].checked=true", radio);
Can try with below code
WebDriverWait wait = new WebDriverWait(driver, 30);
Pass other element would receive the click:<a class="navbar-brand" href="#"></a>
boolean invisiable = wait.until(ExpectedConditions
.invisibilityOfElementLocated(By.xpath("//div[#class='navbar-brand']")));
Pass clickable button id as shown below
if (invisiable) {
WebElement ele = driver.findElement(By.xpath("//div[#id='button']");
ele.click();
}
I am coding a program in Java using WebDriver and am having a little bit of trouble getting the text after the select webElement.
The HTML code for the part of the website that I want is as follows:
<select name="language" id="langSelect" style="width:100px;">
<option value="1" >Français</option>
</select>
</div>
<div id="content">
<div id="Pagination"></div>
<div id="mid">
</div>
</div>
The textbox class codes for a search bar and a drop down bar of languages
My Java code is currently able to open chrome using the chrome driver and is able to type into the search bar. I am however not able to get the text that results from the entry.
Image
In the image here, I entered "avoir" into the search bar, and I want all of the text inside the boxes after which do not seem to have any id's or names to be used inside the xpath.
Can someone please help me in finding how to get and save the text from those fields after the dropdown language menu?
Thank you in advance!
The code I have so far:
//import statements not shown
public class WebScraper {
public WebScraper() {
}
public WebDriver driver = new ChromeDriver();
public void openTestSite() {
driver.navigate().to(the URL for the website);
}
public void enter(String word) {
WebElement query_editbox =
driver.findElement(By.id("query"));
query_editbox.sendKeys(word);
query_editbox.sendKeys(Keys.RETURN);
}
public void getText() {
//List<WebElement> searchResults =
driver.findElements(By.xpath("//div[#id='mid']/div"));
// Writer writer = new BufferedWriter(new
OutputStreamWriter(new FileOutputStream("status.txt"),
"utf-8"));
//int[] index = {0};
WebElement result=driver.findElement(By.id("mid"));
System.out.println(result.getText());
}
public static void main(String[] args) throws IOException {
System.setProperty("webdriver.chrome.driver", "chromedriver");
System.out.println("Hello");
WebScraper webSrcaper = new WebScraper();
webSrcapper.openTestSite();
webSrcapper.enter("avoir");
webSrcapper.getText();
System.out.println("Hello");
}
}
I have specified three approaches to extract the text from the result box. Please check all the approaches and use the required approach.
If you want to extract all the text, then you can find the element of the result box and then you can get the Text from that.
WebElement result=driver.findElement(By.id("mid"));
System.out.println(result.getText());
If you want to extract the Text based on the Section by section, then you can go with the below approach,
List<WebElement> sectionList=driver.findElements(By.xpath("//div[#id='mid']/div"));
int i=0;
for(WebElement element:sectionList){
System.out.println("Section "+i+":"+element.getText());
i++;
}
If you want to extract the text from specific section, then you can do with the below approach
List<WebElement> sectionList=driver.findElements(By.xpath("//div[#id='mid']/div"));
int i=0;
//Inorder to get the Section 3 Content
int section=2;
for(WebElement element:sectionList){
if(section==i){
System.out.println("Section "+i+":"+element.getText());
}
i++;
}
Edit: To address followup question
I would suggest to use some explicit wait after doing some action which resulting in some element rendering. In your code, after doing some modification, I am getting the result as expected.
In openTestSite method, I have just added the explicit wait to ensure the page load after loading the URL
In enter method, actually you are getting the autocomplete suggestion after entering the query value .So, we need to just select the value from the autocomplete.
In getText method, Search result is taking more time.So, we need to add some explicit wait using any one of the dynamically loading element locator.
Code:
openTestSite Method:
public void openTestSite() {
//driver.navigate().to(the URL for the website);
driver.get("https://wonef.fr/try/");
driver.manage().window().maximize();
//Explicit wait is added after the Page load
WebDriverWait wait=new WebDriverWait(driver,20);
wait.until(ExpectedConditions.titleContains("WoNeF"));
}
enter Method:
public void enter(String word) {
WebElement query_editbox =
driver.findElement(By.id("query"));
query_editbox.sendKeys(word);
//AutoComplete is happening even after sending the Enter Key.
// So, Value needs to be selected from the autocomplete
WebDriverWait wait=new WebDriverWait(driver,20);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[#class='autocomplete']/div")));
List<WebElement> matchedList=driver.findElements(By.xpath("//div[#class='autocomplete']/div"));
System.out.println(matchedList.size());
for(WebElement element : matchedList){
if(element.getText().equalsIgnoreCase(word)){
element.click();
}
}
//query_editbox.sendKeys(Keys.RETURN);
}
getText Method:
public void getText() {
WebDriverWait wait=new WebDriverWait(driver,20);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[#id='mid']/div")));
WebElement result=driver.findElement(By.id("mid"));
System.out.println(result.getText());
}
I have tested with the above modified code and it is working fine.
In order to inspect the relevant results for your query, common strategy would be to load a list of search results:
List<WebElement> searchResults = driver.findElements(By.xpath("//div[#id='mid']/div"));
Now you can use stream to iterate over the list and extract your relevant text, by getting the text from child elements of each result:
int[] index = {0};
searchResults.stream().forEach(result -> {
System.out.println("Printing query result of index: " + index[0]);
result.findElements(By.xpath(".//*")).stream().forEach(webElement -> {
try {
System.out.println(webElement.getText());
} catch (Exception e) {
// Do nothing
}
});
index[0]++;
});
And you would get the output:
I have the following problem: I am using the selenium webdriver with Java and want to extract all links of a webpage. Some links are generated on demand. That means with a mouseover on the menulinks there will be generated more links. When I load the page these links are not there.
I tried to first extract the menu-navigation-links, do a mouseover and then ask the driver for the "new" links. But it seems that there a no "new" links.
WebElement mainNavi = element.findElement(By.className("navigation"));
Actions actions = new Actions(driver);
List<WebElement> menuHoverLinks = new ArrayList<WebElement>();
menuHoverLinks.addAll(mainNavi.findElements(By.cssSelector("a")));
for (WebElement menuHoverLink : menuHoverLinks) {
Actions hoverOverRegistrar = actions.moveToElement(menuHoverLink);
hoverOverRegistrar.perform();
}
First: Is my idea right? Is it possible to do so? If yes, what am I doing wrong?
Thanks in advance!
If the links are generated dynamically then they may not exist initially. You should use Implicit Waits after you click on the menu to allow the webpage to load up the new content before trying to query them.
Instead of using Actions, consider using WebElement, which supports clicking.
For example, You might say something like
// do an implicit wait until the menu is fully loaded
List<WebElement> elmts = driver.findElements(By.cssSelector("a"));
for (WebElement elmt : elmts) {
elmt.click();
}
private static String[] links = null;
private static int linksCount = 0;
public static void main(String[] args){
driver.get("basic url");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
List<WebElement> all_link_webpage=driver.findElements(By.tagName("a"));
linksCount = all_link_webpage.size();
System.out.println(linksCount);
links= new String[linksCount];
for(int i=0;i<linksCount;i++)
{
links[i] = all_link_webpage.get(i).getAttribute("href");
System.out.println(all_link_webpage.get(i).getAttribute("href"));
}
}
This will help you to make a count of all links in the webpage and print the links in the console. i hope it can helpful. Moreover am not sure about mouse hover links.. :) thankq.
Can anyone help me to read a label text from selenium webdriver
The for attribute value and label text are entirely different
Assuming the label looks in HTML something like this:
<span id="spannyspan" title="the Title of SPAN">The Text</span>
then the WebElement will be best approached like this:
WebDriver driver = new FirefoxDriver();
WebElement theSpan = driver.findElement(By.id("spannyspan"));
String title = theSpan.getAttribute("title");
String label = theSpan.getText();
System.out.println(title); // will return "the Title of SPAN"
System.out.println(label); // will return "The Text"
// both without apostrophes ofcourse
If this does not help please provide sample HTML of label which you are trying to fetch
Suppose there is a label contain text "hello":
<label>hello</label>
then what you have to do is:
# first find this element using xpath or css locator and store that into WebElement object:
WebElement label = driver.findElement(By.xpath("//label[contains(text(),'hello')]");
# After that using getText() method you can get the text of the label element.getText() method return value in string so,store the value in the string variable
String lbltext = label.getText();
# After that if you want to print the value then
System.out.println("text = "+lbltext);