ashot
ashot copied to clipboard
Remove fixed nav duplication from screeshot
When a website site have a fixed navigation menu. It's appear on all the segment
of the screenshot.
Try a screenshot of http://stackoverflow.com
It's will be nice if we can avoid that
Hi, @khabali. Thank you for interesting issue. Do you have any ideas how to fix it? I have only one idea - to remove or hide this fixed bar while the screenshot is being taken. Actually it is known issue for many years but there is no common way to avoid this problem. Any idea will be appreciated.
we may let the user to give a div identifier that will be ignored after the first screenshot. the user will be responsible of finding this identifier and passing it to the API.
WebElement navBar= webDriver.findElement(By.cssSelector("#my_fixed_element"));
new AShot()
.withFixedElementOnTop(navBar) // this will be ignored while taking the screenshot
.takeScreenshot(webDriver);
Here is a workaround for that to avoid the noisy duplication of the fixed element This don't solve the problem completely but at least the screenshot is more clean even if we loose the fixed element.
// Remove the fixed element from the page
JavascriptExecutor js;
if (driver instanceof JavascriptExecutor) {
js = (JavascriptExecutor) driver;
WebElement element = driver.findElement(By.className("element-class"));
js.executeScript("arguments[0].parentNode.removeChild(arguments[0])", element);
}
//take the screenshot
new AShot().takeScreenshot(webDriver);
As a solution we can take two screenshots, one without the fixed element as shown above and another of only the fixed element then we can merge the two of them in one shcreenshot as a final clean result https://stackoverflow.com/questions/2318020/merging-two-images
any update on this issue? i don't like the idea of editing the page before taking the shot. i have tried taking only the content webelement like this:
WebElement content = driver.findElement(By.xpath("//div[@class='content-page']"));
BufferedImage image = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(100))
.takeScreenshot(driver, content).getImage();
it only works for the first shot, when it scrolled down, it still took the top bar in the shot
@gavrilfb I'm totally agree with you. It is one of not resolved problems of our world. Any ideas and proposal will be highly appreciated.
I forgot to mention it in the last post, but as you can see in the screenshot, some rows sometimes missing. in the example above is row 5.
I don't know if it's possible to copy the function, but I used ShareX before for manual scrolling screen capture. It's in C# though.
Below is the result after it process the image.
I forgot that we have non-documented feature which is the workaround for headers. Mostly it is used for iOS screenshots. It allows to cut off predefined area from top or bottom of origin screenshot. Use ShootingStrategy.viewportNonRetina(int scrollTimeout, int headerToCut, int footerToCut)
.
For example ShootingStrategy.viewportNonRetina(0, 100, 0)
will cut 100 px off from top of each screenshot.
From what I have tried, to achieve 'beautiful' shot of long pages, you have two options:
- Use PhantomJS driver and maximize the windows
- Use JQuery to find max height of all elements on page and set the window heigth to that value
Of course the second method won't work on pages with infinite scrolling. Hope this help.
@gavrilfb ShootingStrategy.viewportNonRetina(int scrollTimeout, int headerToCut, int footerToCut)
implements second approach.
It seems that the implementation leads to black bars at the places where the headers and footers would otherwise be. My expectation was that a single seamless picture would emerge. Isn't that possible or am I possibly doing something wrong?
I also have another suggestion: Should it not be possible to follow the algorithm that is used at CrossBrowserTesting and apparently leads to a perfect result completely automatically, without having to make any static height specifications? See here for details: https://help.crossbrowsertesting.com/screenshots/general/screenshots-fixed-elements/
@drundanibel the example provided in your link is getbootstrap.com/2.3.2/ I checked the page and indeed it is possible to stop the navbar follow scrolling by editing the css attribute. But this implementation won't work on my case, since my navbar is not using position: fixed. Nevertheless, this could be one way to solve this scenario. Would be great if you can share or even commit the codes to do this. Of course we need to restore the actual value before changes after taking the screenshot too for consistency.
@gavrilfb: It seems to me that good solution approaches have already been found in this thread: https://stackoverflow.com/questions/19474320/detect-whether-an-element-has-positionfixed-possibly-by-parent-element-via-jq
Edit: Just for the sake of interest: How does your navbar work, if not with "position: fixed"?
Can you or anyone else please say something about my other question with the black bars? I have applied the viewportNonRetina() workaround tip mentioned above by pazone to the page http://getbootstrap.com/2.3.2/:
Screenshot screenshot = new AShot().shootingStrategy(ShootingStrategies.viewportNonRetina(100, 40, 0)).takeScreenshot(driver)
I got this full page screenshot with two 40 pixel high horizontal black bars at the places where otherwise on both scrolled pages the footer would have been:
Apart from the ugly black bars as such, the content of the page covered by them does not appear in the following image section either.
What am I doing wrong?
Hello guys. I was experiencing this problem since yesterday and I found a workarround for it. The problem is with the header menu bar, ok? So, you can change the attributes of an element with Selenium (using JavascriptExecutor). My solution was change the visibility of header menu to hide it and make the screenshots. After that, I turned back the attribute to the original one (just for keep the behavior along the tests). With that change I can peform a full screenshot perfectly. Without black bars or overlapped menu.
Example:
WebElement element = driver.findElement(By.cssSelector("selector")); ((JavascriptExecutor) driver).executeScript("arguments[0].style.visibility='hidden'", element); Screenshot screenshot = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(100)) .takeScreenshot(driver); ((JavascriptExecutor) driver).executeScript("arguments[0].style.visibility=''", element);
@Lufis: Thanks for sharing your workaround, which I will try out later. But what I would wish for as a perfect solution would be if the header could be seen on the upper edge and the footer on the lower edge of the full page screen shot - with no header or footer or black bars between, of course. :) If I understood your approach correctly, header and footer are not visible at all, are they?
Is there any progress in this matter? Can I still hope that ashot will be able to handle fixed elements appropriately in the future?
By the way, I came across this Chrome browser extension in the meantime, which creates full page screenshots exactly as I would expect them to: https://chrome.google.com/webstore/detail/full-page-screen-capture/fdpohaocaechififmbbbbbknoalclacl
See here in contrast to the ashot result in my post above:
In my Selenium test suites I will now temporarily switch to this somewhat unclean solution in the hope that ashot will take up this challenge in the future. I would be very happy, many thanks in advance!
Is there any progress on this?
Hi All, similar issue i was facing and I came up with a work around for same. please try it .. The problem is with the header menu bar position is fixed , so solution is change the position as "absolute", below same code will help you.
WebElement element = driver.findElement(By.cssSelector("selector")); ((JavascriptExecutor) driver).executeScript("arguments[0].style.position='absolute'", element);
I hope it helps you.
Hi All,
This may help you. Removing or changing the style property of the sticky header using JAVASCRIPT and taking the scrollable screenshot is not suggested as it is considered as standard way of testing and producing screenprint.
One best way is to use the JS and find the full page height viewport height, sticky header height and scroll and take the screenshot. You can use the below code.
public void scrollTheStickyHeaderPage(){
/** This function scrolls and takes screenshot **/
JavascriptExecutor js = (JavascriptExecutor) driver;
int fullPageHeight = Integer.parseInt(js.executeScript
("return document.documentElement.ScrollHeight").toString());
int viewportHeight = Integer.parseInt(js.executeScript("return Math.max
(document.documentElement.clientHeight, window.innerHeight || 0)").toString());
int headerHeight = Integer.parseInt(js.executeScript("return Math.max
(document.getElementsByTagName('/**element**/')[0].clientHeight,
document.getElementsByTagName('/**element**/')[0].offsetHeight,
document.getElementsByTagName('/**element**/')[0].scrollHeight || 0)").toString());
int numofScrolls = (fullPageHeight/viewportHeight);
/** call your screenshot function **/
for(int i=1; i<=numofScrolls; i++){
js.executeScript("window.scrollBy(0,"+(viewportHeight-headerHeight)+")");
/** call your screenshot function **/
}
}
@rciddagoni Thank you for the above solution, it worked for a single element, but i have a full "div" which is sticky. do we have any solution for it???
@rciddagoni i could hide the nav totally using ((JavascriptExecutor) driver).executeScript("arguments[0].style.display='none'", element);. Thank you!!
I use this way to make header not fixed at the top.
JavascriptExecutor js = (JavascriptExecutor)driver; js.executeScript("document.getElementsByClassName('residential-header sticky-header fixed')[0].classList.remove('fixed');");
我觉得可以加入opencv的去除重复的元素,但是我个人算法不行,无法提供代码!
@cosoc could you please use English?