org.richfaces.tests.metamer.ftest.webdriver.Attributes.java Source code

Java tutorial

Introduction

Here is the source code for org.richfaces.tests.metamer.ftest.webdriver.Attributes.java

Source

/*******************************************************************************
 * JBoss, Home of Professional Open Source
 * Copyright 2010-2013, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 *******************************************************************************/
package org.richfaces.tests.metamer.ftest.webdriver;

import java.util.List;

import org.apache.commons.lang.Validate;
import org.jboss.arquillian.ajocado.dom.Event;
import org.jboss.arquillian.ajocado.javascript.JavaScript;
import org.jboss.arquillian.ajocado.locator.JQueryLocator;
import org.jboss.arquillian.graphene.context.GrapheneContext;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import org.richfaces.tests.metamer.ftest.attributes.AttributeEnum;
import org.richfaces.tests.metamer.ftest.webdriver.MetamerPage.WaitRequestType;
import org.richfaces.tests.metamer.ftest.webdriver.utils.StringEqualsWrapper;
import org.richfaces.tests.metamer.ftest.webdriver.utils.WebElementProxyUtils;
import org.richfaces.tests.page.fragments.impl.Utils;

/**
 * @author <a href="mailto:jstefek@redhat.com">Jiri Stefek</a>
 */
public class Attributes<T extends AttributeEnum> {

    protected WebDriver driver = GrapheneContext.getProxy();
    private final String attributesID;
    private static final String PROPERTY_CSS_SELECTOR = "[id$='%s:%sInput']";
    private static final String NULLSTRING = "null";
    private static final String[] NULLSTRINGOPTIONS = { "null", "", " " };
    private static final int WAITTIME = 100;
    private static final int NUMBEROFTRIES = 5;

    public Attributes() {
        this.attributesID = "";
    }

    public Attributes(String attributesID) {
        this.attributesID = attributesID;
    }

    public void set(T attribute, String string) {
        setProperty(attribute.toString(), string);
    }

    /**
     * Setter for special cases. For example, 'for' is reserved java word, but
     * valid richfaces attribute as well. So we use this attribute name in upper
     * case in enum, and then set by special method to avoid overload by
     * toLowerCase-in over the whole world of richfaces attributes
     *
     * @param attribute
     * @param string
     */
    public void setLower(T attribute, String string) {
        setProperty(attribute.toString().toLowerCase(), string);
    }

    // TODO jjamrich 2011-09-02: make sure that this resolve to correct string representation of number given as attr
    public void set(T attribute, Number no) {
        setProperty(attribute.toString(), no);
    }

    public void set(T attribute, Boolean bool) {
        setProperty(attribute.toString(), bool);
    }

    public void set(T attribute, JavaScript js) {
        setProperty(attribute.toString(), js);
    }

    public void set(T attribute, JQueryLocator locator) {
        setProperty(attribute.toString(), locator.getRawLocator());
    }

    public void set(T attribute, Enum<?> item) {
        setProperty(attribute.toString(), item.toString());
    }

    public void set(T attribute, Event event) {
        setProperty(attribute.toString(), event.getEventName());
    }

    public void reset(T attribute) {
        setProperty(attribute.toString(), "");
    }

    /**
     * Sets attribute and checks if it was really set (waits for page
     * re-render).
     *
     * @param propertyName
     * @param value
     */
    protected void setProperty(String propertyName, Object value) {
        String valueAsString = (value == null ? NULLSTRING : value.toString());
        //element for all types of input elements
        WebElement foundElementProxy = WebElementProxyUtils
                .createProxyForElement(getCssSelectorForProperty(propertyName));
        //handle the property by the tagname of the input element
        Tag tag = Tag.getTag(foundElementProxy);
        switch (tag) {
        case input:
            applyText(propertyName, valueAsString);
            break;
        case checkbox:
            throw new UnsupportedOperationException("Checkboxes are not supported");
        case radio:
            applyRadio(tag, valueAsString);
            break;
        case select:
            applySelect(tag, valueAsString);
            break;
        default:
            throw new IllegalArgumentException("Unknown property");
        }
        checkIfPropertyWasSet(propertyName, valueAsString);
    }

    /**
     * Sets text property. Cleans input field, if there is something.
     *
     * @param propertyName name of the property that should change
     * @param value value to be set
     */
    private void applyText(String propertyName, String value) {
        WebElement input = WebElementProxyUtils.createProxyForElement(getCssSelectorForProperty(propertyName));
        String text = input.getAttribute("value");
        if (!value.equals(text)) {
            if (!text.isEmpty()) {
                Utils.jQ("val('')", input);
            }
            input.sendKeys(value);
            MetamerPage.waitRequest(input, WaitRequestType.HTTP).submit();
        }
    }

    private void applyRadio(Tag tag, String valueToBeSet) {
        Validate.notEmpty(tag.radioElements, "No options from which can be selected.");

        for (WebElement element : tag.radioElements) {
            String attributeValue = element.getAttribute("value");
            if (valueToBeSet.equals(NULLSTRING)) {
                if (new StringEqualsWrapper(attributeValue).isSimilarToSomeOfThis(NULLSTRINGOPTIONS)) {
                    if (!element.isSelected()) {
                        MetamerPage.waitRequest(element, WaitRequestType.HTTP).click();
                    }
                    return;
                }
            } else if (valueToBeSet.equals(attributeValue)) {
                if (!element.isSelected()) {
                    MetamerPage.waitRequest(element, WaitRequestType.HTTP).click();
                }
                return;
            } else if (attributeValue.contains(valueToBeSet)) {
                //for image selection radios, which value contains a source url of the image
                if (!element.isSelected()) {
                    MetamerPage.waitRequest(element, WaitRequestType.HTTP).click();
                }
                return;
            }
        }
        throw new IllegalArgumentException("No property with value " + valueToBeSet + " was found");
    }

