Some of WebElements are not recognized by WebDriver, WebDriver fails to find the element which is not visible in browser's visible area.
In order to make the WebElement viewable by WebDriver, We need to make that element to visible in browser's view to do scroll down on particular div!
How can I perform my action(scroll down and click) on particular area of my webpage. I tried lot, doesn't helped me.
Please help me resolve my issue.
First of all, most of the answers posted here are just off the topic. I have been working with selenium 2 and selenium 3 now, the webdriver can handle window scroll to make an element visible.
For everyone posting snippets like:
driver.execute_script('scrollBy(0, 250)')
you do not get the question at all!
Actually I still did not find a way to properly simulate the drag action of scroll handle but this answer seems promising -- but I did not try.
So so far personally there are two ways to do this for me:
Use Keys.ARROW_DOWN
Use Keys.PAGE_DOWN
Actually there is a third way, just give up selenium and contact the website if they provide any API.
The easiest way to do that is executing a Javascript to scroll the element up/down.
JavascriptExecutor jsExec = (JavascriptExecutor) driver;
jsExec.executeScript("document.getElementById('id').scrollDown += 100");
driver.get("http://www.***.com/");
driver.manage().window().maximize();
WebElement scroll = driver.findElement(By.id("someId"));
scroll.sendKeys(Keys.PAGE_DOWN);
Scroll Down:
import org.openqa.selenium.JavascriptExecutor;
WebDriver driver = new FirefoxDriver();
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("scroll(0, 250)"); //y value '250' can be altered
Scroll up:
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("scroll(250, 0)"); //x value '250' can be altered
Scroll bottom of the Page:
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("window.scrollTo(0,Math.max(document.documentElement.scrollHeight,document.body.scrollHeight,document.documentElement.clientHeight));");
or
Actions actions = new Actions(driver);
actions.keyDown(Keys.CONTROL).sendKeys(Keys.END).perform();
Full scroll to bottom in slow motion:
for (int second = 0;; second++) {
if(second >=60){
break;
}
((JavascriptExecutor) driver).executeScript("window.scrollBy(0,400)", ""); //y value '400' can be altered
Thread.sleep(3000);
}
or
JavascriptExecutor jse = (JavascriptExecutor)driver;
for (int second = 0;; second++) {
if(second >=60){
break;
}
jse.executeScript("window.scrollBy(0,800)", ""); //y value '800' can be altered
Thread.sleep(3000);
}
Scroll automatically to your WebElement:
Point hoverItem =driver.findElement(By.xpath("Value")).getLocation();
((JavascriptExecutor)driver).executeScript("return window.title;");
Thread.sleep(6000);
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,"+(hoverItem.getY())+");");
// Adjust your page view by making changes right over here (hoverItem.getY()-400)
or
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", driver.findElement(By.xpath("Value')]")));
or
WebElement element = driver.findElement(By.xpath("Value"));
Coordinates coordinate = ((Locatable)element).getCoordinates();
coordinate.onPage();
coordinate.inViewPort();
First you should do scroll rather than find element so do like below :
document.getElementById("your div id").scrollTop(250);
After above you can find that specific div.
You can also try below :
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.scrollBy(250,350)");
Another way of doing it using JavascriptExceutor's scrollIntoView() method:
WebElement DIVelement = driver.findElement(By.xpath("xpath to div"));
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("arguments[0].scrollIntoView(true)", DIVelement);
Consider your HTML is like below:
<div id="someId" class="className" style="position: relative; top: 0px; left: opx;>
you can observe style attribute in div
check for the value of top which is 0px in above example
Now try to do something like:
$('.className').animate({top: "-60px"});
which will help you to scroll down.
Its a JavaScript executor so of course you need to implement it.
My 'WORKAROUND' is to scroll to the position by element's x and y co-ordinates. I also added an offset to y so that any header/footer or other element don't block the visibility of the element that I want to scroll to.
I have my answer posted under this question -
Selenium webdriver can't click on a link outside the page
None of the posted answers worked for me, however I have found a solution based on this post.
((JavascriptExecutor) driver).executeScript(
"arguments[0].scrollTop=arguments[1].offsetTop",
divWithScrollbarElement,
elementToScrollTo);
where divWithScrollbarElement is the div element which you are looking to scroll, and elementToScrollTo is the child element which you want to make viewable (which in my case was actually the parent of the element which I was initially trying to view). If elementToScrollTo is not actually in the DOM yet, you may need to use the script once to scroll down as far as possible, and then again once more elements have loaded.
As you found, webdriver won't find elements that aren't visible so you need to scroll to the element. However you can't scroll directly to the element because webdriver won't find it until it is visible. Catch-22.
However I do have a way that you can scroll within a DIV. First assign the DIV you want to scroll to an element variable, and then you can use javascript to scroll that element instead of scrolling the entire window.
Some VB.NET example code that should be easily adapted to other languages:
Dim div_to_scroll As IWebElement = driver.FindElement(By.XPath("[put your xpath here]"))
driver.ExecuteJavaScript("arguments[0].scrollBy(0,500)", div_to_scroll)
' Short pause to make sure the screen updates:
System.Threading.Thread.Sleep(500)
If you don't know how far you need to scroll then you will need a loop with a test to see if the desired element is visible yet. This isn't a particularly elegant or fast way of doing things but webdriver isn't a fast solution to begin with and I have found this method to be very robust.
Just in case for anyone looking for an alternative solution, here I put mine using python, which should be easy to transform to Java. First, I was using:
more = panel.find_elements(By.CSS_SELECTOR, "//li")
self.driver.execute_script("arguments[0].scrollIntoView();", more[-1])
if last == more[-1]:
break
else:
last = more_followers[-1]
#wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "//li")))
time.sleep(0.5)
in a loop for a ul inside a div. However, the more li elements appear, the slowest was selenium to perfom this action. At the end, because the div containing the ul had a unique class name I used the following in a loop:
while num_of_il<num_of_elements:
self.driver.execute_script("document.getElementsByClassName('myclass')[0].scrollTop += 100;");
time.sleep(0.5)
num_of_il = self.driver.execute_script("return document.getElementsByTagName('li').length")
print("Num of li "+str(num_of_il))
This way is not slow anymore, and with the 0.5 I give enough time to load my next entries. You can also have other getElementsBy as getElementById(), getElementsByName(), getElementsByTagName() and getElementsByTagNameNS(). Look methods at https://developer.mozilla.org/en-US/docs/Web/API/document/ You can check the number of elements loaded accessing the num_of_il variable. Consider introducing some code to break the loop in case num_of_il does not change (e.g. end of items reached).
Related
I'm working on a program that uses Selenium and I'm trying to scroll on some aside div of the document.
I firstly tried the following line of code but this only scrolls the main part of the HTML document:
((JavascriptExecutor) driver).executeScript("scrollBy(0, 500)");
So I tried to execute this:
((JavascriptExecutor) driver)
.executeScript("document.getElementsByClassName('aside-div')[0].scroll(0,100)");
This compile and executes without any error but the section I want to scroll through doesn't scrolls. How can I do this?
The best practice is to always use the javascript code on your browser console before actual implementation.
Also, plz make sure scroll(x,y), the value should be according to the scroll it can be either (1000,0) or (0,1000) negative-positive according to the requirement. Kindly choose accordingly.
Ok so coming back to your actual problem, what I feel is you are incorrectly using the code
Either you have been using scroll(0,1000) instead of scroll(1000,0) so on..
You have not mentioned the exact element locator.
PS: Please provide the HTML for in-depth debugging.
Meanwhile, you can checkout the below code:
((JavascriptExecutor) driver).executeScript("document.getElementsByClassName('aside-div'[0].scroll(0,1000)");
//OR
((JavascriptExecutor) driver).executeScript("document.getElementsByClassName('aside-div'[0].scroll(1000,0)");
//OR
WebElement elementToScroll = driver.findElement(By.cssSelector(".aside-div"));
((JavascriptExecutor) driver).executeScript("arguments[0].scroll(1000,0);", elementToScroll);
Please provide the exact element locator to use below code:
Example:
WebElement elementToScroll = driver.findElement(By.cssSelector(".aside-div table tr td"));
//This will scroll the page Horizontally till the element is found
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();", elementToScroll);
Usecase: Perform horizontal scroll till the element is found
Pre-reqs: Selenium - Java 3.141/chrome
Below are my few sample snippets
JavascriptExecutor jse = (JavascriptExecutor) driver; //create jse object and with this object, execute js
jse.executeScript("arguments[0].scrollLeft += 250",driver.findElement(By.className("wux-scroller")));
jse.executeScript("window.scrollBy(500,0)");
jse.executeScript("scroll(500, 0)");
jse.executeScript("window.scrollTo(500,0)");
jse.executeScript("arguments[0].scrollIntoView();",el);
jse.executeScript("arguments[0].scrollLeft = arguments[1];",driver.findElement(By.className("wux-scroller")), j)
Expected Result: To perform horizontal windows scroll till the element is displayed
Actual Result: Scroll doesn't happen but no exceptions are thrown as well
Note:
Page has both horizontal and verticall scrollbar
Both scroll elements has same class <div class="wux-scroller wux-ui-is-rendered" >
(I think) Windows default scrollers are used for both vertical and horizontal
scrolls. Image attached.
If I replace scrollLeft to scrollTop in above snippet then scroll happens vertically
fine
Referred below link but didn't help
how to scroll scrollbar horizontally which is inside a window using java
Update 2:
Please find attached image for little detailed dom.
To notice:
There are two horizontal scroll containers. Is that causing some trouble?
gridengine container is placeholder for 'wux-scroller' and it gets activated once user scrolls it manually
//Tried with below snippets but didn't work.
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("window.scrollBy(-2000,0)");
jse.executeScript("arguments[0].scrollLeft = arguments[1];",driver.findElement(By.className("wux-layouts-gridengine-scroller-container")), 500);
jse.executeScript("arguments[0].scrollLeft = arguments[1];",driver.findElement(By.className("wux-scroller")), 500);
Update 3: Solution
Below implementation of python in selenium java helped to perform horizontal scroll in my application
jse.executeScript("document.getElementsByClassName('wux-scroller wux-ui-is-rendered')[0].scrollLeft += 650");
jse.executeScript("document.getElementsByClassName('wux-scroller wux-ui-is-rendered')[0].scrollTo(350,0)");
Please try below code using Javascript but with base on different attribute
WebElement element = driver.findElement(By.className("wux-scroller"));
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.visibilityOf(element));
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("arguments[0].scrollIntoView({behavior: \"auto\", block: \"center\", inline: \"nearest\"});", element);
OR
jse.executeScript("arguments[0].scrollLeft = arguments[0].offsetWidth", element );
Do you need to test scroll or you need elements? For second case you can add --headless argument to driver. If it will be not enough add window-size argument with big resolution.
You need to select a focus then only it will get scrolled.
E.g.
driver.get("http://www.flipkart.com/");
driver.manage().window().maximize();
driver.findElement(By.linkText("Trimmer")).click();
WebElement scroll = driver.findElement(By.id("brand"));
scroll.sendKeys(Keys.PAGE_DOWN);
I have a element with data-qa-id = "journal-submit";
When I ran the test with small screen resolution Selenium says this element is not visible and cannot perform any action on it.
The same element is visible to selenium in regular chrome resolution. Can anyone explain me why it is so ? How to handle it ?
There's a few options for solutions here. I think scrolling to an element can be a bit hacky, because then it will remove other elements from the view of the browser, so you'll end up having to scroll all over the place to locate elements that may or may not be in view of the browser.
But, if you wish to use a scrolling solution, you can try something like this:
// declare JS executor
JavascriptExecutor executor = (JavascriptExecutor)driver;
// this is the element you want to find
WebElement element = driver.findElement(someLocatorHere);
// scroll to the element
executor.executeScript("arguments[0].scrollIntoView(true);", element);
I'm not a huge fan of this solution, for reasons I mentioned above. A "true" solution that will solve all problems of this type is to run your browser in headless and specify the screen size in the driver settings.
// declaring the webdriver
// headless options
ChromeOptions headlessOptions = new ChromeOptions();
headlessOptions.AddArgument("--headless");
headlessOptions.AddArguments("--disable-gpu");
headlessOptions.AddArguments("--window-size=1920,1200");
// start driver
driver = new ChromeDriver(headlessOptions);
I prefer the headless solution because it will solve most, if not all, of your issues regarding smaller screen resolution. I've gone back and forth with screen resolution issues for the majority of my career, and scrolling all over pages to locate individual elements was not a long-term or robust solution. I had much better success using headless, and driver is able to locate all of my elements.
I used JavascriptExecutor and it worked
JavascriptExecutor executor = (JavascriptExecutor)browser;
WebElement submit_btn = browser.findElement(By.name("submit-btn"));
executor.executeScript("arguments[0].click()",submit_btn);
If selenium not able to identify web element due to resolution then try to move to the element using action.
WebElement element = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.visibilityOfElementLocated(By.id("someid")));
Actions action=new Actions(driver);
action.moveToElement(element).perform();
Then perform required action on the webelement
My problem is to scroll the scroll bar horizontally which is inside window
I used this code but it scroll the windows horizontal bar not that exactly scroll bar inside that window.
WebElement scroll = driver.findElement(By.xpath("//div[#id='gvLocationHorizontalRail']"));
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.scrollBy(250,0)", "");
You are using javascript that scrolls the main window, if you want to scroll a element, you should first get the element by id, then change the its scrollLeft property:
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(
"document.getElementById('gvLocationHorizontalRail').scrollLeft += 250", "");
If you instead want to change the scrollbar that moves up and down, you should change the scrollTop property.
In addition to answer by Ferrybig, can you try this:
WebElement scroll = driver.findElement(By.xpath("//div[#id='gvLocationHorizontalRail']"));
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(
driver.execute_script("arguments[0].scrollIntoView()", scroll);
Use the following:
WebElement problematicElement= driver.findElement(By.xpath("//div[#id='blah']"));
(JavascriptExecutor)driver.executeScript("arguments[0].scrollIntoView()", problematicElement);
You don't need to use Javascript to do this. I was having issues with solutions working the second, third and fourth times the page was loaded. The code below works and works always without error. It moves a scroll bar to the right. I broke it out because I prefer to see each action by itself for readability.
myElement = (new WebDriverWait(driver, 30))
.until(ExpectedConditions.elementToBeClickable(By.cssSelector(".ngscroll-scrollbar")));
myElement.click();
Actions move = new Actions(driver);
move.moveToElement(myElement).clickAndHold();
move.moveByOffset(125,0);
move.release();
move.perform();
In my case I could not find the horizontal element of a table, so another (bearish, but still) way to perform this action is:
IWebElement yourElement = driver.FindElement(By.Id("id_XYZ"));
yourElement.Click();
int i = 0;
while (i < 20)
{
yourElement.SendKeys(Keys.Right);
++i;
}
You can use below code to perform scrolling of elements which are inside a window.
For eg: Webtable
WebElement scroll=driver.findElement(By.css(".xyz"));
JavascriptExecutor js=(JavascriptExecutor)driver
js.executeScript("document.querySelector(scroll).scrollLeft=1000");
Note: You have to make sure that you have to pass CSS only in the query Selector method
I have searched all the forums but I didn't get a correct answer for my issue. My web page to test has a link hidden below, and I am trying to find it manually by searching for it with xpath or the ID attribute of the element, but I am not able to find it when I am running the web driver script. Even when it is not giving any error on that element, I am getting an error on next command/line.
I found below code from the forums, which is scrolling whole page. I don't want this, I want to scroll down vertically in a specific div area as in screen shot.
JavascriptExecutor jsx = (JavascriptExecutor)driver;
jsx.executeScript("ctl00_Menu1_scrollDiv.scrollBy(0,250)", "");
div id for this is "ctl00_Menu1_scrollDiv"
Element id: ctl00_Menu1_DlMenu_ctl09_LnkMenuname
Please help me on this issue. Thanks in advance.
Help will be appreciated.
This is umendra tomar , I have found very simple solution for this, please use the below code for scroll a specific div in html using selenium .
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("document.getElementById('scrollCustom').scrollTop= 450");
scrollCustom = this is the ID of your div which you want to scroll.
document.getElementById = this is use in javascript to locate a webelement.
Don't worry we can use this in java using javascriptExecutor
Check if this works for you.
var s = $('#ctl00_Menu1_scrollDiv').scrollTop();
This will give the current value of the scroll in the div.Use this only if you want to scroll inside a div to a certain point dynamically. Otherwise you can hardcode the scrollTop value inside animate()
Using the current value of your scroll you can parameterize the given below scrollTop parameter
$("#ctl00_Menu1_scrollDiv").animate({ scrollTop: "100px" }); // Here 100 px is just an example
I had used this to scroll a large div programmatically in my webdriver framework. Also, this will work if your AUT has jQuery loaded in the browser.
In Java:
JavascriptExecutor js;
js = (JavascriptExecutor) driver;
js.executeScript("$(\"#ctl00_Menu1_scrollDiv\").animate({ scrollTop: \"100px\" })");
First you should not just reference an element by the id. You should set scrollTop to scroll it to a position.
document.getElementById("ctl00_Menu1_scrollDiv").scrollTop(250);
Non-JQuery solution based on this post.
((JavascriptExecutor) driver).executeScript(
"arguments[0].scrollTop=arguments[1].offsetTop",
divWithScrollbarElement,
elementToScrollTo);
where divWithScrollbarElement is the div element which you are looking to scroll, and elementToScrollTo is the child element which you want to make viewable (which in my case was actually the parent of the element which I was initially trying to view). If elementToScrollTo is not actually in the DOM yet, you may need to use the script once to scroll down as far as possible, and then again once more elements have loaded.