mirror of
https://github.com/appium/appium.git
synced 2026-05-05 09:59:58 -05:00
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user