From what I've read the following code:
File s = ((TakesScreenshot)driver_).getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(s,new File("C:\\scr.png"));
} catch (IOException exception) {
exception.printStackTrace();
}
Should take a full page screenshot. But in my case it will only take the screenshot of whatever is currently visible in the browser window. Is this the expected behaviour or did something go wrong in the code?
Yes it is expected behavior from firefox.
If you want to take full page screenshot you can use something like this to zoom out the whole contents to visible area
executor = (JavascriptExecutor)driver.getDriver();
executor.executeScript(
"document.body.style.zoom=
(top.window.screen.height-70)/
Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);");
File scrFile = ((TakesScreenshot)driver.getDriver()).getScreenshotAs(OutputType.FILE);
It will try to bring all the content to visible area, although you can still miss some content from the very bottom area.
Related
I am trying to change the icon of the Java application but nothing seems to work.
I am trying to get image from resources path using:
getClass().getResource("/AppIcon.png")
Sometimes I get an error like URL not found.
The image that is used for the Form's icon can be any image but must be loaded as an Image type (not of ImageIcon type). The JFrame#setIconImage() method will auto-size the image loaded. Here just a couple ways. These examples assume that the code resides in a class which extends JFrame:
Example #1:
try {
/* For a Form's title bar icon....
Don't use this for animated .gif images otherwise your GUI will
freeze. I'm not exactly sure why but it seems as though the gif
frames continuously cycle as though in an infinite loop. If you
want to use an animated .gif image as a Form's title bar icon
then don't use Toolkit, use ImageIO.read() instead since it will
only utilize the first gif frame as the image. */
// Be sure to set the path string to your specific resources directory.
this.setIconImage(java.awt.Toolkit.getDefaultToolkit()
.getImage(getClass().getResource("/resources/images/Apple/png").getFile()));
}
catch (java.lang.NullPointerException ex) {
// Do what you want with caught exception.
ex.printStackTrace();
}
Example #2:
try {
/* Can be used to also display an animated gif for the Form's Title
bar icon but only the first gif frame is utilized. */
// Be sure to set the path string to your specific resources directory.
File pathToFile = new File(getClass().getResource("/resources/images/Apple.png").getFile());
Image image = ImageIO.read(pathToFile);
this.setIconImage(image);
}
catch (IOException ex) {
// Do what you want with caught exception.
ex.printStackTrace();
}
UPDATE:
As stated by #AndrewThompson in comments, the two above examples will not work as expected from a JAR file. They will work if run through the IDE however which in reality is no good except for testing. To use the two examples above in a distributive JAR file then also see Example #3 and Example #4:
Example #3:
try {
/* For a Form's title bar icon.... To be used in a distributive JAR.
Don't use this for animated .gif images otherwise your GUI will
freeze. I'm not exactly sure why but it seems as though the gif
frames continuously cycle as though in an infinite loop. If you
want to use an animated .gif image as a Form's title bar icon
then don't use Toolkit, use ImageIO.read() instead since it will
only utilize the first gif frame as the image. */
// Be sure to set the path string to your specific resources directory.
java.net.URL url = getClass().getResource("/resources/images/Apple.png");
this.setIconImage(java.awt.Toolkit.getDefaultToolkit().getImage(url));
}
catch (java.lang.NullPointerException ex) {
// Do what you want with caught exception.
ex.printStackTrace();
}
Example #4:
try {
/* For a Form's title bar icon.... To be used in a distributive JAR.
Can be used to also display an animated gif for the Form's Title
bar icon but only the first gif frame is utilized. */
// Be sure to set the path string to your specific resources directory.
java.net.URL url = getClass().getResource("/resources/images/Apple.png");
Image image = ImageIO.read(url);
this.setIconImage(image);
}
catch (IOException ex) {
// Do what you want with caught exception.
ex.printStackTrace();
}
Don't even bother with Examples #1 and #2, they now just remain here for reference. Just use either Example #3 or Example #4. Both will work in the IDE or a distributive JAR file.
Solution;
Everything works for windows but I am using Mac :D
So I started to look around Taskbar class comes with awt package and found the solution (Thanks to flohall)
try {
var image = new ImageIcon(Objects.requireNonNull(Main.class.getResource("/AppIcon.png")));
frame.setIconImage(image.getImage());
if (System.getProperty("os.name").startsWith("Mac") || System.getProperty("os.name").startsWith("Darwin")) {
Taskbar taskbar = Taskbar.getTaskbar();
try {
taskbar.setIconImage(image.getImage());
} catch (final UnsupportedOperationException e) {
System.out.println("Can't set taskbar icon.");
} catch (final SecurityException e) {
System.out.println("Warning. Can't set taskbar icon due to security exceptions.");
}
}
} catch (NullPointerException e) {
e.printStackTrace();
}
So we are telling the taskbar to change its icon using built-in awt Taskbar class on taskbar.setIconImage(image.getImage());. And that solves most of the things I've needed for.
Does anybody know how to make full screenshot of display using webdriver?
In Selenium documentation I read that it is possible: (http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/TakesScreenshot.html)
..
The screenshot of the entire display containing the browser
..
I use Selenium Grid. My hub is on linux and node on windows. I tried to use Robot, however it takes screenshot on linux, however needs on windows
If you want a screenshot of your currently running browser instance then you can do it using following code:
public static void captureScreen(WebDriver driver, String screenshotFileName)
{
String screenshotsFile = screenshotsFolder+screenshotFileName+imageExtention;
try {
File screenShot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenShot, new File(screenshotsFile));
} catch (IOException e) {
}
}
But if you want to take screenshot of your active window (other than browser only) then you can use Robot class.
Edit:
Although it's too late for you, the link below contains your answer. I think it may be helpful for others who are searching for the same thing.
Screen shot issue in selenium webdriver
You need to use FirefoxDriver to screenshot whole page.
Chrome and IE doesn't support it.
hi try it like below it will take the complete webpage screen shot
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
//The below method will save the screen shot in defined drive with name "screenshot.png"
FileUtils.copyFile(scrFile, new File("yourPath\\screenshot.png"));
Im experimenting with Allure aShot() class to take screenshots of specific WebElements on a website I'm working on, and below is the code I used in selenium to make it happen.
Please visit this link, which shows aShot() project documentation:
https://github.com/yandex-qatools/ashot
So My QUESTION is that, where are these AShot() screenshots of the WebElement actually being saved? I used testNG to execute below method and successfully able to generate allure reports but I can't see these screenshots in those reports or anywhere in my framework. Please check below code, it is very difficult to pinpoint the location of these images.
So again, my basic question is: How do we specify selenium to store these AShot() screenshots of the WebElement into a particular file that we want?
I've tried to cast Screenshot class mentioned below to BufferedImage or TakesScreenshot class and use ImageIO.write or FileUtils.copyFile methods to copy these images into a file and store these images there, but I get an error saying, for example, "java.lang.ClassCastException: ru.yandex.qatools.ashot.Screenshot cannot be cast to org.openqa.selenium.TakesScreenshot" and I've tried other methods as well, unsuccessfully.
Please help me resolve this issue, how do we know/specify where these AShot() screenshots are being saved?
public WebDriver driver;
#Test
public void getAShotImage() {
driver.get("http://....../");
WebElement element = driver.FindElement(By.xpath(".............."));
AShot shot = new AShot();
shot.takeScreenShot(driver, element);
OR
shot.coordsProvider(new WebDriverCoordsProvider()).takeScreenshot(driver, element);
}
You can attach your screenshots by returning byte array from the method. Look at the following example:-
#Attachment(value="Screenshot", type="image/png")
private static byte[] captureScreenshot(Webdriver driver)
{
byte[] screenshot = null;
screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
}
return screenshot
}
Above code does not use Ashot but it shows how you need to attach files. Also, if you are still not able to see your screenshots, check if your steps are displayed in your report.If not then probably you are missing javaagent as discussed in FAQ
AShot returns the Screenshot object, that contains the image of your element and information for comparison of screenshots. In this case you can use getImage() method to get the image.
new AShot().takeScreenshot(....).getImage();
The Screenshot will contain the byte array instead of BufferedImage soon.
This question already has answers here:
How can I take a screenshot with Selenium WebDriver?
(48 answers)
Closed 6 years ago.
I am trying to take a screenshot of a webpage while selenium is running. I am using the following code for this purpose
WebDriver augmentedDriver = new Augmenter().augment(seleniumDriver);
File scrFile = ((TakesScreenshot)augmentedDriver).getScreenshotAs(OutputType.FILE);
Now it serves my purpose perfectly well except that whenever this method gets called the browser automatically gets into the default size and maximizes again.
And this continues every time the screenshot function gets called.
I am able to solve the problem If I am NOT using the selenium webdriver for taking the screenshots and using other java functions.
I wanted to know if anyone had similar problems/why I am having this problem. And is there any workaround?
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("D:\\screenshot.jpg"));
This code will definitely help
It tries to adapt to page size and take the screenshot as small as possible or as large as needed for the whole page to fit. Apart from being annoying, it should not be a cause of any other problems and is therefore considered a better solution than taking a screenshot of just the actual viewport which could be missing some important piece of the page you're trying to examine.
If you're not happy about it, use Robot and its createScreenCapture() method.
Or, but it will only work for Firefox, you may try overriding the FirefoxDriver's method for screenshots. Not tested, no idea whether you'll be allowed to do it or not.
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("FirefoxDriver.prototype.screenshot = function(a){};");
and (if that's not enough) maybe even
js.executeScript("FirefoxDriver.prototype.saveScreenshot = function(a,b){};");
Inferred from here. The actual screenshooting code is here. You can replace the FirefoxDriver.prototype.screenshot function with your own that wouldn't take the maximum scrollable values for height and width...
The code to take the screenshot make use of getScreenshotAs method of TakesScreenshot interface. Following code will take screenshot of the webpage opened by webDriver instance.
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("D:\\testScreenShot.jpg"));
Now in order to take screenshot in case of test failure we will use AfterMethod annotation of TestNG. In the AfterMethod annotation we will use ITestResult interface's getStatus() method that returns the test result and in case of failure we can use the above commands to take screenshot. Code snippet to take screenshot on test failure-
#AfterMethod
public void takeScreenShotOnFailure(ITestResult testResult) throws IOException {
if (testResult.getStatus() == ITestResult.FAILURE) {
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("D:\\testScreenShot.jpg"));
}
}
For complete sample script refer to http://artoftesting.com/automationTesting/screenShotInSelenium.html
I have created a method for this, which is very easy to use. It takes the screenshot of the whole web page. It counts and name the screen shot depending on the number of screenshots, the method also stores the screenshot as .png file into src.
public static void screenshot(WebDriver driver)
{
System.out.println("Taking the screenshot.");
console_logs("Taking the screenshot.");
scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(scrFile, new File("src//tempOutput//webPage_screenshot_"+count+".png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count++;
//return scrFile;
}
Using the method:
screenshot(driver);
In certain unknown situations selenium does not detect that a page has loaded when using the open method. I am using the Java API. For example (This code will not produce this error. I don't know of an externally visible page that will.):
Selenium browser = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.google.com");
browser.start();
browser.open("http://www.google.com/webhp?hl=en");
browser.type("q", "hello world");
When the error occurs, the call to 'open' times out, even though you can clearly see that the page has loaded successfully before the timeout occurs. Increasing the timeout does not help. The call to 'type' never occurs, no progress is made.
How do you get selenium to recognize that the page has loaded when this error occurs?
I faced this problem quite recently.
All JS-based solutions didn't quite fit ICEFaces 2.x + Selenium 2.x/Webdriver combination I have.
What I did and what worked for me is the following:
In the corner of the screen, there's connection activity indicator.
<ice:outputConnectionStatus id="connectStat"
showPopupOnDisconnect="true"/>
In my Java unit test, I wait until its 'idle' image comes back again:
private void waitForAjax() throws InterruptedException {
for (int second = 0;; second++) {
if (second >= 60) fail("timeout");
try {
if ("visibility: visible;".equals(
selenium.getAttribute("top_right_form:connectStat:connection-idle#style"))) {
break;
}
} catch (Exception e) {
}
Thread.sleep(1000);
}
}
You can disable rendering of this indicator in production build, if showing it at the page is unnecessary, or use empty 1x1 gifs as its images.
Works 100% (with popups, pushed messages etc.) and relieves you from the hell of specifying waitForElement(...) for each element separately.
Hope this helps someone.
Maybe this will help you....
Consider the following method is in page called Functions.java
public static void waitForPageLoaded(WebDriver driver) {
ExpectedCondition<Boolean> expectation = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
WebDriverWait wait = new WebDriverWait(driver,30);
try {
wait.until(expectation);
} catch(Throwable error) {
Assert.assertFalse(true, "Timeout waiting for Page Load Request to complete.");
}
}
And you can call this method into your function. Since it is a static method, you can directly call with the class name.
public class Test(){
WebDriver driver;
#Test
public void testing(){
driver = new FirefoxDriver();
driver.get("http://www.gmail.com");
Functions.waitForPageLoaded(driver);
}
}
When I do Selenium testing, I wait to see if a certain element is visible (waitForVisible), then I do my action. I usually try to use an element after the one I'm typing in.
Using 'openAndWait' in place of 'open' will do the trick.
From the website:
Many Actions can be called with the "AndWait" suffix, e.g. "clickAndWait". This suffix tells Selenium that the action will cause the browser to make a call to the server, and that Selenium should wait for a new page to load.
Enabling the 'multiWindow' feature solved the issue, though I am not clear why.
SeleniumServer(int port, boolean slowResources, boolean multiWindow)
SeleniumServer server = new SeleniumServer(4444, false, true);
Any clarification would be helpful.
I've run into similar issues when using Selenium to test an application with iFrames. Basically, it seemed that once the primary page (the page containing the iframes) was loaded, Selenium was unable to determine when the iframe content had finished loading.
From looking at the source for the link you're trying to load, it looks like there's some Javascript that's creating additional page elements once the page has loaded. I can't be sure, but it's possible that this is what's causing the problem since it seems similar to the situation that I've encountered above.
Do you get the same sort of errors loading a static page? (ie, something with straight html)
If you're unable to get a better answer, try the selenium forums, they're usually quite active and the Selenium devs do respond to good questions.
http://clearspace.openqa.org/community/selenium_remote_control
Also, if you haven't already tried it, add a call to browser.WaitForPageToLoad("15000") after the call to open. I've found that doing this after every page transition makes my tests a little more solid, even though it shouldn't technically be required. (When Selenium detects that the page actually has loaded, it continues, so the actual timeout variable isn't really a concern..
Not a perfect solution, but I am using this method
$t1 = time(); // current timestamp
$this->selenium->waitForPageToLoad(30);
$t2 = time();
if ($t2 - $t1 >= 28) {
// page was not loaded
}
So, it is kind of checking if the page was not loaded during the specified time, so it is not loaded.
another idea is to modify AJAX API (to add some text after AJAX actions).
After ajax action was finished, before return, set invisible field to TRUE, selenium will find it and read as green-light
in html:
<input type='hidden' id="greenlight">
in selenium
if(driver.findElement(By.id("greenlight")).getAttr("value").equals("TRUE")){
// do something after page loading
}
If you page has no AJAX, try to seek footer of page (I also use Junit fail(""), you may use System.err.println() instead):
element.click();
int timeout =120;
// one loop = 0.5 sec, co it will be one minute
WebElement myFooter = null;
for(int i=0; i<timeout; i++){
myFooter = driver.findElement(By.id("footer"));
if(myFooter!= null){
break;
}
else{
timeout--;
}
}
if(timeout==0 && myFooter == null){
fail("ERROR! PAGE TIMEOUT");
}