Java Code Examples for androidx.test.espresso.UiController#loopMainThreadForAtLeast()

The following examples show how to use androidx.test.espresso.UiController#loopMainThreadForAtLeast() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: FloatingActionButtonActions.java    From material-components-android with Apache License 2.0 6 votes vote down vote up
public static ViewAction hideThenShow() {
  return new ViewAction() {
    @Override
    public Matcher<View> getConstraints() {
      return isAssignableFrom(FloatingActionButton.class);
    }

    @Override
    public String getDescription() {
      return "Calls hide() then show()";
    }

    @Override
    public void perform(UiController uiController, View view) {
      FloatingActionButton fab = (FloatingActionButton) view;
      fab.hide();
      fab.show();

      long duration = fab.getShowMotionSpec().getTotalDuration();
      uiController.loopMainThreadForAtLeast(duration + 50);
    }
  };
}
 
Example 2
Source File: FloatingActionButtonActions.java    From material-components-android with Apache License 2.0 6 votes vote down vote up
public static ViewAction showThenHide() {
  return new ViewAction() {
    @Override
    public Matcher<View> getConstraints() {
      return isAssignableFrom(FloatingActionButton.class);
    }

    @Override
    public String getDescription() {
      return "Calls show() then hide()";
    }

    @Override
    public void perform(UiController uiController, View view) {
      FloatingActionButton fab = (FloatingActionButton) view;
      fab.show();
      fab.hide();

      long duration = fab.getHideMotionSpec().getTotalDuration();
      uiController.loopMainThreadForAtLeast(duration + 50);
    }
  };
}
 
Example 3
Source File: TestUtilsActions.java    From material-components-android with Apache License 2.0 6 votes vote down vote up
/**
 * Dummy Espresso action that waits for at least the given amount of milliseconds. This action can
 * be performed on the root view to wait for an ongoing animation to be completed.
 */
public static ViewAction waitFor(final long ms) {
  return new ViewAction() {
    @Override
    public Matcher<View> getConstraints() {
      return isRoot();
    }

    @Override
    public String getDescription() {
      return "wait for " + ms + " ms";
    }

    @Override
    public void perform(UiController uiController, View view) {
      uiController.loopMainThreadForAtLeast(ms);
    }
  };
}
 
Example 4
Source File: DrawerLayoutActions.java    From material-components-android with Apache License 2.0 6 votes vote down vote up
/** Opens the drawer at the specified edge gravity. */
public static ViewAction openDrawer(final int drawerEdgeGravity) {
  return new ViewAction() {
    @Override
    public Matcher<View> getConstraints() {
      return isAssignableFrom(DrawerLayout.class);
    }

    @Override
    public String getDescription() {
      return "Opens the drawer";
    }

    @Override
    public void perform(UiController uiController, View view) {
      uiController.loopMainThreadUntilIdle();

      DrawerLayout drawerLayout = (DrawerLayout) view;
      drawerLayout.openDrawer(drawerEdgeGravity);

      // Wait for a full second to let the inner ViewDragHelper complete the operation
      uiController.loopMainThreadForAtLeast(1000);
    }
  };
}
 
Example 5
Source File: DrawerLayoutActions.java    From material-components-android with Apache License 2.0 6 votes vote down vote up
/** Closes the drawer at the specified edge gravity. */
public static ViewAction closeDrawer(final int drawerEdgeGravity) {
  return new ViewAction() {
    @Override
    public Matcher<View> getConstraints() {
      return isAssignableFrom(DrawerLayout.class);
    }

    @Override
    public String getDescription() {
      return "Closes the drawer";
    }

    @Override
    public void perform(UiController uiController, View view) {
      uiController.loopMainThreadUntilIdle();

      DrawerLayout drawerLayout = (DrawerLayout) view;
      drawerLayout.closeDrawer(drawerEdgeGravity);

      // Wait for a full second to let the inner ViewDragHelper complete the operation
      uiController.loopMainThreadForAtLeast(1000);
    }
  };
}
 
Example 6
Source File: ShowcaseRunTest.java    From fresco with MIT License 6 votes vote down vote up
private static ViewAction waitFor(final long millis) {
  return new ViewAction() {
    @Override
    public Matcher<View> getConstraints() {
      return withId(R.id.drawee_view);
    }

    @Override
    public String getDescription() {
      return "Waiting for " + millis + " milliseconds.";
    }

    @Override
    public void perform(UiController uiController, final View view) {
      uiController.loopMainThreadForAtLeast(millis);
    }
  };
}
 
