org.specrunner.webdriver.assertions.PluginCompareUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.specrunner.webdriver.assertions.PluginCompareUtils.java

Source

/*
SpecRunner - Acceptance Test Driven Development Tool
Copyright (C) 2011-2018  Thiago Santos
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
package org.specrunner.webdriver.assertions;

import java.util.LinkedList;
import java.util.List;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.specrunner.SRServices;
import org.specrunner.comparators.IComparator;
import org.specrunner.context.IBlock;
import org.specrunner.context.IContext;
import org.specrunner.plugins.PluginException;
import org.specrunner.result.IResultSet;
import org.specrunner.result.IWritableFactoryManager;
import org.specrunner.result.status.Failure;
import org.specrunner.result.status.Success;
import org.specrunner.util.UtilLog;
import org.specrunner.util.aligner.core.DefaultAlignmentException;
import org.specrunner.util.string.IStringNormalizer;
import org.specrunner.util.string.UtilString;

import nu.xom.Attribute;
import nu.xom.Element;
import nu.xom.Nodes;

/**
 * Comparison utilities.
 * 
 * @author Thiago Santos
 * 
 */
public final class PluginCompareUtils {

    /**
     * Hidden constructor.
     */
    private PluginCompareUtils() {
    }

    /**
     * Compare two strings.
     * 
     * @param expected
     *            The expected value.
     * @param received
     *            The received value.
     * @param block
     *            The block.
     * @param context
     *            The context.
     * @param result
     *            The result set.
     * @param client
     *            The web driver.
     * @return true, if equals, false, otherwise.
     * @throws PluginException
     *             On comparison errors.
     */
    public static boolean compare(String expected, String received, IBlock block, IContext context,
            IResultSet result, WebDriver client) throws PluginException {
        boolean res = true;
        if (expected.equals(received)) {
            result.addResult(Success.INSTANCE, block);
        } else {
            addError(expected, received, block, context, result, client);
            res = false;
        }
        return res;
    }

    /**
     * Add error to result.
     * 
     * @param expected
     *            The expected value.
     * @param received
     *            The received value.
     * @param block
     *            The block.
     * @param context
     *            The context.
     * @param result
     *            The result set.
     * @param client
     *            The web driver.
     * @throws PluginException
     *             On errors.
     */
    protected static void addError(String expected, String received, IBlock block, IContext context,
            IResultSet result, WebDriver client) throws PluginException {
        try {
            if (client == null) {
                result.addResult(Failure.INSTANCE, block, new DefaultAlignmentException(expected, received));
            } else {
                result.addResult(Failure.INSTANCE, block, new DefaultAlignmentException(expected, received),
                        SRServices.get(IWritableFactoryManager.class).get(WebDriver.class).newWritable(client));
            }
        } catch (Exception e) {
            if (UtilLog.LOG.isDebugEnabled()) {
                UtilLog.LOG.debug(e.getMessage(), e);
            }
            throw new PluginException(e);
        }
    }

    /**
     * Perform date comparisons.
     * 
     * @param compare
     *            The plugin which hold format and tolerance information.
     * @param expected
     *            The expected value.
     * @param received
     *            The received value.
     * @param iComparator
     * @param block
     *            The block.
     * @param context
     *            The context.
     * @param result
     *            The result set.
     * @param client
     *            The web driver.
     * @return true, of equals considering tolerance, false, otherwise.
     * @throws PluginException
     *             On comparison errors.
     */
    public static boolean compareDate(PluginCompareDate compare, String expected, String received,
            IComparator comparator, IBlock block, IContext context, IResultSet result, WebDriver client)
            throws PluginException {
        boolean res = true;
        DateTimeFormatter fmt = null;
        try {
            fmt = DateTimeFormat.forPattern(compare.getFormat());
        } catch (Exception e) {
            if (UtilLog.LOG.isDebugEnabled()) {
                UtilLog.LOG.debug(e.getMessage(), e);
            }
            result.addResult(Failure.INSTANCE, block, new PluginException(e));
            res = false;
        }
        if (fmt != null) {
            try {
                DateTime dtExpected = fmt.parseDateTime(expected);
                DateTime dtReceived = fmt.parseDateTime(received);
                if (comparator.match(dtExpected, dtReceived)) {
                    result.addResult(Success.INSTANCE, block);
                } else {
                    addError(expected, received, block, context, result, client);
                    res = false;
                }
            } catch (Exception e) {
                if (UtilLog.LOG.isDebugEnabled()) {
                    UtilLog.LOG.debug(e.getMessage(), e);
                }
                addError(expected, received, block, context, result, client);
            }
        }
        return res;
    }

