summaryrefslogtreecommitdiff
path: root/base/test/android/javatests/src/org/chromium/base
diff options
context:
space:
mode:
Diffstat (limited to 'base/test/android/javatests/src/org/chromium/base')
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/transit/Elements.java4
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/transit/ViewConditions.java50
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/transit/ViewElement.java95
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/transit/ViewElementInState.java11
4 files changed, 123 insertions, 37 deletions
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/Elements.java b/base/test/android/javatests/src/org/chromium/base/test/transit/Elements.java
index 72249ca960..3286462525 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/Elements.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/Elements.java
@@ -18,10 +18,6 @@ import java.util.List;
* </pre>
*/
public class Elements {
-
- /** If passed as |id|, the description is considered the id. */
- public static final String DESCRIPTION_AS_ID = "__DESCRIPTION_AS_ID";
-
static final Elements EMPTY = new Elements();
private ArrayList<ElementInState> mElementsInState = new ArrayList<>();
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewConditions.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewConditions.java
index ac9f53c1c6..2cf5a801d3 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewConditions.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewConditions.java
@@ -32,8 +32,8 @@ import java.util.regex.Pattern;
public class ViewConditions {
/** Fulfilled when a single matching View exists and is displayed. */
public static class DisplayedCondition extends ExistsCondition {
- public DisplayedCondition(Matcher<View> matcher) {
- super(allOf(matcher, isDisplayed()));
+ public DisplayedCondition(Matcher<View> matcher, ExistsCondition.Options options) {
+ super(allOf(matcher, isDisplayed()), options);
}
}
@@ -46,9 +46,10 @@ public class ViewConditions {
private final DisplayedCondition mDisplayedCondition;
private final Condition mGate;
- public GatedDisplayedCondition(Matcher<View> matcher, Condition gate) {
+ public GatedDisplayedCondition(
+ Matcher<View> matcher, Condition gate, ExistsCondition.Options options) {
super();
- mDisplayedCondition = new DisplayedCondition(matcher);
+ mDisplayedCondition = new DisplayedCondition(matcher, options);
mGate = gate;
}
@@ -75,11 +76,13 @@ public class ViewConditions {
/** Fulfilled when a single matching View exists. */
public static class ExistsCondition extends InstrumentationThreadCondition {
private final Matcher<View> mMatcher;
+ private final Options mOptions;
private View mViewMatched;
- public ExistsCondition(Matcher<View> matcher) {
+ public ExistsCondition(Matcher<View> matcher, Options options) {
super();
- this.mMatcher = matcher;
+ mMatcher = matcher;
+ mOptions = options;
}
@Override
@@ -115,6 +118,15 @@ public class ViewConditions {
mViewMatched = view;
}
});
+ if (mOptions.mExpectEnabled) {
+ if (!mViewMatched.isEnabled()) {
+ return notFulfilled("View displayed but disabled");
+ }
+ } else { // Expected a displayed but disabled View.
+ if (mViewMatched.isEnabled()) {
+ return notFulfilled("View displayed but enabled");
+ }
+ }
return fulfilled(message[0]);
} catch (NoMatchingViewException
| NoMatchingRootException
@@ -129,6 +141,32 @@ public class ViewConditions {
return notFulfilled(e.getClass().getSimpleName());
}
}
+
+ /**
+ * @return an Options builder to customize the ViewCondition.
+ */
+ public static Options.Builder newOptions() {
+ return new Options().new Builder();
+ }
+
+ /** Extra options for declaring ExistsCondition. */
+ public static class Options {
+ boolean mExpectEnabled = true;
+
+ private Options() {}
+
+ public class Builder {
+ public Options build() {
+ return Options.this;
+ }
+
+ /** Whether the view is expected to be enabled or disabled. */
+ public Builder withExpectEnabled(boolean state) {
+ mExpectEnabled = state;
+ return this;
+ }
+ }
+ }
}
/** Fulfilled when no matching Views exist and are displayed. */
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElement.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElement.java
index 6a44672063..444376877c 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElement.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElement.java
@@ -11,7 +11,6 @@ import static org.hamcrest.Matchers.allOf;
import android.view.View;
import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
import androidx.test.espresso.Espresso;
import androidx.test.espresso.ViewAction;
import androidx.test.espresso.ViewInteraction;
@@ -35,6 +34,7 @@ public class ViewElement {
private final Matcher<View> mViewMatcher;
private final @Scope int mScope;
private final String mId;
+ private final Options mOptions;
/** Alias for {@link #sharedViewElement(Matcher)} as the default way to declare ViewElements. */
public static ViewElement viewElement(Matcher<View> viewMatcher) {
@@ -42,11 +42,12 @@ public class ViewElement {
}
/**
- * Version of {@link #sharedViewElement(Matcher, String)} using the Matcher |description| as
- * |id|.
+ * Version of {@link #sharedViewElement(Matcher, Options)} using default Options.
+ *
+ * <p>This is a good default method to the declare ViewElements; when in doubt, use this.
*/
public static ViewElement sharedViewElement(Matcher<View> viewMatcher) {
- return new ViewElement(viewMatcher, Scope.SHARED, /* id= */ null);
+ return new ViewElement(viewMatcher, Scope.SHARED, Options.DEFAULT);
}
/**
@@ -57,19 +58,14 @@ public class ViewElement {
* <p>Shared ViewElements add an EXIT condition that no View is matched unless transitioning to
* a ConditionalState that declares a ViewElement with the same id (which usually means an equal
* Matcher<View>).
- *
- * <p>This is a good default method to the declare ViewElements; when in doubt, use this.
*/
- public static ViewElement sharedViewElement(Matcher<View> viewMatcher, String id) {
- return new ViewElement(viewMatcher, Scope.SHARED, id);
+ public static ViewElement sharedViewElement(Matcher<View> viewMatcher, Options options) {
+ return new ViewElement(viewMatcher, Scope.SHARED, options);
}
- /**
- * Version of {@link #scopedViewElement(Matcher, String)} using the Matcher |description| as
- * |id|.
- */
+ /** Version of {@link #scopedViewElement(Matcher, Options)} using default Options. */
public static ViewElement scopedViewElement(Matcher<View> viewMatcher) {
- return new ViewElement(viewMatcher, Scope.CONDITIONAL_STATE_SCOPED, /* id= */ null);
+ return new ViewElement(viewMatcher, Scope.CONDITIONAL_STATE_SCOPED, Options.DEFAULT);
}
/**
@@ -80,16 +76,13 @@ public class ViewElement {
* <p>ConditionalState-scoped ViewElements are the most restrictive; they generate an EXIT
* condition that no View is matched under any circumstances.
*/
- public static ViewElement scopedViewElement(Matcher<View> viewMatcher, String id) {
- return new ViewElement(viewMatcher, Scope.CONDITIONAL_STATE_SCOPED, id);
+ public static ViewElement scopedViewElement(Matcher<View> viewMatcher, Options options) {
+ return new ViewElement(viewMatcher, Scope.CONDITIONAL_STATE_SCOPED, options);
}
- /**
- * Version of {@link #unscopedViewElement(Matcher, String)} using the Matcher |description| as
- * |id|.
- */
+ /** Version of {@link #unscopedViewElement(Matcher, Options)} using default Options. */
public static ViewElement unscopedViewElement(Matcher<View> viewMatcher) {
- return new ViewElement(viewMatcher, Scope.UNSCOPED, /* id= */ null);
+ return new ViewElement(viewMatcher, Scope.UNSCOPED, Options.DEFAULT);
}
/**
@@ -100,16 +93,17 @@ public class ViewElement {
* <p>Unscoped ViewElements are the most permissive; they do not generate EXIT conditions,
* therefore they may or may not be gone.
*/
- public static ViewElement unscopedViewElement(Matcher<View> viewMatcher, String id) {
- return new ViewElement(viewMatcher, Scope.UNSCOPED, id);
+ public static ViewElement unscopedViewElement(Matcher<View> viewMatcher, Options options) {
+ return new ViewElement(viewMatcher, Scope.UNSCOPED, options);
}
- private ViewElement(Matcher<View> viewMatcher, @Scope int scope, @Nullable String id) {
+ private ViewElement(Matcher<View> viewMatcher, @Scope int scope, Options options) {
mViewMatcher = viewMatcher;
mScope = scope;
- if (id != null) {
- mId = id;
+ if (options.mElementId != null) {
+ // Use a custom id instead of the Matcher description.
+ mId = options.mElementId;
} else {
// Capture the description as soon as possible to compare ViewElements added to
// different
@@ -119,6 +113,8 @@ public class ViewElement {
// https://crbug.com/41494895#comment7.
mId = StringDescription.toString(mViewMatcher);
}
+
+ mOptions = options;
}
String getId() {
@@ -150,4 +146,53 @@ public class ViewElement {
public ViewInteraction perform(ViewAction action) {
return onView().perform(action);
}
+
+ /**
+ * @return the Options passed when declaring the ViewElement.
+ */
+ public Options getOptions() {
+ return mOptions;
+ }
+
+ /**
+ * @return an Options builder to customize the ViewElement further.
+ */
+ public static Options.Builder newOptions() {
+ return new Options().new Builder();
+ }
+
+ /** Extra options for declaring ViewElements. */
+ public static class Options {
+ static final Options DEFAULT = new Options();
+ protected boolean mExpectEnabled = true;
+ protected String mElementId;
+
+ protected Options() {}
+
+ public class Builder {
+ public Options build() {
+ return Options.this;
+ }
+
+ /** Use a custom Element id instead of the Matcher<View> description. */
+ public Builder elementId(String id) {
+ mElementId = id;
+ return this;
+ }
+
+ /**
+ * Expect the View to be disabled instead of enabled.
+ *
+ * <p>This is different than passing an isEnabled() Matcher.If the matcher was, for
+ * example |allOf(withId(ID), isEnabled())|, the exit condition would be considered
+ * fulfilled if the View became disabled. Meanwhile, using this option makes the exit
+ * condition only be considered fulfilled if no Views |withId(ID)|, enabled or not, were
+ * displayed.
+ */
+ public Builder expectDisabled() {
+ mExpectEnabled = false;
+ return this;
+ }
+ }
+ }
}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElementInState.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElementInState.java
index d1fe0fa8f9..5aa969303a 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElementInState.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ViewElementInState.java
@@ -11,6 +11,7 @@ import androidx.annotation.Nullable;
import org.hamcrest.Matcher;
import org.chromium.base.test.transit.ViewConditions.DisplayedCondition;
+import org.chromium.base.test.transit.ViewConditions.ExistsCondition;
import org.chromium.base.test.transit.ViewConditions.GatedDisplayedCondition;
import org.chromium.base.test.transit.ViewConditions.NotDisplayedAnymoreCondition;
import org.chromium.base.test.transit.ViewElement.Scope;
@@ -39,12 +40,18 @@ class ViewElementInState implements ElementInState {
mGate = gate;
Matcher<View> viewMatcher = mViewElement.getViewMatcher();
+ ExistsCondition.Options conditionOptions =
+ ExistsCondition.newOptions()
+ .withExpectEnabled(mViewElement.getOptions().mExpectEnabled)
+ .build();
if (mGate != null) {
GatedDisplayedCondition gatedDisplayedCondition =
- new GatedDisplayedCondition(mViewElement.getViewMatcher(), mGate);
+ new GatedDisplayedCondition(
+ mViewElement.getViewMatcher(), mGate, conditionOptions);
mEnterCondition = gatedDisplayedCondition;
} else {
- DisplayedCondition displayedCondition = new DisplayedCondition(viewMatcher);
+ DisplayedCondition displayedCondition =
+ new DisplayedCondition(viewMatcher, conditionOptions);
mEnterCondition = displayedCondition;
}