    private void applySelect(Tag tag, String value) {
        Validate.notEmpty(tag.selection.getOptions(), "No options from which can be selected.");

        if (value.equals(NULLSTRING)) {
            for (WebElement element : tag.selection.getOptions()) {
                String val = element.getAttribute("value");
                if (new StringEqualsWrapper(val).isSimilarToSomeOfThis(NULLSTRINGOPTIONS)) {
                    if (!element.isSelected()) {
                        MetamerPage.waitRequest(element, WaitRequestType.HTTP).click();
                    }
                    return;
                }
            }
        } else {
            tag.selection.selectByValue(value);
            return;
        }
        throw new IllegalArgumentException("No property with value " + value + " was found");
    }

    /**
     * Retrieve current attribute value
     *
     * @param attribute
     * @return current attribute value
     */
    public String get(T attribute) {
        return getProperty(attribute.toString());
    }

    private By getCssSelectorForProperty(String property) {
        return By.cssSelector(String.format(PROPERTY_CSS_SELECTOR, attributesID, property));
    }

    /**
     * Gets String representation of attribute value set in page.
     *
     * @param propertyName string name of attribute
     * @return
     */
    private String getProperty(String propertyName) {
        WebElement foundElementProxy = WebElementProxyUtils
                .createProxyForElement(getCssSelectorForProperty(propertyName));
        //handle the property by the tagname of the input element
        Tag tag = Tag.getTag(foundElementProxy);
        switch (tag) {
        case input:
            return foundElementProxy.getAttribute("value");
        case checkbox:
            throw new UnsupportedOperationException("Checkboxes are not supported");
        case radio:
            return getValueFromRadio(tag);
        case select:
            return getValueFromSelect(tag);
        default:
            throw new IllegalArgumentException("Unknown property: " + propertyName);
        }
    }

    private String getValueFromRadio(Tag tag) {
        Validate.notEmpty(tag.radioElements, "No inputs for this attribute found");

        WebElement nullSelectionOption = null;
        for (WebElement webElement : tag.radioElements) {
            String value = webElement.getAttribute("value");
            if (new StringEqualsWrapper(value).isSimilarToSomeOfThis(NULLSTRINGOPTIONS)) {
                nullSelectionOption = webElement;
            }
            if (webElement.isSelected()) {
                return webElement.getAttribute("value");
            }
        }
        if (nullSelectionOption != null) {
            //workaround for String options with value="" , used in attributes like
            //action, actionListener, model...
            //they do not preserve its selected state
            return NULLSTRING;
        }
        throw new IllegalArgumentException("No selected choice for this attribute found.");
    }

    private String getValueFromSelect(Tag tag) {
        Validate.notEmpty(tag.selection.getOptions(), "No inputs for this attribute found");

        WebElement nullSelectionOption = null;
        for (WebElement webElement : tag.selection.getAllSelectedOptions()) {
            String value = webElement.getAttribute("value");
            if (new StringEqualsWrapper(value).isSimilarToSomeOfThis(NULLSTRINGOPTIONS)) {
                nullSelectionOption = webElement;
            }
            if (webElement.isSelected()) {
                return webElement.getAttribute("value");
            }
        }
        if (nullSelectionOption != null) {
            //workaround for String options with value="" , used in attributes like
            //action, actionListener, model...
            //they do not preserve its selected state
            return NULLSTRING;
        }
        throw new IllegalArgumentException("No selected choice for this attribute found.");
    }

    /**
     * Wait for page to load after attribute was set and then ckecks if it
     * really was set. If it was not set, then IllegalStateException is thrown.
     *
     * @param propertyName string value of attribute
     * @param value value that the attribute should have
     */
    private void checkIfPropertyWasSet(String propertyName, String value) {
        String property;
        for (int i = 0; i < NUMBEROFTRIES; i++) {
            try {
                property = getProperty(propertyName);
                if (value.equals(NULLSTRING)) {
                    if (new StringEqualsWrapper(property).isSimilarToSomeOfThis(NULLSTRINGOPTIONS)) {
                        return;
                    }
                } else if (property.contains(value)) {
                    return;
                }
                waiting(WAITTIME);
            } catch (Exception ignored) {
                waiting(WAITTIME);
            }
        }
        throw new IllegalStateException("Property " + propertyName + " was not changed.");
    }

    /**
     * Waiting.
     *
     * @param milis
     */
    protected void waiting(int milis) {
        try {
            Thread.sleep(milis);
        } catch (InterruptedException ignored) {
        }
    }

    private enum Tag {

        input("input"), radio("table"), checkbox("table"), select("select"), unknown("");
        private final String tagname;
        private List<WebElement> radioElements;
        private List<WebElement> checkboxElements;
        private Select selection;

        Tag(String tagname) {
            this.tagname = tagname;
        }

        public static Tag getTag(WebElement foundElement) {
            String elementTag = foundElement.getTagName();
            for (Tag t : values()) {
                if (t.tagname.equals(elementTag)) {
                    if (t.equals(radio) || t.equals(checkbox)) {
                        List<WebElement> foundElements = WebElementProxyUtils
                                .createProxyForElements(By.tagName("input"), foundElement);
                        String inputType = foundElements.get(0).getAttribute("type");
                        if ("radio".equals(inputType)) {
                            radio.radioElements = foundElements;
                            return radio;
                        } else if ("checkbox".equals(inputType)) { //not supported
                            checkbox.checkboxElements = foundElements;
                            return checkbox;
                        }
                        return t;
                    } else if (t.equals(select)) {
                        select.selection = new Select(foundElement);
                        return select;
                    } else {
                        return t;
                    }
                }
            }
            return unknown;
        }
    }
}