Example 7
Source File: DrawerActions.java    From android-test with Apache License 2.0 6 votes vote down vote up
/**
 * Creates an action which closes the {@link DrawerLayout} with the gravity. This method blocks
 * until the drawer is fully closed. No operation if the drawer is already closed.
 */
// TODO alias to closeDrawer before 3.0 and deprecate this method.
public static ViewAction close(final int gravity) {
  return new DrawerAction() {
    @Override
    public String getDescription() {
      return "close drawer with gravity " + gravity;
    }

    @Override
    protected Matcher<View> checkAction() {
      return isOpen(gravity);
    }

    @Override
    protected void performAction(UiController uiController, DrawerLayout view) {
      view.closeDrawer(gravity);
      uiController.loopMainThreadUntilIdle();
      // If still open wait some more...
      if (view.isDrawerVisible(gravity)) {
        uiController.loopMainThreadForAtLeast(300);
      }
    }
  };
}
 
Example 8
Source File: KeyEventActionBase.java    From android-test with Apache License 2.0 6 votes vote down vote up
static void waitForStageChangeInitialActivity(UiController controller, Activity initialActivity) {
  if (isActivityResumed(initialActivity)) {
    // The activity transition hasn't happened yet, wait for it.
    controller.loopMainThreadForAtLeast(BACK_ACTIVITY_TRANSITION_MILLIS_DELAY);
    if (isActivityResumed(initialActivity)) {
      Log.i(
          TAG,
          "Back was pressed but there was no Activity stage transition in "
              + BACK_ACTIVITY_TRANSITION_MILLIS_DELAY
              + "ms. Pressing back may trigger an activity stage transition if the activity is"
              + " finished as a result. However, the activity may handle the back behavior in"
              + " any number of other ways internally as well, such as popping the fragment back"
              + " stack, dismissing a dialog, otherwise manually transacting fragments, etc.");
    }
  }
}
 
Example 9
Source File: BottomSheetBehaviorTest.java    From material-components-android with Apache License 2.0 5 votes vote down vote up
@Override
public void perform(UiController uiController, View view) {
  float[] precision = precisionDescriber.describePrecision();
  float[] start = this.start.calculateCoordinates(view);
  float[] end = this.end.calculateCoordinates(view);
  float[][] steps = interpolate(start, end, STEPS);
  int delayBetweenMovements = DURATION / steps.length;
  // Down
  MotionEvent downEvent = MotionEvents.sendDown(uiController, start, precision).down;
  try {
    for (int i = 0; i < steps.length; i++) {
      // Wait
      long desiredTime = downEvent.getDownTime() + (long) (delayBetweenMovements * i);
      long timeUntilDesired = desiredTime - SystemClock.uptimeMillis();
      if (timeUntilDesired > 10L) {
        uiController.loopMainThreadForAtLeast(timeUntilDesired);
      }
      // Move
      if (!MotionEvents.sendMovement(uiController, downEvent, steps[i])) {
        MotionEvents.sendCancel(uiController, downEvent);
        throw new RuntimeException("Cannot drag: failed to send a move event.");
      }
    }
    int duration = ViewConfiguration.getPressedStateDuration();
    if (duration > 0) {
      uiController.loopMainThreadForAtLeast((long) duration);
    }
  } finally {
    downEvent.recycle();
  }
}
 
Example 10
Source File: ViewActions.java    From Kore with Apache License 2.0 5 votes vote down vote up
/**
 * ViewAction that waits until view with viewId becomes visible
 * @param viewId Resource identifier of view item that must be checked
 * @param checkStatus called when viewId has been found to check its status. If return value
 *                      is true waitForView will stop, false it will continue until timeout is exceeded
 * @param millis amount of time to wait for view to become visible
 * @return
 */
public static ViewAction waitForView(final int viewId, final CheckStatus checkStatus, final long millis) {
    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return isRoot();
        }

        @Override
        public String getDescription() {
            return "Searches for view with id: " + viewId + " and tests its status using CheckStatus, using timeout " + millis + " ms.";
        }

        @Override
        public void perform(UiController uiController, View view) {
            final long endTime = System.currentTimeMillis() + millis;
            do {
                for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
                    if (child.getId() == viewId) {
                        if (checkStatus.check(child)) {
                            return;
                        }
                    }
                }

                uiController.loopMainThreadForAtLeast(50);
            } while (System.currentTimeMillis() < endTime);

            throw new PerformException.Builder()
                    .withActionDescription(this.getDescription())
                    .withViewDescription(HumanReadables.describe(view))
                    .withCause(new TimeoutException())
                    .build();
        }
    };
}
 
