This repository has been archived by the owner on Jan 12, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from dpulitano/master
Add ScreenshotUtils code and tests, scrollTo code and test, focusOn code and test, isElementVisibleWithinBoundsOfScreen code
- Loading branch information
Showing
9 changed files
with
475 additions
and
1 deletion.
There are no files selected for viewing
217 changes: 217 additions & 0 deletions
217
src/main/java/org/finra/jtaf/ewd/utils/ScreenshotUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
/* | ||
* (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.apache.log4j.Logger; | ||
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 = Logger.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.getLocator() + " ... attempt #" + (i+1)); | ||
|
||
//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); | ||
element.waitForElementPresent(); | ||
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(); | ||
element.scrollTo(); | ||
} | ||
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; | ||
} | ||
} | ||
} | ||
|
||
/*** | ||
* 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; | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.