mobile: find

Fix #387
This commit is contained in:
bootstraponline
2013-04-08 15:59:46 -04:00
parent e203f0a98e
commit 73b169ce69
8 changed files with 223 additions and 5 deletions
+8
View File
@@ -316,6 +316,13 @@ exports.mobileSource = function(req, res) {
}
};
exports.find = function(req, res) {
var strategy = "dynamic"
, selector = req.body;
req.device.findElements(strategy, selector, getResponseHandler(req, res));
};
exports.mobileSwipe = function(req, res) {
var onElement = typeof req.body.element !== "undefined";
req.body = _.defaults(req.body, {
@@ -757,6 +764,7 @@ var mobileCmdMap = {
, 'leaveWebView': exports.leaveWebView
, 'fireEvent': exports.fireEvent
, 'source': exports.mobileSource
, 'find': exports.find
};
exports.produceError = function(req, res) {
+25
View File
@@ -9,6 +9,31 @@ var path = require('path')
"android", appPkg, appAct)
, should = require('should');
describeWd('mobile find', function(h) {
it('should find a single element by content-description', function(done) {
h.driver.execute("mobile: find", [ [[7, "Animation"]] ], function(err, el) {
should.not.exist(err);
should.exist(el);
el.text(function(err, text) {
should.not.exist(err);
text.should.eql("Animation");
done();
});
});
});
it('should find a single element by text', function(done) {
h.driver.execute("mobile: find", [ [[3, "Animation"]] ], function(err, el) {
should.not.exist(err);
should.exist(el);
el.text(function(err, text) {
should.not.exist(err);
text.should.eql("Animation");
done();
});
});
});
});
describeWd('find element(s)', function(h) {
it('should find a single element by content-description', function(done) {
h.driver.elementByName("Animation", function(err, el) {
+6
View File
@@ -10,8 +10,14 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -1,14 +1,15 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
@@ -0,0 +1,151 @@
package io.appium.android.bootstrap;
import org.json.JSONArray;
import org.json.JSONException;
import com.android.uiautomator.core.UiSelector;
// Constants from
// https://android.googlesource.com/platform/frameworks/testing/+/master/uiautomator/library/src/com/android/uiautomator/core/UiSelector.java
public class Dynamic {
// static final int SELECTOR_NIL = 0; // nothing.
/** text(String text) */
private static final int SELECTOR_TEXT = 1;
/** textStartsWith(String text) */
private static final int SELECTOR_START_TEXT = 2;
/** textContains(String text) */
private static final int SELECTOR_CONTAINS_TEXT = 3;
/** className(String className), className(Class<T> type) */
private static final int SELECTOR_CLASS = 4;
/** description(String desc) */
private static final int SELECTOR_DESCRIPTION = 5;
/** descriptionStartsWith(String desc) */
private static final int SELECTOR_START_DESCRIPTION = 6;
/** descriptionContains(String desc) */
private static final int SELECTOR_CONTAINS_DESCRIPTION = 7;
/** index(final int index) */
private static final int SELECTOR_INDEX = 8;
/** instance(final int instance) */
private static final int SELECTOR_INSTANCE = 9;
/** enabled(boolean val) */
private static final int SELECTOR_ENABLED = 10;
/** focused(boolean val) */
private static final int SELECTOR_FOCUSED = 11;
/** focusable(boolean val) */
private static final int SELECTOR_FOCUSABLE = 12;
/** scrollable(boolean val) */
private static final int SELECTOR_SCROLLABLE = 13;
/** clickable(boolean val) */
private static final int SELECTOR_CLICKABLE = 14;
/** checked(boolean val) */
private static final int SELECTOR_CHECKED = 15;
/** selected(boolean val) */
private static final int SELECTOR_SELECTED = 16;
// static final int SELECTOR_ID = 17; // nothing.
/** packageName(String name) */
private static final int SELECTOR_PACKAGE_NAME = 18;
// @formatter:off
// private static final int SELECTOR_CHILD = 19; // childSelector(UiSelector selector)
// private static final int SELECTOR_CONTAINER = 20; // containerSelector(UiSelector selector)
// private static final int SELECTOR_PATTERN = 21; // ! private ! patternSelector(UiSelector selector)
// private static final int SELECTOR_PARENT = 22; // fromParent(UiSelector selector)
// private static final int SELECTOR_COUNT = 23; // nothing.
// @formatter:on
/** longClickable(boolean val) */
private static final int SELECTOR_LONG_CLICKABLE = 24;
/** textMatches(String regex) */
private static final int SELECTOR_TEXT_REGEX = 25;
/** classNameMatches(String regex) */
private static final int SELECTOR_CLASS_REGEX = 26;
/** descriptionMatches(String regex) */
private static final int SELECTOR_DESCRIPTION_REGEX = 27;
/** packageNameMatches(String regex) */
private static final int SELECTOR_PACKAGE_NAME_REGEX = 28;
private UiSelector s = new UiSelector();
public UiSelector get(final JSONArray array) throws JSONException {
// Reset selector.
s = new UiSelector();
// Example pair.
// Find everything containing the text sign.
// [ [3, 'sign'] ]
for (int a = 0; a < array.length(); a++) {
final JSONArray pair = array.getJSONArray(a);
update(pair.getInt(0), pair.get(1));
}
return s;
}
private void update(final int method, final Object param) {
switch (method) {
case SELECTOR_TEXT:
s = s.text((String) param);
break;
case SELECTOR_START_TEXT:
s = s.textStartsWith((String) param);
break;
case SELECTOR_CONTAINS_TEXT:
s = s.textContains((String) param);
break;
case SELECTOR_CLASS:
s = s.className((String) param);
break;
case SELECTOR_DESCRIPTION:
s = s.description((String) param);
break;
case SELECTOR_START_DESCRIPTION:
s = s.descriptionStartsWith((String) param);
break;
case SELECTOR_CONTAINS_DESCRIPTION:
s = s.descriptionContains((String) param);
break;
case SELECTOR_INDEX:
s = s.index((Integer) param);
break;
case SELECTOR_INSTANCE:
s = s.instance((Integer) param);
break;
case SELECTOR_ENABLED:
s = s.enabled((Boolean) param);
break;
case SELECTOR_FOCUSED:
s = s.focused((Boolean) param);
break;
case SELECTOR_FOCUSABLE:
s = s.focusable((Boolean) param);
break;
case SELECTOR_SCROLLABLE:
s = s.scrollable((Boolean) param);
break;
case SELECTOR_CLICKABLE:
s = s.clickable((Boolean) param);
break;
case SELECTOR_CHECKED:
s = s.checked((Boolean) param);
break;
case SELECTOR_SELECTED:
s = s.selected((Boolean) param);
break;
case SELECTOR_PACKAGE_NAME:
s = s.packageName((String) param);
break;
case SELECTOR_LONG_CLICKABLE:
s = s.longClickable((Boolean) param);
break;
case SELECTOR_TEXT_REGEX:
s = s.textMatches((String) param);
break;
case SELECTOR_CLASS_REGEX:
s = s.classNameMatches((String) param);
break;
case SELECTOR_DESCRIPTION_REGEX:
s = s.descriptionMatches((String) param);
break;
case SELECTOR_PACKAGE_NAME_REGEX:
s = s.packageNameMatches((String) param);
break;
}
}
}
@@ -6,6 +6,7 @@ import io.appium.android.bootstrap.AndroidElement;
import io.appium.android.bootstrap.AndroidElementClassMap;
import io.appium.android.bootstrap.AndroidElementsHash;
import io.appium.android.bootstrap.CommandHandler;
import io.appium.android.bootstrap.Dynamic;
import io.appium.android.bootstrap.Logger;
import io.appium.android.bootstrap.WDStatus;
import io.appium.android.bootstrap.exceptions.AndroidCommandException;
@@ -36,6 +37,7 @@ import com.android.uiautomator.core.UiSelector;
*/
public class Find extends CommandHandler {
AndroidElementsHash elements = AndroidElementsHash.getInstance();
Dynamic dynamic = new Dynamic();
/*
* @param command The {@link AndroidCommand} used for this handler.
@@ -55,9 +57,29 @@ public class Find extends CommandHandler {
// only makes sense on a device
final Strategy strategy = Strategy.fromString((String) params
.get("strategy"));
final String text = (String) params.get("selector");
final String contextId = (String) params.get("context");
if (strategy == Strategy.DYNAMIC) {
Logger.debug("Finding dynamic.");
final JSONArray selectors = (JSONArray) params.get("selector");
final JSONArray results = new JSONArray();
try {
for (int selIndex = 0; selIndex < selectors.length(); selIndex++) {
final UiSelector sel = dynamic.get((JSONArray) selectors.get(selIndex));
final JSONArray tmp = fetchElements(sel, contextId);
for (int tmpIndex = 0; tmpIndex < tmp.length(); tmpIndex++) {
results.put(tmp.get(tmpIndex));
}
}
return getSuccessResult(results);
} catch (final Exception e) {
return getErrorResult(e.getMessage());
}
}
final String text = (String) params.get("selector");
Logger.debug("Finding " + text + " using " + strategy.toString()
+ " with the contextId: " + contextId);
@@ -9,7 +9,8 @@ package io.appium.android.bootstrap.selector;
public enum Strategy {
CLASS_NAME(0, "class name"), CSS_SELECTOR(1, "css selector"), ID(2, "id"), NAME(
3, "name"), LINK_TEXT(4, "link text"), PARTIAL_LINK_TEXT(5,
"partial link text"), TAG_NAME(6, "tag name"), XPATH(7, "xpath");
"partial link text"), TAG_NAME(6, "tag name"), XPATH(7, "xpath"), DYNAMIC(
8, "dynamic");
public static Strategy fromString(final String text) {
if (text != null) {