Example 11
Source File: KeyEventActionBase.java    From android-test with Apache License 2.0 5 votes vote down vote up
static void waitForPendingForegroundActivities(UiController controller, boolean conditional) {
  ActivityLifecycleMonitor activityLifecycleMonitor =
      ActivityLifecycleMonitorRegistry.getInstance();
  boolean pendingForegroundActivities = false;
  for (int attempts = 0; attempts < CLEAR_TRANSITIONING_ACTIVITIES_ATTEMPTS; attempts++) {
    controller.loopMainThreadUntilIdle();
    pendingForegroundActivities = hasTransitioningActivities(activityLifecycleMonitor);
    if (pendingForegroundActivities) {
      controller.loopMainThreadForAtLeast(CLEAR_TRANSITIONING_ACTIVITIES_MILLIS_DELAY);
    } else {
      break;
    }
  }

  // Pressing back can kill the app: log a warning.
  if (!hasForegroundActivities(activityLifecycleMonitor)) {
    if (conditional) {
      throw new NoActivityResumedException("Pressed back and killed the app");
    }
    Log.w(TAG, "Pressed back and hopped to a different process or potentially killed the app");
  }

  if (pendingForegroundActivities) {
    Log.w(
        TAG,
        "Back was pressed and left the application in an inconsistent state even after "
            + (CLEAR_TRANSITIONING_ACTIVITIES_MILLIS_DELAY
                * CLEAR_TRANSITIONING_ACTIVITIES_ATTEMPTS)
            + "ms.");
  }
}
 
Example 12
Source File: WaitAction.java    From mapbox-plugins-android with BSD 2-Clause "Simplified" License 4 votes vote down vote up
@Override
public void perform(UiController uiController, View view) {
  uiController.loopMainThreadForAtLeast(loopTime);
}
 
Example 13
Source File: Utils.java    From BottomNavigation with Apache License 2.0 4 votes vote down vote up
/**
 * Perform action of waiting for a specific view id.
 */
public static ViewAction waitId(final int viewId, final long millis) {
    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return isRoot();
        }

        @Override
        public String getDescription() {
            return "wait for a specific view with id <" + viewId + "> during " + millis + " millis.";
        }

        @Override
        public void perform(final UiController uiController, final View view) {
            uiController.loopMainThreadUntilIdle();
            final long startTime = System.currentTimeMillis();
            final long endTime = startTime + millis;
            final Matcher<View> viewMatcher = withId(viewId);

            do {
                for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
                    // found view with required ID
                    if (viewMatcher.matches(child)) {
                        return;
                    }
                }

                uiController.loopMainThreadForAtLeast(50);
            }
            while (System.currentTimeMillis() < endTime);

            // timeout happens
            throw new PerformException.Builder()
                    .withActionDescription(this.getDescription())
                    .withViewDescription(HumanReadables.describe(view))
                    .withCause(new TimeoutException())
                    .build();
        }
    };
}
 
Example 14
Source File: ViewActions.java    From Kore with Apache License 2.0 4 votes vote down vote up
public static ViewAction slideSeekBar(final int progress) {
    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return new TypeSafeMatcher<View>() {
                @Override
                protected boolean matchesSafely(View item) {
                    return item instanceof SeekBar;
                }

                @Override
                public void describeTo(Description description) {
                    description.appendText("is a SeekBar.");
                }
            };
        }

        @Override
        public String getDescription() {
            return "Slides seekbar to progress position " + progress;
        }

        @Override
        public void perform(UiController uiController, View view) {
            SeekBar seekBar = (SeekBar) view;

            int[] seekBarPos = {0,0};
            view.getLocationOnScreen(seekBarPos);
            float[] startPos = {seekBarPos[0], seekBarPos[1]};

            MotionEvents.DownResultHolder downResultHolder =
                    MotionEvents.sendDown(uiController, startPos,
                                          Press.PINPOINT.describePrecision());

            while(seekBar.getProgress() < progress) {
                startPos[0]++;
                MotionEvents.sendMovement(uiController, downResultHolder.down, startPos);
                uiController.loopMainThreadForAtLeast(10);
            }

            MotionEvents.sendUp(uiController, downResultHolder.down, startPos);
        }
    };
}
 
