/* 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.fonemonkey.web; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.webkit.WebView; import com.gorillalogic.fonemonkey.automators.AutomationManager; import com.gorillalogic.fonemonkey.automators.WebViewAutomator; public abstract class WebFilterBase implements IWebFilter { public static String[] webProperties = { "@id", "@name", "@value", "text()", "@title", "@class", "@alt", "@src", "@href" }; private static Pattern ordPattern = Pattern.compile("#\\d+"); @Override public HtmlElement findHtmlElement(WebView webview, String componentType, String monkeyId) { Pattern monkeyIndexPattern = Pattern.compile("\\([0-9]+(?:\\.[0-9]*)?\\)$"); Matcher monkeyIndexMatcher = monkeyIndexPattern.matcher(monkeyId); Pattern xpathPattern = Pattern.compile("^xpath="); WebViewAutomator auto = (WebViewAutomator) AutomationManager.findAutomator(webview); String xpath = xpathPattern.matcher(monkeyId).find() ? monkeyId.replace("xpath=", "") : getXpathExpression(monkeyId); HtmlElement elem = null; boolean isOrdinalMonkeyId = ordPattern.matcher(monkeyId).matches() || monkeyId.equalsIgnoreCase("*"); boolean isIndexedMonkeyId = monkeyIndexMatcher.find(); if (isOrdinalMonkeyId || isIndexedMonkeyId) { int n = 1; if (!monkeyId.equalsIgnoreCase("*") && !isIndexedMonkeyId) { n = Integer.valueOf(monkeyId.substring(1)); } else if (isIndexedMonkeyId) { String monkeyIndex = monkeyIndexMatcher.group(); String baseMonkeyId = monkeyId.replace(monkeyIndex, ""); xpath = xpath.replace(monkeyId, baseMonkeyId); monkeyId = baseMonkeyId; monkeyIndex = monkeyIndex.replace("(", ""); monkeyIndex = monkeyIndex.replace(")", ""); n = Integer.parseInt(monkeyIndex); } elem = auto.findElementByXpath(n, xpath); } else { elem = auto.findElementByXpath(xpath); } return elem; } @Override public HtmlElement findNthHtmlElement(WebView webview, String componentType, int n) { String xpath = this.getXpathNode(); WebViewAutomator auto = (WebViewAutomator) AutomationManager.findAutomator(webview); HtmlElement elem = auto.findElementByXpath(n, xpath); return elem; } public List<HtmlElement> findAll(WebView webview) { List<HtmlElement> results = new ArrayList<HtmlElement>(); for (String tagName : getTagNames()) { List<HtmlElement> elems = WebAutomationManager.findHtmlElements(webview, "document.getElementsByTagName(\'" + tagName + "')"); results.addAll(elems); } return results; } @Override public String getXpathExpression(String monkeyId) { String node = this.getXpathNode(); String predicate; String xpath; if (ordPattern.matcher(monkeyId).matches() || monkeyId.equalsIgnoreCase("*")) { predicate = ""; } else { predicate = this.getXpathPredicate(monkeyId); } xpath = node + predicate; return xpath; } @Override public String getXpathNode() { String node = ""; boolean isCompoundNode = getTagNames().length > 1; if (isCompoundNode) { node += "("; } for (int i = 0; i < getTagNames().length; i++) { String tag = getTagNames()[i]; node += "//" + tag; if (i + 1 < getTagNames().length) { node += "|"; } } if (isCompoundNode) { node += ")"; } return node; } @Override public String getXpathPredicate(String monkeyId) { String predicate = "["; for (int i = 0; i < webProperties.length; i++) { String property = webProperties[i]; predicate += property + "='" + monkeyId + "'"; if (i + 1 < webProperties.length) { predicate += " or "; } } predicate += "]"; return predicate; } public boolean isIncluded(HtmlElement elem, String monkeyId) { boolean b = defaultIsIncluded(elem, monkeyId); return b; } protected boolean defaultIsIncluded(HtmlElement elem, String monkeyId) { return elem.matches(monkeyId); } protected abstract String[] getTagNames(); }