
org.finra.jtaf.ewd.utils.ScreenshotUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jtaf-extwebdriver Show documentation
Show all versions of jtaf-extwebdriver Show documentation
ExtWebDriver is an enhancement to the WebDriver API, with features such as widget library, session management and extended functions
/*
* (C) Copyright 2013 Java Test Automation Framework Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.finra.jtaf.ewd.utils;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.finra.jtaf.ewd.session.SessionManager;
import org.finra.jtaf.ewd.timer.WidgetTimeoutException;
import org.finra.jtaf.ewd.widget.IElement;
import org.finra.jtaf.ewd.widget.WidgetException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.internal.Locatable;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.RemoteWebDriver;
/***
* Utilities to take and compare screenshots of elements
*
* @author Pulitand
*
*/
public class ScreenshotUtils {
private static Logger log = LoggerFactory.getLogger(ScreenshotUtils.class);
/***
* You can use this method to take your control pictures. Note that the file should be a png.
*
* @param element
* @param toSaveAs
* @throws IOException
* @throws WidgetException
* @throws WidgetTimeoutException
* @throws Exception
*/
public static void takeScreenshotOfElement(IElement element, File toSaveAs) throws IOException, WidgetException {
for(int i = 0; i < 10; i++) { //Loop up to 10x to ensure a clean screenshot was taken
log.info("Taking screen shot of locator " + element.getByLocator() + " ... attempt #" + (i+1));
//Scroll to element
element.scrollTo();
//Take picture of the page
WebDriver wd = SessionManager.getInstance().getCurrentSession().getWrappedDriver();
File screenshot;
boolean isRemote = false;
if(!(wd instanceof RemoteWebDriver)) {
screenshot = ((TakesScreenshot) wd).getScreenshotAs(OutputType.FILE);
}
else {
Augmenter augmenter = new Augmenter();
screenshot = ((TakesScreenshot) augmenter.augment(wd)).getScreenshotAs(OutputType.FILE);
isRemote = true;
}
BufferedImage fullImage = ImageIO.read(screenshot);
WebElement ele = element.getWebElement();
//Parse out the picture of the element
Point point = ele.getLocation();
int eleWidth = ele.getSize().getWidth();
int eleHeight = ele.getSize().getHeight();
int x;
int y;
if(isRemote) {
x = ((Locatable)ele).getCoordinates().inViewPort().getX();
y = ((Locatable)ele).getCoordinates().inViewPort().getY();
}
else {
x = point.getX();
y = point.getY();
}
log.debug("Screenshot coordinates x: "+x+", y: "+y);
BufferedImage eleScreenshot = fullImage.getSubimage(x, y, eleWidth, eleHeight);
ImageIO.write(eleScreenshot, "png", screenshot);
//Ensure clean snapshot (sometimes WebDriver takes bad pictures and they turn out all black)
if(!isBlack(ImageIO.read(screenshot))) {
FileUtils.copyFile(screenshot, toSaveAs);
break;
}
}
}
/***
* Take a screenshot of the browser content. Note that while using RemoteWebDriver sessions (ie: with
* Sauce Labs), the screenshot will be a full page of content--not only the visible content where the
* page is scrolled (as when using a non-RemoteWebDriver session).
*
* @param toSaveAs - name of the file to save the picture in (Note: must be PNG)
* @throws IOException
*/
public static void takeScreenshotOfPage(File toSaveAs) throws IOException {
WebDriver wd = SessionManager.getInstance().getCurrentSession().getWrappedDriver();
File screenshot;
if(!(wd instanceof RemoteWebDriver)) {
screenshot = ((TakesScreenshot) wd).getScreenshotAs(OutputType.FILE);
}
else {
Augmenter augmenter = new Augmenter();
screenshot = ((TakesScreenshot) augmenter.augment(wd)).getScreenshotAs(OutputType.FILE);
}
FileUtils.copyFile(screenshot, toSaveAs);
}
/***
* Prereq: The page on which you are taking the screenshot is fully loaded
*
* Take a screenshot of the element identified by element and save the file as toSaveAs
* (Note that this file should be saved as a png).
* Test that the control picture, controlPicture, is both the same size as,
* and, has a similarity value greater than or equal to the threshold.
*
* @param element - the element to be tested
* @param controlPicture - the file of the picture that will serve as the control
* @param toSaveAs - for example, save the file at "testData/textFieldWidget/screenshot.png"
* @param threshold - you are asserting that the similarity between the two pictures
* is a double greater than or equal to this double (between 0.0 and 1.0)
* @throws Exception
*/
public static boolean isSimilarToScreenshot(IElement element, File controlPicture, File
toSaveAs, double threshold) throws IOException, WidgetException {
takeScreenshotOfElement(element, toSaveAs);
log.info("Screenshot was successful. Comparing against control...");
BufferedImage var = ImageIO.read(toSaveAs);
BufferedImage cont = ImageIO.read(controlPicture);
return isSimilar(var, cont, threshold);
}
/***
* Prereq: The page on which you are taking the screenshot is fully loaded
*
* Take a screenshot of the element identified by element and save the file as toSaveAs
* (Note that this file should be saved as a png).
* Test that the control picture, controlPicture, is both the same size as,
* and, has a similarity value greater than or equal to the default threshold of .85.
*
* @param element - the element to be tested
* @param controlPicture - the file of the picture that will serve as the control
* @param toSaveAs - for example, save the file at "testData/textFieldWidget/screenshot.png"
* @throws WidgetException
* @throws IOException
* @throws Exception
*/
public static boolean isSimilarToScreenshot(IElement element, File controlPicture,
File toSaveAs) throws IOException, WidgetException {
return isSimilarToScreenshot(element, controlPicture, toSaveAs, .85);
}
private static boolean isBlack(BufferedImage var) {
double[] varArr = new double[var.getWidth()*var.getHeight()*3];
//unroll pixels
for(int i = 0; i < var.getHeight(); i++) {
for(int j = 0; j < var.getWidth(); j++) {
varArr[i*var.getWidth() + j + 0] = new Color(var.getRGB(j, i)).getRed();
varArr[i*var.getWidth() + j + 1] = new Color(var.getRGB(j, i)).getGreen();
varArr[i*var.getWidth() + j + 2] = new Color(var.getRGB(j, i)).getBlue();
}
}
//test if all are black
for(int i=0;i!=varArr.length;i++){
if(varArr[i] != 0)
return false;
}
return true;
}
private static boolean isSimilar(BufferedImage var, BufferedImage cont, double threshold) {
return similarity(var, cont) >= threshold;
}
//Returns a double between 0 and 1.0
private static double similarity(BufferedImage var, BufferedImage cont) {
double[] varArr = new double[var.getWidth()*var.getHeight()*3];
double[] contArr = new double[cont.getWidth()*cont.getHeight()*3];
if (varArr.length!=contArr.length)
throw new IllegalStateException("The pictures are different sizes!");
//unroll pixels
for(int i = 0; i < var.getHeight(); i++) {
for(int j = 0; j < var.getWidth(); j++) {
varArr[i*var.getWidth() + j + 0] = new Color(var.getRGB(j, i)).getRed();
contArr[i*cont.getWidth() + j + 0] = new Color(cont.getRGB(j, i)).getRed();
varArr[i*var.getWidth() + j + 1] = new Color(var.getRGB(j, i)).getGreen();
contArr[i*cont.getWidth() + j + 1] = new Color(cont.getRGB(j, i)).getGreen();
varArr[i*var.getWidth() + j + 2] = new Color(var.getRGB(j, i)).getBlue();
contArr[i*cont.getWidth() + j + 2] = new Color(cont.getRGB(j, i)).getBlue();
}
}
double mins=0;
double maxs=0;
for(int i=0;i!=varArr.length;i++){
if (varArr[i]>contArr[i]){
mins+=contArr[i];
maxs+=varArr[i];
} else {
mins+=varArr[i];
maxs+=contArr[i];
}
}
return mins/maxs;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy