/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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 com.vaadin.tests.tb3;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import org.openqa.selenium.Dimension;
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 com.vaadin.testbench.Parameters;
import com.vaadin.testbench.screenshot.ImageComparison;
import com.vaadin.testbench.screenshot.ImageFileUtil;
/**
* Internal hack to support capturing screenshots for elements.
*
* Most parts are from TestBenchCommandExecutor and the feature should be
* integrated into TB4.
*
* @author Vaadin Ltd
*/
public class CustomTestBenchCommandExecutor {
private ImageComparison imageComparison = new ImageComparison();
private final WebDriver actualDriver;
public CustomTestBenchCommandExecutor(WebDriver driver) {
actualDriver = driver;
}
/**
* Compares the screenshot of the given element with the reference.
*
* Copied from TestBenchCommandExecutor
*/
public boolean compareScreen(WebElement element, File reference)
throws IOException {
BufferedImage image = null;
try {
image = ImageIO.read(reference);
} catch (IIOException e) {
// Don't worry, an error screen shot will be generated that later
// can be used as the reference
}
return compareScreen(element, image, reference.getName());
}
/**
* Compares the screenshot of the given element with the reference.
*
* Copied from TestBenchCommandExecutor and added cropToElement
*/
public boolean compareScreen(WebElement element, BufferedImage reference,
String referenceName) throws IOException {
for (int times = 0; times < Parameters
.getMaxScreenshotRetries(); times++) {
BufferedImage screenshotImage = cropToElement(element,
ImageIO.read(new ByteArrayInputStream(
((TakesScreenshot) actualDriver)
.getScreenshotAs(OutputType.BYTES))));
if (reference == null) {
// Store the screenshot in the errors directory and fail the
// test
ImageFileUtil.createScreenshotDirectoriesIfNeeded();
ImageIO.write(screenshotImage, "png",
ImageFileUtil.getErrorScreenshotFile(referenceName));
getLogger().severe("No reference found for " + referenceName
+ " in "
+ ImageFileUtil.getScreenshotReferenceDirectory());
return false;
}
if (imageComparison.imageEqualToReference(screenshotImage,
reference, referenceName,
Parameters.getScreenshotComparisonTolerance())) {
return true;
}
pause(Parameters.getScreenshotRetryDelay());
}
return false;
}
/**
* Crops the image to show only the element. If the element is partly off
* screen, crops to show the part of the element which is in the screenshot
*
* @param element
* the element to retain in the screenshot
* @param fullScreen
* the full screen image
* @return
* @throws IOException
*/
public static BufferedImage cropToElement(WebElement element,
BufferedImage fullScreen) throws IOException {
Point loc = element.getLocation();
Dimension size = element.getSize();
int x = loc.x, y = loc.y;
int w = size.width;
int h = size.height;
if (x >= 0 && x < fullScreen.getWidth()) {
// X loc on screen
// Get the part of the element which is on screen
w = Math.min(fullScreen.getWidth() - x, w);
} else {
throw new IOException("Element x is outside the screenshot (x: " + x
+ ", y: " + y + ")");
}
if (y >= 0 && y < fullScreen.getHeight()) {
// Y loc on screen
// Get the part of the element which is on screen
h = Math.min(fullScreen.getHeight() - y, h);
} else {
throw new IOException("Element y is outside the screenshot (x: " + x
+ ", y: " + y + ")");
}
return fullScreen.getSubimage(x, y, w, h);
}
private void pause(int delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
}
}
private static Logger getLogger() {
return Logger.getLogger(CustomTestBenchCommandExecutor.class.getName());
}
}