Search code examples
javaseleniumtestingautomated-testsscreenshot

Taking a screenshot of a modal window produces a black image


I'm using IE11 and Java under Eclipse. I'm not running the test on a remote system nor Am I using an RDC. This test is running on my local machine.

When I try to take a snapshot of the following screen, Selenium seems to have a problem with it.

Selenium cannot take a screenshot of this modal

This is what it does when the following code is executed:

File scrFile = ((TakesScreenshot) webdr).getScreenshotAs(OutputType.FILE);
  1. It moves the modal window in steps up and to the left. So if the original window position was (5,5) it moves it to (4,4)
  2. It plays the "alarm" sound -- (ding!)

It does this for about three times and then continues onto the next statement.

The result of screenshot process is a black image. enter image description here

Here is the actual method that I call when taking a screenshot:

public String captureScreenShot() {
    String      screenShotLocation  = System.getProperty("user.dir");
    String      TCID                = GlobalVars.getInstance().getTCID();
    WebDriver   webdr               = GlobalVars.getInstance().getWebdr();
    String      screenshotDir       = GlobalVars.getInstance().getScreenshotDir();
    String      methodName          = getCallingMethod(0);
    String      screenShotName      = null;


// I'm using the test case ID as the directory name where the image will be stored.
if (screenshotDir == null) {
    if (TCID.toLowerCase().contains("like")) {
        String[] parsedName = TCID.split(" ");
        screenshotDir = parsedName[1];
    } else {
        screenshotDir = TCID;
    }
}

try {
    File scrFile = ((TakesScreenshot) webdr).getScreenshotAs(OutputType.FILE);

    screenShotName          = generateUniqueValue().retStringValue + ".png";
    String[] pathSections   = GlobalVars.getInstance().getLogDir().split("\\\\");
    pathSections[pathSections.length-1] = "";

    String path = "";
    for (int x = 0; x < pathSections.length-1; x++) {
        path = path + pathSections[x] + "\\";
    }

    screenShotLocation  = path + "screenshots\\" + screenshotDir +"\\" + screenShotName;
    FileUtils.copyFile(scrFile, new File(screenShotLocation));

} catch (IOException e) {
    logMessage(MessType.FAIL, "From Common (" + methodName + ") Sorry, Because I received an exception while trying to capture the a screenshot, a screenshot will not be included.", "System Returned: " + e.toString());
}

return screenShotLocation;

}

The condition occurs right at line:

File scrFile = ((TakesScreenshot) webdr).getScreenshotAs(OutputType.FILE);

GlobalVars is a singleton class that is mostly Setters and Getters. Here is the code:

/**
 * The GlobalVars class is a singleton class that provides the ability to set global variables during the execution of a script.
 * @author lgonzalez
 * @since Dec 10, 2015
 */
public static class GlobalVars {
    private static GlobalVars instance;

    public static GlobalVars getInstance() {
        if (instance == null) {
            instance = new GlobalVars();
        }
        return instance;
    }
    private String          currentTestCaseID;
    private String          screenshotDir;
    private WebDriver       webdr;
    private String          LogDir;
    private BufferedWriter  bfWritter;
    private FileWriter      flWriter;
    private LogFileHandler  fileHandler;
    private int             logLevel;
    private int             passed;
    private int             failed;

    // I create a variable containing the LogHandler class when the singleton class is invoked
    private GlobalVars() {
        fileHandler = new LogFileHandler(); 
    }

    //---------------------------------------------------
    //         G E T T E R S
    //---------------------------------------------------
    public BufferedWriter getbfWriter() {
        return bfWritter;
    }

    public FileWriter getflWriter() {
        return flWriter;
    }

    public String getLogDir() {
        return LogDir;
    }       

    public LogFileHandler getLogHandler() {
        return fileHandler;
    }

    public int getLogLevel() {
        return logLevel;
    }   

    public String getScreenshotDir() {
        return screenshotDir;
    }

    public String getTCID() {
        return currentTestCaseID;
    }

    public WebDriver getWebdr() {
        return webdr;
    }

    public int getPassed() {
        return passed;
    }

    public int getFailed() {
        return failed;
    }

    //---------------------------------------------------
    //         S E T T E R S 
    //---------------------------------------------------

    public void setbfWriter(BufferedWriter bfwritter) {
        this.bfWritter = bfwritter;
    }

    public void setflWriter(FileWriter flwriter) {
        this.flWriter = flwriter;
    }   

    public void setLogDir(String logDir) {
        this.LogDir = logDir;
    }

    public void setLogLevel(int loglevel) {
        this.logLevel = loglevel;
    }   

    public void setScreenshotDir(String screenshotDir) {
        this.screenshotDir = screenshotDir;
    }

    public void setTCID(String currentTestCaseID) {
        this.currentTestCaseID = currentTestCaseID;
    }   

    public void setWebdr(WebDriver webdr) {
        this.webdr = webdr;
    }       

    public void setPassed(int passed) {
        this.passed = passed;
    }

    public void setFailed(int failed) {
        this.failed = failed;
    }
}

As for the FileUtils. This class was imported as part of the org.apache.commons.io.FileUtils


Solution

  • I was never able to solve that specific problem, but I found a solution that works even better. I used Java's Robot class, so I replace Selenium's method:

     File scrFile = ((TakesScreenshot) webdr).getScreenshotAs(OutputType.FILE);
    

    with the following Robot code:

            try {
            Robot       robot   = new Robot();
            Dimension   scrSize = Toolkit.getDefaultToolkit().getScreenSize();
    
            //Create the image 
            BufferedImage exportImage = robot.createScreenCapture(new Rectangle(0, 0, (int) scrSize.getWidth(), (int) scrSize.getHeight()));
    
            //Get graphics - Get the layer we can actually draw on
            Graphics2D imageGraphics = (Graphics2D) exportImage.getGraphics();
    
            //Cleanup after ourselves
            imageGraphics.dispose();
    
            screenShotName          = generateUniqueValue().retStringValue + ".png";
            String[] pathSections   = GlobalVars.getInstance().getLogDir().split("\\\\");
            pathSections[pathSections.length-1] = "";
    
            String path = "";
            for (int x = 0; x < pathSections.length-1; x++) {
                path = path + pathSections[x] + "\\";
            }
    

    That worked a lot better.