com.galenframework.api.GalenPageDump.java Source code

Java tutorial

Introduction

Here is the source code for com.galenframework.api.GalenPageDump.java

Source

/*******************************************************************************
* Copyright 2017 Ivan Shubin http://galenframework.com
* 
* 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.galenframework.api;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;

import com.galenframework.browser.Browser;
import com.galenframework.browser.SeleniumBrowser;
import com.galenframework.page.PageElement;
import com.galenframework.page.Rect;
import com.galenframework.rainbow4j.Rainbow4J;

import com.galenframework.speclang2.pagespec.PageSpecReader;
import com.galenframework.specs.page.Locator;
import com.galenframework.specs.page.PageSpec;
import com.galenframework.speclang2.pagespec.SectionFilter;
import com.galenframework.utils.GalenUtils;
import com.galenframework.validation.PageValidation;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.openqa.selenium.WebDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;

public class GalenPageDump {

    private final static Logger LOG = LoggerFactory.getLogger(GalenPageDump.class);
    private static final List<String> EMPTY_TAGS = Collections.emptyList();
    private boolean onlyImages = false;

    private String pageName;

    private Integer maxWidth = null;
    private Integer maxHeight = null;
    private Properties properties;
    private Map<String, Object> jsVariables;
    private Map<String, Locator> objects;
    private List<String> excludedObjects;

    public GalenPageDump(String pageName) {
        setPageName(pageName);
    }

    public void dumpPage(WebDriver driver, String pageSpecPath, String reportFolderPath) throws IOException {
        Browser browser = new SeleniumBrowser(driver);
        dumpPage(browser, loadPageSpec(browser, pageSpecPath), reportFolderPath);
    }

    private PageSpec loadPageSpec(Browser browser, String pageSpecPath) throws IOException {
        PageSpecReader reader = new PageSpecReader();
        return reader.read(pageSpecPath, browser.getPage(), new SectionFilter(EMPTY_TAGS, EMPTY_TAGS), properties,
                jsVariables, objects);
    }

    public void dumpPage(Browser browser, String pageSpecPath, String reportFolderPath) throws IOException {
        dumpPage(browser, loadPageSpec(browser, pageSpecPath), reportFolderPath);
    }

    public void dumpPage(Browser browser, PageSpec pageSpec, String reportFolderPath) throws IOException {
        File reportFolder = new File(reportFolderPath);
        if (!reportFolder.exists()) {
            if (!reportFolder.mkdirs()) {
                throw new RuntimeException("Cannot create dir: " + reportFolder.getAbsolutePath());
            }
        }

        Set<String> objectNames = pageSpec.getObjects().keySet();
        PageValidation pageValidation = new PageValidation(browser, browser.getPage(), pageSpec, null, null);

        PageDump pageDump = new PageDump();
        pageDump.setTitle(browser.getPage().getTitle());

        List<Pattern> patterns = convertPatterns(excludedObjects);

        Set<String> finalObjectNames = new HashSet<>();
        finalObjectNames.addAll(objectNames);
        finalObjectNames.add("screen");
        finalObjectNames.add("viewport");

        for (String objectName : finalObjectNames) {
            if (!matchesExcludedPatterns(objectName, patterns)) {
                PageElement pageElement = pageValidation.findPageElement(objectName);

                if (pageElement.isVisible() && pageElement.getArea() != null) {
                    PageDump.Element element = new PageDump.Element(objectName, pageElement.getArea().toIntArray());

                    if (pageElement.isPresent() && pageElement.isVisible()
                            && isWithinArea(pageElement, maxWidth, maxHeight)) {
                        element.setHasImage(true);
                    }
                    pageDump.addElement(element);
                }
            }
        }

        if (!onlyImages) {
            pageDump.setPageName(pageName);
            exportAsJson(pageDump, new File(reportFolder.getAbsoluteFile() + File.separator + "page.json"));
            exportAsHtml(pageDump, pageName,
                    new File(reportFolder.getAbsoluteFile() + File.separator + "page.html"));
            copyResource("/html-report/jquery-1.11.2.min.js",
                    new File(reportFolder.getAbsolutePath() + File.separator + "jquery-1.11.2.min.js"));
            copyResource("/pagedump/galen-pagedump.js",
                    new File(reportFolder.getAbsolutePath() + File.separator + "galen-pagedump.js"));
            copyResource("/pagedump/galen-pagedump.css",
                    new File(reportFolder.getAbsolutePath() + File.separator + "galen-pagedump.css"));
        }

        exportAllScreenshots(pageDump, browser, reportFolder);
    }

    private boolean matchesExcludedPatterns(String objectName, List<Pattern> patterns) {
        for (Pattern pattern : patterns) {
            if (pattern.matcher(objectName).matches()) {
                return true;
            }
        }
        return false;
    }

    private List<Pattern> convertPatterns(List<String> excludedObjects) {
        List<Pattern> patterns = new LinkedList<>();
        if (excludedObjects != null) {
            for (String excludedObject : excludedObjects) {
                patterns.add(GalenUtils.convertObjectNameRegex(excludedObject));
            }
        }
        return patterns;
    }

    public void exportAsJson(PageDump pageDump, File file) throws IOException {
        makeSureFileExists(file);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.writeValue(file, pageDump);
    }

    public void exportAsHtml(PageDump pageDump, String title, File file) throws IOException {
        makeSureFileExists(file);
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonText = objectMapper.writeValueAsString(pageDump);

        String template = IOUtils.toString(getClass().getResourceAsStream("/pagedump/page.html"));

        String htmlText = template.replace("${title}", title);
        htmlText = htmlText.replace("${json}", jsonText);

        FileUtils.writeStringToFile(file, htmlText);
    }

    public void makeSureFileExists(File file) throws IOException {
        if (!file.exists()) {
            if (!file.createNewFile()) {
                throw new RuntimeException("Couldn't create file: " + file.getAbsolutePath());
            }
        }
    }

    public void exportAllScreenshots(PageDump pageDump, Browser browser, File reportFolder) throws IOException {

        File screenshotOriginalFile = browser.getPage().getScreenshotFile();

        FileUtils.copyFile(screenshotOriginalFile,
                new File(reportFolder.getAbsolutePath() + File.separator + "page.png"));

        BufferedImage image = Rainbow4J.loadImage(screenshotOriginalFile.getAbsolutePath());

        File objectsFolder = new File(reportFolder.getAbsolutePath() + File.separator + "objects");
        objectsFolder.mkdirs();

        for (PageDump.Element element : pageDump.getItems().values()) {
            if (element.getHasImage()) {
                int[] area = element.getArea();

                if (area[0] < image.getWidth() && area[1] < image.getHeight()) {
                    int x = Math.max(area[0], 0);
                    int y = Math.max(area[1], 0);

                    int x2 = Math.min(area[0] + area[2], image.getWidth());
                    int y2 = Math.min(area[1] + area[3], image.getHeight());

                    int availableWidth = x2 - x;
                    int availableHeight = y2 - y;

                    try {
                        if (availableWidth > 0 && availableHeight > 0) {
                            BufferedImage subImage = image.getSubimage(x, y, availableWidth, availableHeight);
                            Rainbow4J.saveImage(subImage, new File(objectsFolder.getAbsolutePath() + File.separator
                                    + element.getObjectName() + ".png"));
                        } else {
                            element.setHasImage(false);
                        }
                    } catch (Exception ex) {
                        LOG.error("Got error during saving image", ex);
                    }
                }
            }
        }
    }

    private static void copyResource(String resourceName, File destFile) throws IOException {
        String value = IOUtils.toString(Galen.class.getResourceAsStream(resourceName));
        FileUtils.writeStringToFile(destFile, value);
    }

    private static boolean isWithinArea(PageElement element, Integer maxWidth, Integer maxHeight) {
        Rect area = element.getArea();
        if (maxWidth != null && maxHeight != null) {
            return maxWidth * maxHeight > area.getWidth() * area.getHeight();
        } else if (maxWidth != null) {
            return maxWidth > area.getWidth();
        } else if (maxHeight != null) {
            return maxHeight > area.getHeight();
        } else
            return true;
    }

    public String getPageName() {
        return pageName;
    }

    public GalenPageDump setPageName(String pageName) {
        this.pageName = pageName;
        return this;
    }

    public GalenPageDump setProperties(Properties properties) {
        this.properties = properties;
        return this;
    }

    public GalenPageDump setJsVariables(Map<String, Object> jsVariables) {
        this.jsVariables = jsVariables;
        return this;
    }

    public void setObjects(Map<String, Locator> objects) {
        this.objects = objects;
    }

    public Integer getMaxHeight() {
        return maxHeight;
    }

    public Integer getMaxWidth() {
        return maxWidth;
    }

    public GalenPageDump setMaxHeight(Integer maxHeight) {
        this.maxHeight = maxHeight;
        return this;
    }

    public GalenPageDump setMaxWidth(Integer maxWidth) {
        this.maxWidth = maxWidth;
        return this;
    }

    public GalenPageDump setOnlyImages(boolean onlyImages) {
        this.onlyImages = onlyImages;
        return this;
    }

    public boolean isOnlyImages() {
        return onlyImages;
    }

    public GalenPageDump setExcludedObjects(List<String> excludedObjects) {
        this.excludedObjects = excludedObjects;
        return this;
    }

    public List<String> getExcludedObjects() {
        return excludedObjects;
    }
}