How to scroll in selenium headless mode using Java? - selenium

Description
Because I don't yet have got any answer from mine post:
How to get all stocks from the specified URL in selenium headless mode?
I have to work on workaround to get progress on my work! Instead of trying to force an update on the site to get all stocks viewable (as described in my post) I will go to the end of page and then scroll up to force all stocks to get viewable (works fine when I do it manually).
All this MUST work in selenium headless mode!
Problem
I know how this can be implemented in selenium normal mode (not headless) but I can't get it to work in headless mode.
I think this line works both in normal and headless mode to go to the END of page:
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
The issue I'm struggeling with is how to scroll up or pageup from the end of the page. I guess something like this will work:
WebElement e = driver.findElement(By.xpath("element to be returned like Storskogen"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();", e);
I can't fetch the element "e", I can't get it work (NoSuchElementException is thrown). I have copied the xpath or css from Chrome without result though. I'm not even sure this will work in headless mode.
Questions
how to fetch element "Storskogen"?
is "scrollIntoView" scrolling working in headless mode?
how can pageup be implemented and working in headless mode?
how can I verify scrolling in headless mode?
It's okay to not answer every question. I use Java for implemention.

Selenium headless window/display size by default is 800x600.
So if you have a lot on your webpage, then you may end up with horizontal, as well as vertical scroll bars on the headless browser. Therefore, dependent on your webpage, the element you are after may not be drawn, hence you have to scroll up and down for it to appear.
To get the best results of scrolling up and down, you want to maximise your browser window. As you want to operate in headless mode, the actual browser will not be active, thus driver.manage().window().maximize(); is not an option.
Do the following:
Update your browser driver with a specific window size that will ensure no horizontal scroll bars. I have used the following for my BrowserDriverFactory as I test with multiple browsers: driver.manage().window().setSize(new Dimension(1920, 1280)); also you could manage a specific browser driver i.e. chromedriver with options.addArguments("window-size=1920,1080");
Then use JavascriptExecutor, as you mentioned above:
Scroll down - ((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
Scroll up - ((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollTop);");

Related

Selenium click action on a webElement does not work when changing to a 4K monitor (3840 x 2160)

I have an electron application and I am using Selenium for automatic testing. The application was displayed on a full hd monitor and click action on webElements was working fine. However, after changing the monitor to a 4k monitor, the click action does not respond.
This action does work for Full HD resolution but not for 4K:
webElement.Click();
I have to use JavaScriptExecutor instead to make it works. This way it does work:
js.ExecuteScript("arguments[0].click();", webElement);
I would like to understand why Selenium click method has stopped working when changing screen resolution. I have tried to change ChromeOptions to set the screen resolution but it does not help. Any ideas?
Before clicking the element, scroll the element to centre of screen using javascript executor and check, if it works.

There is no frame but still there is an error element is not found

Below is my code, the line =>
driver.findElement(By.xpath("//*[#id=\"quote_password\"]")).sendKeys("password"); throws exception that element is not found
#Test
public void mytest()
{
System.setProperty("webdriver.chrome.driver","Drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("http://billing.scriptinglogic.net/index.php/sessions/login");
driver.findElement(By.xpath("//*[#id='email']")).sendKeys("email");
driver.findElement(By.xpath("//*[#id='password']")).sendKeys("password");
driver.findElement(By.xpath("/html/body/div/div/form/input")).click();
driver.findElement(By.xpath("//*[text()='Quotes']")).click();
driver.findElement(By.xpath("//*[text()='Create Quote']")).click();
driver.findElement(By.xpath("//*[#id=\"quote_password\"]")).sendKeys("password");
}
Quick and dirty solution:
WebDriverWait wait = new WebDriverWait(driver, 15, 100);
driver.get("http://billing.scriptinglogic.net/index.php/sessions/login");
driver.findElement(By.id("email")).sendKeys("<EMAIL>");
driver.findElement(By.id("password")).sendKeys("<PASSWORD>");
driver.findElement(By.name("btn_login")).click();
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[text()='Quotes']"))).click();
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".create-quote"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.id("quote_password"))).sendKeys("password");
Updated based on the credentials supplied in the comment below. I've tweaked the selectors to use ID, name and class where applicable. There is no need to use complex XPath locators when they aren't needed.
The explicit waits are required based on the way the site is working and I've added JeffC's suggestion of using an elementToBeClickable expected condition for the input element (I don't think it's really required in this instance though since the site doesn't seem to ever disable the input field, so a visibilityOfElementLocated expected condition is just as good really).
This solution is working for me in Chrome and Firefox in standard mode and Firefox in headless mode. It's not working in headless mode in Chrome because the screen size is smaller and when the screen width goes below 1000px the header changes and the text "Quotes" is never displayed. Below 767px the header is completely removed and you get a side menu. This means that the flow of the script needs to change slightly based on resolution.
I would suggest asking your developer to add an ID to the menu items, it will make it easier to locate them and use the site in its various states. The quick and dirty solution to this problem is ensure the browser is a certain size while the test runs, you can do this by setting the size in the first line of your script:
driver.manage().window().setSize(new Dimension(1024, 768));
When you do this it passes in Firefox and Chrome in standard and headless mode.
Note: The lines with an explicit wait that result in an element being clicked are anchor elements so there is no point waiting for the element to be clickable as the condition is always going to return true.

click event for a link is not working for phantomjs

I am using nightwatchjs for end to end testing. My test passes for chrome, firefox, ie and edge but one of the test fails for phantomjs. click event for url seems to fail.
'do somethings' : function(browser) {
browser
.setValue('input[id=SearchInput]', '000')
.click('button[id=Button]')
.assert.containsText('label[id=nOutput]', '000')
.click('a[id=link]')// this click is not working
.pause(1000)
.assert.value('input[id=Input]', 'A')
.assert.value('input[id=InputB]', 'B')
//reset page
.click('button[id=__xmlview0--clearButton]')
.end()
},
Thanks for help.
Looks like a Selenium issue.
https://github.com/SeleniumHQ/selenium-google-code-issue-archive/issues/5404
Selenium first gets the element's position, then sends a mouse click event. If the element moved between the time, the element will not be clicked.
I've encountered this too, my test case is trying to click A, but B gets clicked. Still trying to figure out a solution.
In another project I also encountered another reason. The page is responsive-ready, some elements are display:none when browser width is less than, say, 1000px. When nightwatch launches Chrome or Firefox, the browser window is full screensize, but phantomjs's default viewport size triggers the responsive condition. So Selenium cannot even find the element I want to click.

How to resolve org.openqa.selenium.WebDriverException?

I am writing an automated test and want to report bugs, if occur, directly in the repo at GitHub. The step which fails in my program is the Submit new issue button from GitHub Issue Tracker.
Here is the code:
WebElement sendIssue = driver.findElement(By.xpath("/html/body/div[5]/div/div/div[2]/div[1]/div/form/div[2]/div[1]/div/div/div[3]/button"));
sendIssue.click();
And the exception:
org.openqa.selenium.WebDriverException: Element is not clickable at
point (883, 547.7999877929688). Other element would receive the click:
div class="modal-backdrop"></div
The following command also does not work:
((JavascriptExecutor) driver).executeScript("arguments[0].click();", sendIssue);
How can I make it clickable? Is there any other way by which I can resolve this issue?
This is happening because when selenium is trying to click ,the desired element is not clickable.
You have to make sure that the Xpath provided by you is absolutely right.If you are sure about the Xpath then try the following
replace
WebElement sendIssue = driver.findElement(By.xpath("/html/body/div[5]/div/div/div[2]/div[1]/div/form/div[2]/div[1]/div/div/div[3]/button"));
sendIssue.click();
with
WebElement sendIssue =(WebElement)new WebDriverWait(DRIVER,10).until(ExpectedConditions.elementToBeClickable(By.xpath("/html/body/div[5]/div/div/div[2]/div[1]/div/form/div[2]/div[1]/div/div/div[3]/button")));
sendIssue.click();
If that doesn't work ,You will get an Timeout exception, In that case try incaresing the timeout amount from 10 to 20.
If it still doesn't work please post a screenshot of the HTML.
You need to write something in the issue title and description to make the issue clickable are you sure you are not making that mistake of clicking the button without writing anything in those places I am adding screenshot for your convenience.
Selenium Webdriver introduced in a previous version (v2.48) a new behavior that prevent clicks on elements that may be overlapped for something else (a fixed header or footer - for example) or may not be at your viewport (visible area of the webpage within the browser window).
You can see the debate here.
To solve this you will need to scroll (up or down) to the element you're trying to click.
One approach would be something like this post:
Page scroll up or down in Selenium WebDriver (Selenium 2) using java
Another, and maybe more reasonable, way to create a issue on Github, would be using their API. Maybe it would be good to check out!
Github API - Issues
Gook luck.
This worked for me. Instead of HTML browser this would be useful if we perform intended Web Browser
// Init chromedriver
String chromeDriverPath = "/Path/To/Chromedriver" ;
System.setProperty("webdriver.chrome.driver", chromeDriverPath);
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless", "--disable-gpu", "--window-size=1920,1200","--ignore-certificate-errors");
WebDriver driver = new ChromeDriver(options);

Selenium evaluates DOM or Visible elements

I would like to understand how Selenium evaluates the page.
I have set of test to check elements on the page. Written with Nunit, Selenium and PhantomJS as Driver.
Page.Visit();
Page.FindElement(By.Id("testid").Text.Should().NotBeNull(); // PASS
Page.FindElement(By.Id("testid").Text.Should().NotBeEmpty(); // does NOT PASS
The test DOES NOT pass if the browser size is set to be very small:
driver.Manage().Window.Size = new Size(10,10);
Based on this test, it is confusing how PhantomJS evaluates the page. I always thought that it checks the DOM but seems like for element TEXT it evaluates based on visibility!
Although this surprised me too when I first discovered it, Selenium will only find elements visible in the viewport of the browser. For this reason, you will want to ensure at the start of your tests that your browser viewport is large enough to accommodate the content of your application.
Typically this can be done by maximizing the browser window. If you are using Windows, triggering the F11 key via Selenium should work.