From c9fe5b8bcd6ce6ea0eaeb5208044208d74577690 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 26 Jun 2015 11:17:58 +0300 Subject: [PATCH] Support taking test screenshots of individual elements Change-Id: I8fc5df882aa1ce0c897777111a2ac49856bd91cc --- .../tb3/CustomTestBenchCommandExecutor.java | 165 ++++++++++++++++++ .../vaadin/tests/tb3/ScreenshotTB3Test.java | 29 ++- 2 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 uitest/src/com/vaadin/tests/tb3/CustomTestBenchCommandExecutor.java diff --git a/uitest/src/com/vaadin/tests/tb3/CustomTestBenchCommandExecutor.java b/uitest/src/com/vaadin/tests/tb3/CustomTestBenchCommandExecutor.java new file mode 100644 index 0000000000..a70eeeeb49 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/CustomTestBenchCommandExecutor.java @@ -0,0 +1,165 @@ +/* + * Copyright 2000-2014 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, + boolean isIE8) 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(), isIE8); + } + + /** + * 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, boolean isIE8) throws IOException { + for (int times = 0; times < Parameters.getMaxScreenshotRetries(); times++) { + BufferedImage screenshotImage = cropToElement(element, + ImageIO.read(new ByteArrayInputStream( + ((TakesScreenshot) actualDriver) + .getScreenshotAs(OutputType.BYTES))), isIE8); + 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 + * @param isIE8 + * true if the browser is IE8 + * @return + * @throws IOException + */ + private BufferedImage cropToElement(WebElement element, + BufferedImage fullScreen, boolean isIE8) 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 (isIE8) { + // IE8 border... + x += 2; + y += 2; + } + 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()); + } +} diff --git a/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java b/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java index e059dea78d..6b8fb1741b 100644 --- a/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java +++ b/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java @@ -30,6 +30,8 @@ import org.junit.Rule; import org.junit.rules.TestRule; import org.junit.rules.TestWatcher; import org.junit.runner.Description; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DesiredCapabilities; import com.vaadin.testbench.Parameters; @@ -119,6 +121,11 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test { * @throws IOException */ protected void compareScreen(String identifier) throws IOException { + compareScreen(null, identifier); + } + + protected void compareScreen(WebElement element, String identifier) + throws IOException { if (identifier == null || identifier.isEmpty()) { throw new IllegalArgumentException("Empty identifier not supported"); } @@ -129,7 +136,17 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test { List failedReferenceFiles = new ArrayList(); for (File referenceFile : referenceFiles) { - if (testBench(driver).compareScreen(referenceFile)) { + boolean match = false; + if (element == null) { + // Full screen + match = testBench(driver).compareScreen(referenceFile); + } else { + // Only the element + match = customTestBench(driver).compareScreen(element, + referenceFile, + BrowserUtil.isIE8(getDesiredCapabilities())); + } + if (match) { // There might be failure files because of retries in TestBench. deleteFailureFiles(getErrorFileFromReference(referenceFile)); break; @@ -180,6 +197,16 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test { } } + private CustomTestBenchCommandExecutor customTestBench = null; + + private CustomTestBenchCommandExecutor customTestBench(WebDriver driver) { + if (customTestBench == null) { + customTestBench = new CustomTestBenchCommandExecutor(driver); + } + + return customTestBench; + } + private void enableAutoswitch(File htmlFile) throws FileNotFoundException, IOException { if (htmlFile == null || !htmlFile.exists()) { -- 2.39.5