Java tutorial
/** * Orignal work: Copyright 2015 www.seleniumtests.com * Modified work: Copyright 2016 www.infotel.com * Copyright 2017-2019 B.Hecquet * * 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.seleniumtests.it.driver; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.List; import javax.imageio.ImageIO; import org.apache.commons.io.FileUtils; import org.openqa.selenium.Dimension; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.testng.Assert; import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.seleniumtests.MockitoTest; import com.seleniumtests.core.SeleniumTestsContextManager; import com.seleniumtests.driver.WebUIDriver; import com.seleniumtests.driver.screenshots.ScreenShot; import com.seleniumtests.driver.screenshots.ScreenshotUtil; import com.seleniumtests.driver.screenshots.ScreenshotUtil.Target; import com.seleniumtests.it.driver.support.pages.DriverSubTestPage; import com.seleniumtests.it.driver.support.pages.DriverTestPage; import com.seleniumtests.util.FileUtility; import com.seleniumtests.util.HashCodeGenerator; import com.seleniumtests.util.helper.WaitHelper; import com.seleniumtests.util.imaging.ImageDetector; public class TestBrowserSnapshot extends MockitoTest { private static WebDriver driver; private final String browserName = "firefox"; @BeforeMethod(groups = { "it" }) public void initDriver(final ITestContext testNGCtx, final ITestResult testResult) throws Exception { initThreadContext(testNGCtx, null, testResult); SeleniumTestsContextManager.getThreadContext().setExplicitWaitTimeout(2); SeleniumTestsContextManager.getThreadContext().setBrowser(browserName); SeleniumTestsContextManager.getThreadContext().setSnapshotBottomCropping(0); SeleniumTestsContextManager.getThreadContext().setSnapshotTopCropping(0); // SeleniumTestsContextManager.getThreadContext().setWebDriverGrid("http://127.0.0.1:4444/wd/hub"); // SeleniumTestsContextManager.getThreadContext().setRunMode("grid"); // SeleniumTestsContextManager.getThreadContext().setBrowser("firefox"); // SeleniumTestsContextManager.getThreadContext().setFirefoxBinary("path to firefox"); new DriverTestPage(true); // start displaying page driver = WebUIDriver.getWebDriver(true); } @AfterMethod(groups = { "it" }, alwaysRun = true) public void closeBrowser() { WebUIDriver.cleanUp(); WebUIDriver.cleanUpWebUIDriver(); } /** * Read the capture file to detect dimension * It assumes that picture background is white and counts the number of white pixels in width and height (first column and first row) * @return * @throws IOException */ private Dimension getViewPortDimension(File picture) throws IOException { BufferedImage image = ImageIO.read(picture); int width = 0; int height = 0; for (width = 0; width < image.getWidth(); width++) { Color color = new Color(image.getRGB(width, 0)); if (!(color.equals(Color.WHITE) || color.equals(Color.YELLOW) || color.equals(Color.ORANGE) || color.equals(Color.GREEN) || color.equals(Color.RED))) { break; } } for (height = 0; height < image.getHeight(); height++) { Color color = new Color(image.getRGB(5, height)); if (!(color.equals(Color.WHITE) || color.equals(Color.YELLOW) || color.equals(Color.ORANGE) || color.equals(Color.GREEN) || color.equals(Color.RED))) { break; } } return new Dimension(width, height); } /** * Test page contains fixed header (yellow) and footer (orange) of 5 pixels height. Detect how many * pixels of these colors are present in picture * Also count red pixels which is a line not to remove when cropping * @param picture * @return * @throws IOException */ private int[] getHeaderAndFooterPixels(File picture) throws IOException { BufferedImage image = ImageIO.read(picture); int topPixels = 0; int bottomPixels = 0; int securityLine = 0; for (int height = 0; height < image.getHeight(); height++) { Color color = new Color(image.getRGB(0, height)); if (color.equals(Color.YELLOW)) { topPixels++; } else if (color.equals(Color.ORANGE)) { bottomPixels++; } else if (color.equals(Color.RED) || color.equals(Color.GREEN)) { securityLine++; } } return new int[] { topPixels, bottomPixels, securityLine }; } private String generateCaptureFilePath() { return SeleniumTestsContextManager.getThreadContext().getOutputDirectory() + "/" + HashCodeGenerator.getRandomHashCode("web") + ".png"; } private void captureSnapshot(String filePath) { String b64Img = new ScreenshotUtil(driver).capture(Target.PAGE, String.class); byte[] byteArray = b64Img.getBytes(); FileUtility.writeImage(filePath, byteArray); } /** * Test if we succeed in removing scrollbars from capture (horizontal and vertical) * @throws IOException */ @Test(groups = { "it" }) public void testRemoveScrollbarCapture() throws IOException { driver.manage().window().setSize(new Dimension(400, 300)); WaitHelper.waitForSeconds(1); // get real capture String origFilePath = generateCaptureFilePath(); captureSnapshot(origFilePath); Dimension screenshotDim = getViewPortDimension(new File(origFilePath)); // get cropped picture BufferedImage image = new ScreenshotUtil(driver).capture(Target.PAGE, BufferedImage.class); // check all scrollbars where already removed from screenshot Assert.assertEquals(image.getWidth(), screenshotDim.width); Assert.assertEquals(image.getHeight(), screenshotDim.height); } /** * Test when no scrollbar is present in capture * @throws Exception */ @Test(groups = { "it" }) public void testNoScrollbarCapture() throws Exception { new DriverSubTestPage(true); // get real capture String origFilePath = generateCaptureFilePath(); captureSnapshot(origFilePath); Dimension screenshotDim = getViewPortDimension(new File(origFilePath)); // get cropped picture BufferedImage image = new ScreenshotUtil(driver).capture(Target.PAGE, BufferedImage.class); // check all scrollbars where already removed from screenshot Assert.assertEquals(image.getWidth(), screenshotDim.width); Assert.assertEquals(image.getHeight(), screenshotDim.height); } /** * Test if we succeed in cropping picture according to requested parameters * @throws IOException */ @Test(groups = { "it" }) public void testRemoveHeader() throws IOException { driver.manage().window().setSize(new Dimension(400, 300)); WaitHelper.waitForSeconds(1); // get cropped picture String filePath = generateCaptureFilePath(); BufferedImage image = new ScreenshotUtil(driver).capturePage(6, 0); FileUtility.writeImage(filePath, image); int[] headerFooter = getHeaderAndFooterPixels(new File(filePath)); // header should have been removed, not footer Assert.assertEquals(0, headerFooter[0]); Assert.assertEquals(5, headerFooter[1]); Assert.assertEquals(2, headerFooter[2]); } /** * Test if we succeed in cropping picture according to requested parameters * @throws IOException */ @Test(groups = { "it" }) public void testRemoveFooter() throws IOException { driver.manage().window().setSize(new Dimension(400, 300)); WaitHelper.waitForSeconds(1); // get cropped picture String filePath = generateCaptureFilePath(); BufferedImage image = new ScreenshotUtil(driver).capturePage(0, 5); FileUtility.writeImage(filePath, image); int[] headerFooter = getHeaderAndFooterPixels(new File(filePath)); // header should have been removed, not footer Assert.assertEquals(6, headerFooter[0]); Assert.assertEquals(0, headerFooter[1]); Assert.assertEquals(2, headerFooter[2]); } /** * Test if we succeed in cropping picture according to requested parameters * @throws IOException */ @Test(groups = { "it" }) public void testRemoveHeaderAndFooter() throws IOException { driver.manage().window().setSize(new Dimension(400, 300)); WaitHelper.waitForSeconds(1); // get cropped picture String filePath = generateCaptureFilePath(); BufferedImage image = new ScreenshotUtil(driver).capturePage(6, 5); FileUtility.writeImage(filePath, image); int[] headerFooter = getHeaderAndFooterPixels(new File(filePath)); // header should have been removed, not footer Assert.assertEquals(0, headerFooter[0]); Assert.assertEquals(0, headerFooter[1]); Assert.assertEquals(2, headerFooter[2]); } /** * Check we can rebuild the whole page from partial captures * This is useful for chrome as snapshot is only taken from visible display * For firefox, nothing to do * @throws IOException */ @Test(groups = { "it" }) public void testCaptureAllPage() throws IOException { driver.manage().window().setSize(new Dimension(400, 300)); WaitHelper.waitForSeconds(1); String topFilePath = generateCaptureFilePath(); FileUtility.writeImage(topFilePath, new ScreenshotUtil(driver).capturePage(0, 0)); // get full picture File image = new ScreenshotUtil(driver).capture(Target.PAGE, File.class); String bottomFilePath = generateCaptureFilePath(); FileUtility.writeImage(bottomFilePath, new ScreenshotUtil(driver).capturePage(0, 0)); // exception thrown if nothing found ImageDetector detectorTop = new ImageDetector(image, new File(topFilePath), 0.001); detectorTop.detectExactZoneWithScale(); } /** * Check we are able to get all the content whereas we crop the header and footer * @throws IOException */ @Test(groups = { "it" }) public void testFixedHeaderFooterCropping() throws IOException { driver.manage().window().setSize(new Dimension(400, 300)); WaitHelper.waitForSeconds(1); // get full picture without cropping File imageFull = new ScreenshotUtil(driver).capture(Target.PAGE, File.class); SeleniumTestsContextManager.getThreadContext().setSnapshotBottomCropping(5); SeleniumTestsContextManager.getThreadContext().setSnapshotTopCropping(6); // get picture with header and footer cropped File image = new ScreenshotUtil(driver).capture(Target.PAGE, File.class); int[] headerFooter = getHeaderAndFooterPixels(image); int[] headerFooterFull = getHeaderAndFooterPixels(imageFull); // header and footer should have been removed Assert.assertEquals(6, headerFooter[0]); Assert.assertEquals(5, headerFooter[1]); Assert.assertTrue(headerFooter[2] >= headerFooterFull[2]); // depending on browser window size (depends on OS) image is split in more or less sections Assert.assertEquals(ImageIO.read(image).getHeight(), ImageIO.read(imageFull).getHeight()); } /** * Check we get capture for each window * Check also we remain on the same window handle after the capture * Check that first captured image (popup) is smaller than the second one (main page) */ @Test(groups = { "it" }) public void testMultipleWindowsCapture() { String currentWindowHandle = driver.getWindowHandle(); DriverTestPage.link.click(); List<ScreenShot> screenshots = new ScreenshotUtil().capture(Target.PAGE, ScreenShot.class, true, false); Assert.assertEquals(screenshots.size(), 2); Assert.assertEquals(currentWindowHandle, driver.getWindowHandle()); Assert.assertTrue( FileUtils.sizeOf(new File(((ScreenShot) screenshots.get(0)).getFullImagePath())) < FileUtils .sizeOf(new File(((ScreenShot) screenshots.get(1)).getFullImagePath()))); } /** * Check that when an error occurs when communicating with driver, a desktop capture is taken */ @Test(groups = { "it" }) public void testMultipleWindowsCaptureWithError() { DriverTestPage.link.click(); WebDriver mockedDriver = spy(driver); ScreenshotUtil screenshotUtil = spy(new ScreenshotUtil(mockedDriver)); when(mockedDriver.getWindowHandles()).thenThrow(WebDriverException.class); List<ScreenShot> screenshots = screenshotUtil.capture(Target.PAGE, ScreenShot.class, true, false); Assert.assertEquals(screenshots.size(), 1); verify(screenshotUtil).captureDesktop(); } /** * Check we can capture desktop snapshots */ @Test(groups = { "it" }) public void testDesktopSnapshot() { File output = new ScreenshotUtil(driver).capture(Target.SCREEN, File.class); Assert.assertTrue(FileUtils.sizeOf(output) > 0); } /** * Check that only main window is captured */ @Test(groups = { "it" }) public void testCurrentWindowsCapture() { String currentWindowHandle = driver.getWindowHandle(); DriverTestPage.link.click(); List<ScreenShot> screenshots = new ScreenshotUtil(driver).capture(Target.PAGE, ScreenShot.class, false, false); Assert.assertEquals(screenshots.size(), 1); Assert.assertEquals(currentWindowHandle, driver.getWindowHandle()); } /** * Check that only main window is captured when no argument is given */ @Test(groups = { "it" }) public void testCurrentWindowsCapture2() { DriverTestPage.link.click(); ScreenShot screenshot = new ScreenshotUtil(driver).capture(Target.PAGE, ScreenShot.class); Assert.assertNotNull(screenshot.getImagePath()); } }