com.gorillalogic.agents.html.automators.WebElementAutomator.java Source code

Java tutorial

Introduction

Here is the source code for com.gorillalogic.agents.html.automators.WebElementAutomator.java

Source

/*  MonkeyTalk - a cross-platform functional testing tool
Copyright (C) 2012 Gorilla Logic, Inc.
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
    
You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>. */

package com.gorillalogic.agents.html.automators;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import com.gorillalogic.monkeytalk.Command;
import com.gorillalogic.monkeytalk.automators.AutomatorConstants;

public class WebElementAutomator extends AutomatorBase {
    public static String componentType = "HtmlTag";
    public static String[] aliases = { "View" };

    private WebElement element = null;

    @Override
    public String getComponentType() {
        return componentType;
    }

    @Override
    public void init(WebDriver driver, String monkeyId) {
        super.init(driver, monkeyId);
    }

    public WebElement getElement() {
        if (element != null) {
            return element;
        }

        String xpath = getLocatorExpr();
        try {
            List<WebElement> elements = driver.findElements(By.xpath(xpath));
            if (elements.size() == 0) {
                throw new IllegalArgumentException(
                        "Unable to find html element with monkeyID '" + this.monkeyId + "'");
            }
            int monkeyIndex = 0;

            if (getMonkeyOrdinal() != null) {
                String monkeyOrdinal = getMonkeyOrdinal().get(1);
                monkeyIndex = Integer.parseInt(monkeyOrdinal) - 1;

                if (Integer.parseInt(monkeyOrdinal) > elements.size())
                    throw new IllegalArgumentException(
                            "Unable to find html element with monkeyID '" + this.monkeyId + "'");
            }

            driver.switchTo().defaultContent();
            element = elements.get(monkeyIndex);
        } catch (NoSuchElementException e1) {
            // OK
        }
        if (element != null) {
            return element;
        }

        List<WebElement> frameset = driver.findElements(By.tagName("iframe"));
        for (WebElement framename : frameset) {
            try {
                List<WebElement> elements = driver.findElements(By.xpath(xpath));
                int monkeyIndex = 0;

                if (getMonkeyOrdinal() != null) {
                    String monkeyOrdinal = getMonkeyOrdinal().get(1);
                    monkeyIndex = Integer.parseInt(monkeyOrdinal) - 1;

                    if (Integer.parseInt(monkeyOrdinal) > elements.size())
                        throw new IllegalArgumentException(
                                "Unable to find button with monkeyID '" + this.monkeyId + "'");
                }

                driver.switchTo().defaultContent();
                driver.switchTo().frame(framename);
                element = elements.get(monkeyIndex);
                break;
            } catch (NoSuchElementException e) {

            }
        }
        if (element == null) {
            throw new IllegalArgumentException(
                    "Unable to find " + getComponentType() + " with monkeyId '" + monkeyId + "'");
        }
        return element;
    }

    public String getElementExpr() {
        return "//*";
    }

    public String getOrdinal() {
        String firstChar = this.monkeyId.substring(0, 1);

        if (firstChar.equals("#"))
            return this.monkeyId.substring(1);
        else if (this.monkeyId.equals("*"))
            return "1";

        return null;
    }

    public ArrayList<String> getMonkeyOrdinal() {
        Pattern pattern = Pattern.compile("\\(\\d+\\)$");
        //      String firstChar = this.monkeyId.substring(0, 1);

        Matcher matcher = pattern.matcher(this.monkeyId);

        if (matcher.find()) {
            String ordinal = matcher.group().replace("(", "");
            ordinal = ordinal.replace(")", "");

            //         this.monkeyId = this.monkeyId.substring(0, matcher.start());

            ArrayList<String> ordinalMID = new ArrayList<String>();

            ordinalMID.add(this.monkeyId.substring(0, matcher.start()));
            ordinalMID.add(ordinal);

            return ordinalMID;
        }

        return null;
    }

    /**
     * "where" part of xpath expr (without []'s)
     * 
     * @param monkeyId
     * @return
     */
    public String getWhereExpr(String monkeyId) {
        String eqId = " = '" + monkeyId + "'";
        // The "." in the expession below matches the textContent of the node. 
        // For some (perhaps never TBD) reason, @textContent doesn't match 
        // when nodes contain tags, for example <a>this is <b>it</b></a>
        // . == 'this is it' matches but @textContent='this is it' doesn't
        // even though element.textContent will return 'this is it'.
        return "@id" + eqId + " or @name" + eqId + " or @value" + eqId + " or . " + eqId + " or @title" + eqId
                + " or @styleClass" + eqId;
    }

    @Override
    public String play(Command command) {
        String action = command.getAction();
        if (isTapAction(action)) {
            tap();
            return null;
        }

        if (isEnterTextAction(action)) {
            enterText(command);
            return null;
        }

        return super.play(command);
    }

    protected void clear(Command command) {
        getElement().clear();
    }

    protected void enterText(Command command) {

        getElement().sendKeys(getArg(command, 0));
        if ("enter".equals(getOptArg(command, 1))) {
            getElement().sendKeys("\n");
        }

    }

    private boolean isEnterTextAction(String action) {
        return action.equalsIgnoreCase(AutomatorConstants.ACTION_ENTER_TEXT);
    }

    /**
     * Override to customize tap
     */
    protected void tap() {
        getElement().click();

        //new WebDriverBackedSelenium(driver, driver.getCurrentUrl()).clickAt(getLocatorExpr(),"0,0");

    }

    /**
     * Override to customize what actions are taps
     */
    private final static String[] taps = { AutomatorConstants.ACTION_TAP, AutomatorConstants.ACTION_CLICK };

    protected boolean isTapAction(String action) {
        for (String s : taps) {
            if (action.equalsIgnoreCase(s)) {
                return true;
            }
        }
        return false;
    }

    protected String getLocatorExpr() {
        String where = getWhereExpr(this.monkeyId);
        String base = getElementExpr();

        if (getMonkeyOrdinal() != null) {
            String strippedId = getMonkeyOrdinal().get(0);

            where = getWhereExpr(strippedId);
        } else if (getOrdinal() != null) {
            where = getOrdinal();
            base = "(" + base + ")";
        }

        return base + "[" + where + "]";
    }

    @Override
    protected void assertExists() {
        getElement();
    }

    @Override
    protected String getProperty(String prop) {
        String value = getElement().getAttribute(prop);
        return value == null ? super.getProperty(prop) : value;
    }

    @Override
    protected Rect getBoundingRectangle() {
        Dimension dim = getElement().getSize();
        Point p = getElement().getLocation();
        return new Rect(p.x, p.y, dim.height, dim.width);
    }
}