aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKevin Jin <kjin@google.com>2014-10-30 14:01:48 -0700
committerKevin Jin <kjin@google.com>2014-10-30 14:13:22 -0700
commitb8c4f2e950ab8132196dd644d7cfc892f75a8441 (patch)
tree9435e30187a45f8ef52594c191435a368f475040 /src
parentecd187a1c7c94101abc997a188f8d385938db2e0 (diff)
downloaddroiddriver-b8c4f2e950ab8132196dd644d7cfc892f75a8441.tar.gz
fix setText and remove replaceText
setText was a misleading method because it did not clear existing text, which was implied by the name. This change first puts the UiElement in focus, then clears existing text, finally sets the new text. This change is not backward compatible in many cases, so please modify your client code then we can coordinate to submit at the same time. Change-Id: I3a959301734db9075a768b1d63019af8320dc89b
Diffstat (limited to 'src')
-rw-r--r--src/com/google/android/droiddriver/UiElement.java18
-rw-r--r--src/com/google/android/droiddriver/actions/EventUiElementActor.java5
-rw-r--r--src/com/google/android/droiddriver/actions/SingleKeyAction.java34
-rw-r--r--src/com/google/android/droiddriver/actions/UiElementActor.java7
-rw-r--r--src/com/google/android/droiddriver/actions/accessibility/AccessibilityUiElementActor.java6
-rw-r--r--src/com/google/android/droiddriver/base/BaseUiDevice.java6
-rw-r--r--src/com/google/android/droiddriver/base/BaseUiElement.java35
-rw-r--r--src/com/google/android/droiddriver/util/Events.java32
8 files changed, 87 insertions, 56 deletions
diff --git a/src/com/google/android/droiddriver/UiElement.java b/src/com/google/android/droiddriver/UiElement.java
index 72804d8..f53c22a 100644
--- a/src/com/google/android/droiddriver/UiElement.java
+++ b/src/com/google/android/droiddriver/UiElement.java
@@ -145,20 +145,22 @@ public interface UiElement {
boolean perform(Action action);
/**
- * Sets the text of this element.
+ * Sets the text of this element. The implementation may not work on all
+ * UiElements if the underlying view is not EditText.
+ * <p>
+ * If IME is open after this call, you can call
+ *
+ * <pre>
+ * perform(SingleKeyAction.BACK);
+ * </pre>
+ *
+ * to close the IME.
*
* @param text The text to enter.
*/
void setText(String text);
/**
- * Replace the text of this element.
- *
- * @param text The text that be replaced with
- */
- void replaceText(String text);
-
- /**
* Clicks this element. The click will be at the center of the visible
* element.
*/
diff --git a/src/com/google/android/droiddriver/actions/EventUiElementActor.java b/src/com/google/android/droiddriver/actions/EventUiElementActor.java
index 1913e5d..a5414a9 100644
--- a/src/com/google/android/droiddriver/actions/EventUiElementActor.java
+++ b/src/com/google/android/droiddriver/actions/EventUiElementActor.java
@@ -27,11 +27,6 @@ public class EventUiElementActor implements UiElementActor {
public static final EventUiElementActor INSTANCE = new EventUiElementActor();
@Override
- public void setText(UiElement uiElement, String text) {
- uiElement.perform(new TextAction(text));
- }
-
- @Override
public void click(UiElement uiElement) {
uiElement.perform(ClickAction.SINGLE);
}
diff --git a/src/com/google/android/droiddriver/actions/SingleKeyAction.java b/src/com/google/android/droiddriver/actions/SingleKeyAction.java
index 853840e..3f5fe15 100644
--- a/src/com/google/android/droiddriver/actions/SingleKeyAction.java
+++ b/src/com/google/android/droiddriver/actions/SingleKeyAction.java
@@ -17,12 +17,12 @@
package com.google.android.droiddriver.actions;
import android.os.Build;
-import android.os.SystemClock;
import android.view.KeyEvent;
import com.google.android.droiddriver.UiElement;
import com.google.android.droiddriver.util.Events;
import com.google.android.droiddriver.util.Strings;
+import com.google.android.droiddriver.util.Strings.ToStringHelper;
/**
* An action to press a single key. While it is convenient for navigating the
@@ -39,30 +39,42 @@ public class SingleKeyAction extends KeyAction {
public static final SingleKeyAction SEARCH = new SingleKeyAction(KeyEvent.KEYCODE_SEARCH);
public static final SingleKeyAction BACK = new SingleKeyAction(KeyEvent.KEYCODE_BACK);
public static final SingleKeyAction DELETE = new SingleKeyAction(KeyEvent.KEYCODE_DEL);
+ public static final SingleKeyAction CTRL_MOVE_HOME = new SingleKeyAction(
+ KeyEvent.KEYCODE_MOVE_HOME, KeyEvent.META_CTRL_LEFT_ON);
+ public static final SingleKeyAction CTRL_MOVE_END = new SingleKeyAction(
+ KeyEvent.KEYCODE_MOVE_END, KeyEvent.META_CTRL_LEFT_ON);
private final int keyCode;
+ private final int metaState;
/**
- * Defaults timeoutMillis to 100.
+ * Defaults metaState to 0.
*/
public SingleKeyAction(int keyCode) {
- this(keyCode, 100L, false);
+ this(keyCode, 0);
}
- public SingleKeyAction(int keyCode, long timeoutMillis, boolean checkFocused) {
+ /**
+ * Defaults timeoutMillis to 100 and checkFocused to false.
+ */
+ public SingleKeyAction(int keyCode, int metaState) {
+ this(keyCode, metaState, 100L, false);
+ }
+
+ public SingleKeyAction(int keyCode, int metaState, long timeoutMillis, boolean checkFocused) {
super(timeoutMillis, checkFocused);
this.keyCode = keyCode;
+ this.metaState = metaState;
}
@Override
public boolean perform(InputInjector injector, UiElement element) {
maybeCheckFocused(element);
- final long downTime = SystemClock.uptimeMillis();
- KeyEvent downEvent = Events.newKeyEvent(downTime, KeyEvent.ACTION_DOWN, keyCode);
- KeyEvent upEvent = Events.newKeyEvent(downTime, KeyEvent.ACTION_UP, keyCode);
+ final long downTime = Events.keyDown(injector, keyCode, metaState);
+ Events.keyUp(injector, downTime, keyCode, metaState);
- return injector.injectInputEvent(downEvent) && injector.injectInputEvent(upEvent);
+ return true;
}
@Override
@@ -70,6 +82,10 @@ public class SingleKeyAction extends KeyAction {
String keyCodeString =
Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1 ? String.valueOf(keyCode)
: KeyEvent.keyCodeToString(keyCode);
- return Strings.toStringHelper(this).addValue(keyCodeString).toString();
+ ToStringHelper toStringHelper = Strings.toStringHelper(this);
+ if (metaState != 0) {
+ toStringHelper.add("metaState", metaState);
+ }
+ return toStringHelper.addValue(keyCodeString).toString();
}
}
diff --git a/src/com/google/android/droiddriver/actions/UiElementActor.java b/src/com/google/android/droiddriver/actions/UiElementActor.java
index abca286..80c97f4 100644
--- a/src/com/google/android/droiddriver/actions/UiElementActor.java
+++ b/src/com/google/android/droiddriver/actions/UiElementActor.java
@@ -24,13 +24,6 @@ import com.google.android.droiddriver.scroll.Direction.PhysicalDirection;
*/
public interface UiElementActor {
/**
- * Sets the text of this element.
- *
- * @param text The text to enter.
- */
- void setText(UiElement uiElement, String text);
-
- /**
* Clicks this element. The click will be at the center of the visible
* element.
*/
diff --git a/src/com/google/android/droiddriver/actions/accessibility/AccessibilityUiElementActor.java b/src/com/google/android/droiddriver/actions/accessibility/AccessibilityUiElementActor.java
index dec5979..afb91f1 100644
--- a/src/com/google/android/droiddriver/actions/accessibility/AccessibilityUiElementActor.java
+++ b/src/com/google/android/droiddriver/actions/accessibility/AccessibilityUiElementActor.java
@@ -17,7 +17,6 @@
package com.google.android.droiddriver.actions.accessibility;
import com.google.android.droiddriver.UiElement;
-import com.google.android.droiddriver.actions.TextAction;
import com.google.android.droiddriver.actions.UiElementActor;
import com.google.android.droiddriver.scroll.Direction.PhysicalDirection;
@@ -28,11 +27,6 @@ public class AccessibilityUiElementActor implements UiElementActor {
public static final AccessibilityUiElementActor INSTANCE = new AccessibilityUiElementActor();
@Override
- public void setText(UiElement uiElement, String text) {
- uiElement.perform(new TextAction(text));
- }
-
- @Override
public void click(UiElement uiElement) {
uiElement.perform(AccessibilityClickAction.SINGLE);
}
diff --git a/src/com/google/android/droiddriver/base/BaseUiDevice.java b/src/com/google/android/droiddriver/base/BaseUiDevice.java
index a48e410..d7c5afa 100644
--- a/src/com/google/android/droiddriver/base/BaseUiDevice.java
+++ b/src/com/google/android/droiddriver/base/BaseUiDevice.java
@@ -36,11 +36,11 @@ import java.io.BufferedOutputStream;
*/
public abstract class BaseUiDevice implements UiDevice {
// power off may not trigger new events
- private static final SingleKeyAction POWER_OFF = new SingleKeyAction(KeyEvent.KEYCODE_POWER, 0,
- false);
+ private static final SingleKeyAction POWER_OFF = new SingleKeyAction(KeyEvent.KEYCODE_POWER,
+ 0/* metaState */, 0/* timeoutMillis */, false);
// power on should always trigger new events
private static final SingleKeyAction POWER_ON = new SingleKeyAction(KeyEvent.KEYCODE_POWER,
- 1000L, false);
+ 0/* metaState */, 1000L/* timeoutMillis */, false);
@Override
public boolean isScreenOn() {
diff --git a/src/com/google/android/droiddriver/base/BaseUiElement.java b/src/com/google/android/droiddriver/base/BaseUiElement.java
index ef4038f..2c996f4 100644
--- a/src/com/google/android/droiddriver/base/BaseUiElement.java
+++ b/src/com/google/android/droiddriver/base/BaseUiElement.java
@@ -17,17 +17,21 @@
package com.google.android.droiddriver.base;
import android.graphics.Rect;
+import android.view.KeyEvent;
import com.google.android.droiddriver.UiElement;
import com.google.android.droiddriver.actions.Action;
import com.google.android.droiddriver.actions.EventUiElementActor;
+import com.google.android.droiddriver.actions.InputInjector;
import com.google.android.droiddriver.actions.SingleKeyAction;
+import com.google.android.droiddriver.actions.TextAction;
import com.google.android.droiddriver.actions.UiElementActor;
import com.google.android.droiddriver.exceptions.DroidDriverException;
import com.google.android.droiddriver.finders.Attribute;
import com.google.android.droiddriver.finders.Predicate;
import com.google.android.droiddriver.finders.Predicates;
import com.google.android.droiddriver.scroll.Direction.PhysicalDirection;
+import com.google.android.droiddriver.util.Events;
import com.google.android.droiddriver.util.Logs;
import com.google.android.droiddriver.util.Strings;
import com.google.android.droiddriver.util.Strings.ToStringHelper;
@@ -208,18 +212,29 @@ public abstract class BaseUiElement<R, E extends BaseUiElement<R, E>> implements
@Override
public void setText(String text) {
- uiElementActor.setText(this, text);
+ Logs.call(this, "setText", text);
+ clearText();
+ if (text == null || text.isEmpty()) {
+ return;
+ }
+
+ perform(new TextAction(text));
}
- @Override
- public void replaceText(String text) {
- if (this.getText() != null) {
- int len = this.getText().length();
- for (int i = 0; i < len; i++) {
- this.perform(SingleKeyAction.DELETE);
- }
- }
- this.setText(text);
+ private void clearText() {
+ longClick(); // Gain focus; single click always activates IME.
+ String text = getText();
+ if (text == null || text.isEmpty()) {
+ return;
+ }
+
+ InputInjector injector = getInjector();
+ SingleKeyAction.CTRL_MOVE_HOME.perform(injector, this);
+
+ final long shiftDownTime = Events.keyDown(injector, KeyEvent.KEYCODE_SHIFT_LEFT, 0);
+ SingleKeyAction.CTRL_MOVE_END.perform(injector, this);
+ Events.keyUp(injector, shiftDownTime, KeyEvent.KEYCODE_SHIFT_LEFT, 0);
+ SingleKeyAction.DELETE.perform(injector, this);
}
@Override
diff --git a/src/com/google/android/droiddriver/util/Events.java b/src/com/google/android/droiddriver/util/Events.java
index cc43ec2..a905851 100644
--- a/src/com/google/android/droiddriver/util/Events.java
+++ b/src/com/google/android/droiddriver/util/Events.java
@@ -19,6 +19,7 @@ package com.google.android.droiddriver.util;
import android.os.SystemClock;
import android.util.Log;
import android.view.InputDevice;
+import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -32,7 +33,7 @@ public class Events {
/**
* @return a touch down event at the specified coordinates
*/
- public static MotionEvent newTouchDownEvent(int x, int y) {
+ private static MotionEvent newTouchDownEvent(int x, int y) {
long downTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, x, y, 1);
event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
@@ -42,7 +43,7 @@ public class Events {
/**
* @return a touch up event at the specified coordinates
*/
- public static MotionEvent newTouchUpEvent(long downTime, int x, int y) {
+ private static MotionEvent newTouchUpEvent(long downTime, int x, int y) {
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 1);
event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
@@ -52,15 +53,16 @@ public class Events {
/**
* @return a touch move event at the specified coordinates
*/
- public static MotionEvent newTouchMoveEvent(long downTime, int x, int y) {
+ private static MotionEvent newTouchMoveEvent(long downTime, int x, int y) {
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 1);
event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
return event;
}
- public static KeyEvent newKeyEvent(long downTime, int action, int keyCode) {
- KeyEvent event = new KeyEvent(downTime, downTime, action, keyCode, 0 /* repeat */);
+ private static KeyEvent newKeyEvent(long downTime, long eventTime, int action, int keyCode,
+ int metaState) {
+ KeyEvent event = new KeyEvent(downTime, eventTime, action, keyCode, 0 /* repeat */, metaState);
event.setSource(InputDevice.SOURCE_KEYBOARD);
return event;
}
@@ -71,18 +73,20 @@ public class Events {
*
* @throws ActionException if injection failed
*/
- public static void injectEvent(InputInjector injector, MotionEvent event) {
+ private static void injectEvent(InputInjector injector, InputEvent event) {
injectEvent(Log.DEBUG, injector, event);
}
- public static void injectEvent(int priority, InputInjector injector, MotionEvent event) {
+ private static void injectEvent(int priority, InputInjector injector, InputEvent event) {
Logs.call(priority, injector, "injectInputEvent", event);
try {
if (!injector.injectInputEvent(event)) {
throw new ActionException("Failed to inject " + event);
}
} finally {
- event.recycle();
+ if (event instanceof MotionEvent) {
+ ((MotionEvent) event).recycle();
+ }
}
}
@@ -101,5 +105,17 @@ public class Events {
injectEvent(Log.VERBOSE, injector, newTouchMoveEvent(downTime, x, y));
}
+ public static long keyDown(InputInjector injector, int keyCode, int metaState) {
+ long downTime = SystemClock.uptimeMillis();
+ KeyEvent downEvent = newKeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, metaState);
+ injectEvent(injector, downEvent);
+ return downTime;
+ }
+
+ public static void keyUp(InputInjector injector, long downTime, int keyCode, int metaState) {
+ injectEvent(injector,
+ newKeyEvent(downTime, SystemClock.uptimeMillis(), KeyEvent.ACTION_UP, keyCode, metaState));
+ }
+
private Events() {}
}