    /**
     * Compare two nodes. The expected node can have less attributes than
     * received content, this is due to WebDriver API which does not provide
     * much reflection on WebElements.
     * 
     * @param compare
     *            The compare plugin.
     * @param expected
     *            The expected content.
     * @param received
     *            The received content.
     * @param block
     *            The context block.
     * @param context
     *            The context.
     * @param result
     *            The result information.
     * @return true, if can be considered equals, false, otherwise.
     */
    public static boolean compareNode(PluginCompareNode compare, Element expected, WebElement received,
            IBlock block, IContext context, IResultSet result) {
        int errors = compareTexts(compare, context, result, expected, received, 0);
        Nodes expChildren = expected.query("descendant::*");
        List<WebElement> recChildren = received.findElements(By.xpath("descendant::*"));
        List<WebElement> visible = new LinkedList<WebElement>();
        for (WebElement we : recChildren) {
            if (we.isDisplayed()) {
                visible.add(we);
            }
        }
        recChildren = visible;
        int min = Math.min(expChildren.size(), recChildren.size());
        for (int i = 0; i < min; i++) {
            errors = compareElements(compare, context, result, (Element) expChildren.get(i), recChildren.get(i),
                    errors);
        }
        int max = Math.max(expChildren.size(), recChildren.size());
        boolean onExpected = (max == expChildren.size());
        for (int i = min; i < max; i++) {
            errors++;
            if (onExpected) {
                result.addResult(Failure.INSTANCE, context.newBlock(expChildren.get(i), compare),
                        new PluginException("Missing element."));
            } else {
                result.addResult(Failure.INSTANCE, context.newBlock(expected, compare),
                        new PluginException("Extra element on screen."));
            }
        }
        if (errors == 0) {
            result.addResult(Success.INSTANCE, block);
        }
        return errors == 0;
    }

    /**
     * Compare two nodes by theirs texts.
     * 
     * @param compare
     *            The plugin.
     * @param context
     *            The context.
     * @param result
     *            The result set.
     * @param expected
     *            The expected content.
     * @param received
     *            The received content.
     * @param errors
     *            The errors count.
     * @return The errors count adjusted.
     */
    protected static int compareTexts(PluginCompareNode compare, IContext context, IResultSet result,
            Element expected, WebElement received, int errors) {
        IStringNormalizer sn = UtilString.getNormalizer();
        String strExpected = sn.normalize(expected.getValue());
        String strReceived = sn.normalize(received.getText());
        if (!strExpected.equals(strReceived)) {
            errors++;
            result.addResult(Failure.INSTANCE, context.newBlock(expected, compare),
                    new DefaultAlignmentException(strExpected, strReceived));
        }
        return errors;
    }

    /**
     * Compare two elements and return the number of errors in comparison.
     * 
     * @param compare
     *            The compare plugin.
     * @param context
     *            The context.
     * @param result
     *            The result.
     * @param e
     *            The expected content.
     * @param we
     *            The received content.
     * @param errors
     *            The errors count.
     * @return The errors count adjusted.
     */
    protected static int compareElements(PluginCompareNode compare, IContext context, IResultSet result, Element e,
            WebElement we, int errors) {
        errors = compareTexts(compare, context, result, e, we, errors);
        if (!e.getLocalName().equalsIgnoreCase(we.getTagName())) {
            errors++;
            result.addResult(Failure.INSTANCE, context.newBlock(e, compare),
                    new PluginException("Tag names do not match (expected: '" + e.getLocalName() + "', received: '"
                            + we.getTagName() + "'."));
        }
        for (int j = 0; j < e.getAttributeCount(); j++) {
            Attribute att = e.getAttribute(j);
            String name = att.getLocalName();
            String attExp = e.getAttributeValue(name);
            String attRec = we.getAttribute(name);
            if (attRec == null) {
                errors++;
                result.addResult(Failure.INSTANCE, context.newBlock(e, compare), new PluginException(
                        "Attribute '" + name + "' missing (expected: '" + name + "=" + attExp + "')."));
                continue;
            }
            String attRecNorm = compare.getNormalized(attRec);
            String attExpNorm = compare.getNormalized(attExp);
            boolean match = (compare.getContains() && attRecNorm.contains(attExpNorm))
                    || attExpNorm.equals(attRecNorm);
            if (!match) {
                errors++;
                result.addResult(Failure.INSTANCE, context.newBlock(e, compare), new PluginException("Attribute '"
                        + name + "' does not match (expected: '" + attExp + "', received: '" + attRec + "')."));
            }
        }
        return errors;
    }
}