Example 15
Source File: MotionEvents.java    From android-test with Apache License 2.0 4 votes vote down vote up
public static DownResultHolder sendDown(
    UiController uiController,
    float[] coordinates,
    float[] precision,
    int inputDevice,
    int buttonState) {
  checkNotNull(uiController);
  checkNotNull(coordinates);
  checkNotNull(precision);

  for (int retry = 0; retry < MAX_CLICK_ATTEMPTS; retry++) {
    MotionEvent motionEvent = null;
    try {
      motionEvent = obtainDownEvent(coordinates, precision, inputDevice, buttonState);
      // The down event should be considered a tap if it is long enough to be detected
      // but short enough not to be a long-press. Assume that TapTimeout is set at least
      // twice the detection time for a tap (no need to sleep for the whole TapTimeout since
      // we aren't concerned about scrolling here).
      long downTime = motionEvent.getDownTime();
      long isTapAt = downTime + (ViewConfiguration.getTapTimeout() / 2);

      boolean injectEventSucceeded = uiController.injectMotionEvent(motionEvent);

      while (true) {
        long delayToBeTap = isTapAt - SystemClock.uptimeMillis();
        if (delayToBeTap <= 10) {
          break;
        }
        // Sleep only a fraction of the time, since there may be other events in the UI queue
        // that could cause us to start sleeping late, and then oversleep.
        uiController.loopMainThreadForAtLeast(delayToBeTap / 4);
      }

      boolean longPress = false;
      if (SystemClock.uptimeMillis() > (downTime + ViewConfiguration.getLongPressTimeout())) {
        longPress = true;
        Log.w(TAG, "Overslept and turned a tap into a long press");
      }

      if (!injectEventSucceeded) {
        motionEvent.recycle();
        motionEvent = null;
        continue;
      }

      return new DownResultHolder(motionEvent, longPress);
    } catch (InjectEventSecurityException e) {
      throw new PerformException.Builder()
          .withActionDescription("Send down motion event")
          .withViewDescription("unknown") // likely to be replaced by FailureHandler
          .withCause(e)
          .build();
    }
  }
  throw new PerformException.Builder()
      .withActionDescription(
          String.format(Locale.ROOT, "click (after %s attempts)", MAX_CLICK_ATTEMPTS))
      .withViewDescription("unknown") // likely to be replaced by FailureHandler
      .build();
}
 
Example 16
Source File: GeneralSwipeAction.java    From android-test with Apache License 2.0 4 votes vote down vote up
@Override
public void perform(UiController uiController, View view) {
  float[] startCoordinates = startCoordinatesProvider.calculateCoordinates(view);
  float[] endCoordinates = endCoordinatesProvider.calculateCoordinates(view);
  float[] precision = precisionDescriber.describePrecision();

  Swiper.Status status = Swiper.Status.FAILURE;

  for (int tries = 0; tries < MAX_TRIES && status != Swiper.Status.SUCCESS; tries++) {
    try {
      status = swiper.sendSwipe(uiController, startCoordinates, endCoordinates, precision);
    } catch (RuntimeException re) {
      throw new PerformException.Builder()
          .withActionDescription(this.getDescription())
          .withViewDescription(HumanReadables.describe(view))
          .withCause(re)
          .build();
    }

    int duration = ViewConfiguration.getPressedStateDuration();
    // ensures that all work enqueued to process the swipe has been run.
    if (duration > 0) {
      uiController.loopMainThreadForAtLeast(duration);
    }
  }

  if (status == Swiper.Status.FAILURE) {
    throw new PerformException.Builder()
        .withActionDescription(getDescription())
        .withViewDescription(HumanReadables.describe(view))
        .withCause(
            new RuntimeException(
                String.format(
                    Locale.ROOT,
                    "Couldn't swipe from: %s,%s to: %s,%s precision: %s, %s . Swiper: %s "
                        + "start coordinate provider: %s precision describer: %s. Tried %s times",
                    startCoordinates[0],
                    startCoordinates[1],
                    endCoordinates[0],
                    endCoordinates[1],
                    precision[0],
                    precision[1],
                    swiper,
                    startCoordinatesProvider,
                    precisionDescriber,
                    MAX_TRIES)))
        .build();
  }
}