summaryrefslogtreecommitdiff
path: root/app/src/androidTest/java/utils
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/androidTest/java/utils')
-rw-r--r--app/src/androidTest/java/utils/CustomInteractions.java82
-rw-r--r--app/src/androidTest/java/utils/CustomMatchers.java31
-rw-r--r--app/src/androidTest/java/utils/CustomViewActions.java89
3 files changed, 202 insertions, 0 deletions
diff --git a/app/src/androidTest/java/utils/CustomInteractions.java b/app/src/androidTest/java/utils/CustomInteractions.java
new file mode 100644
index 00000000..9e3a8f9d
--- /dev/null
+++ b/app/src/androidTest/java/utils/CustomInteractions.java
@@ -0,0 +1,82 @@
+package utils;
+
+import androidx.annotation.Nullable;
+import androidx.test.espresso.DataInteraction;
+import androidx.test.espresso.NoMatchingViewException;
+import androidx.test.espresso.ViewAssertion;
+import androidx.test.espresso.ViewInteraction;
+
+public class CustomInteractions {
+
+ public static @Nullable
+ ViewInteraction tryResolve(ViewInteraction viewInteraction, int maxTries) {
+ return tryResolve(viewInteraction, null, maxTries);
+ }
+
+ public static @Nullable
+ ViewInteraction tryResolve(ViewInteraction viewInteraction, ViewAssertion assertion) {
+ return tryResolve(viewInteraction, assertion, 10);
+ }
+
+ public static @Nullable ViewInteraction tryResolve(ViewInteraction viewInteraction, ViewAssertion assertion, int maxTries) {
+ ViewInteraction resolvedViewInteraction = null;
+ int attempt = 0;
+ boolean hasFound = false;
+ while (!hasFound && attempt < maxTries) {
+ try {
+ resolvedViewInteraction = viewInteraction;
+ if (assertion != null) {
+ resolvedViewInteraction.check(assertion);
+ }
+ hasFound = true;
+ } catch (NoMatchingViewException exception) {
+ System.out.println("NoMatchingViewException attempt: " + attempt);
+ exception.printStackTrace();
+ attempt++;
+ if (attempt == maxTries) {
+ throw exception;
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
+ return resolvedViewInteraction;
+ }
+
+ public static @Nullable
+ DataInteraction tryResolve(DataInteraction dataInteraction, ViewAssertion assertion, int maxTries) {
+ DataInteraction resolvedDataInteraction = null;
+ int attempt = 0;
+ boolean hasFound = false;
+ while (!hasFound && attempt < maxTries) {
+ try {
+ resolvedDataInteraction = dataInteraction;
+ if (assertion != null) {
+ resolvedDataInteraction.check(assertion);
+ }
+ hasFound = true;
+ } catch (Exception exception) {
+ // TODO: specify expected exception
+ attempt++;
+ if (attempt == maxTries) {
+ throw exception;
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
+ return resolvedDataInteraction;
+ }
+ public static @Nullable
+ DataInteraction tryResolve(DataInteraction dataInteraction, int maxTries) {
+ return tryResolve(dataInteraction, null, maxTries);
+ }
+}
diff --git a/app/src/androidTest/java/utils/CustomMatchers.java b/app/src/androidTest/java/utils/CustomMatchers.java
new file mode 100644
index 00000000..5fe11cd2
--- /dev/null
+++ b/app/src/androidTest/java/utils/CustomMatchers.java
@@ -0,0 +1,31 @@
+package utils;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+public class CustomMatchers {
+
+ public static Matcher<View> childAtPosition(
+ final Matcher<View> parentMatcher, final int position) {
+
+ return new TypeSafeMatcher<View>() {
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Child at position " + position + " in parent ");
+ parentMatcher.describeTo(description);
+ }
+
+ @Override
+ public boolean matchesSafely(View view) {
+ ViewParent parent = view.getParent();
+ return parent instanceof ViewGroup && parentMatcher.matches(parent)
+ && view.equals(((ViewGroup) parent).getChildAt(position));
+ }
+ };
+ }
+}
diff --git a/app/src/androidTest/java/utils/CustomViewActions.java b/app/src/androidTest/java/utils/CustomViewActions.java
new file mode 100644
index 00000000..fb0dcc27
--- /dev/null
+++ b/app/src/androidTest/java/utils/CustomViewActions.java
@@ -0,0 +1,89 @@
+package utils;
+
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import android.view.View;
+
+import androidx.annotation.StringRes;
+import androidx.test.espresso.UiController;
+import androidx.test.espresso.ViewAction;
+import androidx.test.espresso.util.TreeIterables;
+
+import org.hamcrest.Matcher;
+
+public class CustomViewActions {
+
+ public static ViewAction waitForView(int viewId, long timeout) {
+ return new ViewAction() {
+
+ @Override
+ public String getDescription() {
+ return "Wait for view with specific id \n@param viewId: resource ID \n@param timeout: timeout in milli seconds.";
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isRoot();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ uiController.loopMainThreadUntilIdle();
+ long startTime = System.currentTimeMillis();
+ long endTime = startTime + timeout;
+ Matcher viewMatcher = withId(viewId);
+
+ while (System.currentTimeMillis() < endTime) {
+ // Iterate through all views on the screen and see if the view we are looking for is there already
+ for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
+ // found view with required ID
+ if (viewMatcher.matches(child)) {
+ return;
+ }
+ }
+ // Loops the main thread for a specified period of time.
+ // Control may not return immediately, instead it'll return after the provided delay has passed and the queue is in an idle state again.
+ uiController.loopMainThreadForAtLeast(100);
+ }
+ }
+ };
+ }
+
+ public static ViewAction waitForText(@StringRes int textId, long timeout) {
+ return new ViewAction() {
+
+ @Override
+ public String getDescription() {
+ return "Wait for view with specific id \n@param viewId: resource ID \n@param timeout: timeout in milli seconds.";
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isRoot();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ uiController.loopMainThreadUntilIdle();
+ long startTime = System.currentTimeMillis();
+ long endTime = startTime + timeout;
+ Matcher viewMatcher = withText(textId);
+
+ while (System.currentTimeMillis() < endTime) {
+ // Iterate through all views on the screen and see if the view we are looking for is there already
+ for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
+ // found view with required ID
+ if (viewMatcher.matches(child)) {
+ return;
+ }
+ }
+ // Loops the main thread for a specified period of time.
+ // Control may not return immediately, instead it'll return after the provided delay has passed and the queue is in an idle state again.
+ uiController.loopMainThreadForAtLeast(100);
+ }
+ }
+ };
+ }
+} \ No newline at end of file