public final class

ViewActions

extends java.lang.Object

 java.lang.Object

↳androidx.test.espresso.action.ViewActions

Gradle dependencies

compile group: 'androidx.test.espresso', name: 'espresso-core', version: '3.6.1'

  • groupId: androidx.test.espresso
  • artifactId: espresso-core
  • version: 3.6.1

Artifact androidx.test.espresso:espresso-core:3.6.1 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.test.espresso:espresso-core com.android.support.test.espresso:espresso-core

Androidx class mapping:

androidx.test.espresso.action.ViewActions android.support.test.espresso.action.ViewActions

Overview

A collection of common ViewActions.

Summary

Methods
public static ViewActionactionWithAssertions(ViewAction viewAction)

Performs all assertions before the ViewActions in this class and then performs the given ViewAction

public static voidaddGlobalAssertion(java.lang.String name, ViewAssertion viewAssertion)

Adds a ViewAssertion to be run every time a ViewAction in this class is performed.

public static ViewActioncaptureToBitmap(ViewActions.BitmapReceiver bitmapReceiver)

Returns an action that captures an image of the desired View and performs some other operation on the result.

public static voidclearGlobalAssertions()

public static ViewActionclearText()

Returns an action that clears text on the view.

View constraints:

  • must be displayed on screen

public static ViewActionclick()

Same as click(int inputDevice, int buttonState), but uses as the inputDevice and MotionEvent as the buttonState.

public static ViewActionclick(int inputDevice, int buttonState)

Returns an action that clicks the view for a specific input device and button state.

public static ViewActionclick(ViewAction rollbackAction)

Returns an action that performs a single click on the view.

public static ViewActioncloseSoftKeyboard()

Returns an action that closes soft keyboard.

public static ViewActiondoubleClick()

Returns an action that double clicks the view.

View preconditions:

  • must be displayed on screen

public static ViewActionlongClick()

Returns an action that long clicks the view.

View preconditions:

  • must be displayed on screen

public static ViewActionopenLink(<any> linkTextMatcher, <any> uriMatcher)

Returns an action that opens a link matching the given link text and uri matchers.

public static ViewActionopenLinkWithText(<any> linkTextMatcher)

Same as openLink(Matcher linkTextMatcher, Matcher uriMatcher), but uses any(Uri.class) as the uriMatcher.

public static ViewActionopenLinkWithText(java.lang.String linkText)

Same as openLinkWithText(Matcher linkTextMatcher), but uses is(linkText) as the linkTextMatcher.

public static ViewActionopenLinkWithUri(<any> uriMatcher)

Same as openLink(Matcher linkTextMatcher, Matcher uriMatcher), but uses any(String.class) as the linkTextMatcher.

public static ViewActionopenLinkWithUri(java.lang.String uri)

Same as openLinkWithUri(Matcher uriMatcher), but uses is(uri) as the uriMatcher.

public static ViewActionpressBack()

Returns an action that clicks the back button.

public static ViewActionpressBackUnconditionally()

Similar to ViewActions.pressBack() but will not throw an exception when Espresso navigates outside the application or process under test.

public static ViewActionpressImeActionButton()

Returns an action that presses the current action button (next, done, search, etc) on the IME (Input Method Editor).

public static ViewActionpressKey(EspressoKey key)

Returns an action that presses the specified key with the specified modifiers.

public static ViewActionpressKey(int keyCode)

Returns an action that presses the key specified by the keyCode (eg.

public static ViewActionpressMenuKey()

Returns an action that presses the hardware menu key.

public static voidremoveGlobalAssertion(ViewAssertion viewAssertion)

Removes the given assertion from the set of assertions to be run before actions are performed.

public static ViewActionrepeatedlyUntil(ViewAction action, <any> desiredStateMatcher, int maxAttempts)

Returns an action that performs given ViewAction on the view until view matches the desired Matcher.

public static ViewActionreplaceText(java.lang.String stringToBeSet)

Returns an action that updates the text attribute of a view.

public static ViewActionscrollCompletelyTo()

Returns an action that scrolls to the view.

In order for the scroll to be considered to have succeeded, the target view must match ViewMatchers for the specified value.

public static ViewActionscrollTo()

Returns an action that scrolls to the view.

View preconditions:

  • must be a descendant of ScrollView
  • must have visibility set to View.VISIBLE

public static ViewActionscrollTo(int isDisplayingAtLeastThreshold)

Returns an action that scrolls to the view.

In order for the scroll to be considered to have succeeded, the target view must match ViewMatchers.isDisplayingAtLeast(int) for the specified value.

public static ViewActionslowSwipeLeft()

Similar to ViewActions.swipeLeft() but performs a slow and deliberate swipe instead.

public static ViewActionswipeDown()

Returns an action that performs a swipe top-to-bottom across the horizontal center of the view.

public static ViewActionswipeLeft()

Returns an action that performs a fast swipe right-to-left across the vertical center of the view.

public static ViewActionswipeRight()

Returns an action that performs a swipe left-to-right across the vertical center of the view.

public static ViewActionswipeUp()

Returns an action that performs a swipe bottom-to-top across the horizontal center of the view.

public static ViewActiontypeText(java.lang.String stringToBeTyped)

Returns an action that selects the view (by clicking on it) and types the provided string into the view.

public static ViewActiontypeTextIntoFocusedView(java.lang.String stringToBeTyped)

Returns an action that types the provided string into the view.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

public static void addGlobalAssertion(java.lang.String name, ViewAssertion viewAssertion)

Adds a ViewAssertion to be run every time a ViewAction in this class is performed. The assertion will be run prior to performing the action.

Parameters:

name: a name of the assertion to be added
viewAssertion: a ViewAssertion to be added

public static void removeGlobalAssertion(ViewAssertion viewAssertion)

Removes the given assertion from the set of assertions to be run before actions are performed.

Parameters:

viewAssertion: the assertion to remove

public static void clearGlobalAssertions()

public static ViewAction actionWithAssertions(ViewAction viewAction)

Performs all assertions before the ViewActions in this class and then performs the given ViewAction

Parameters:

viewAction: the ViewAction to perform after the assertions

public static ViewAction clearText()

Returns an action that clears text on the view.

View constraints:

  • must be displayed on screen

public static ViewAction click(int inputDevice, int buttonState)

Returns an action that clicks the view for a specific input device and button state.

Note: Not supported by API < 14. An java.lang.UnsupportedOperationException will be thrown if called on API < 14. For API < 14, call ViewActions.click() instead.

View constraints:

  • must be displayed on screen

Parameters:

inputDevice: source input device of the click. Example:
buttonState: buttonState associated with the click. Example: MotionEvent

public static ViewAction click()

Same as click(int inputDevice, int buttonState), but uses as the inputDevice and MotionEvent as the buttonState.

public static ViewAction click(ViewAction rollbackAction)

Returns an action that performs a single click on the view.

If the click takes longer than the 'long press' duration (which is possible) the provided rollback action is invoked on the view and a click is attempted again.

This is only necessary if the view being clicked on has some different behaviour for long press versus a normal tap.

For example - if a long press on a particular view element opens a popup menu - ViewActions.pressBack() may be an acceptable rollback action.
View constraints:

  • must be displayed on screen
  • any constraints of the rollbackAction

public static ViewAction swipeLeft()

Returns an action that performs a fast swipe right-to-left across the vertical center of the view. ViewActions.slowSwipeLeft() should be used instead if a slow deliberate swipe is needed (e.g. to avoid fling). The swipe doesn't start at the very edge of the view, but is a bit offset.

View constraints:

  • must be displayed on screen

public static ViewAction slowSwipeLeft()

Similar to ViewActions.swipeLeft() but performs a slow and deliberate swipe instead. This is useful, for example, to avoid fling.

View constraints:

  • must be displayed on screen

public static ViewAction swipeRight()

Returns an action that performs a swipe left-to-right across the vertical center of the view. The swipe doesn't start at the very edge of the view, but is a bit offset.

View constraints:

  • must be displayed on screen

public static ViewAction swipeDown()

Returns an action that performs a swipe top-to-bottom across the horizontal center of the view. The swipe doesn't start at the very edge of the view, but has a bit of offset.

View constraints:

  • must be displayed on screen

public static ViewAction swipeUp()

Returns an action that performs a swipe bottom-to-top across the horizontal center of the view. The swipe doesn't start at the very edge of the view, but has a bit of offset.

View constraints:

  • must be displayed on screen

public static ViewAction closeSoftKeyboard()

Returns an action that closes soft keyboard. If the keyboard is already closed, it is a no-op.

public static ViewAction pressImeActionButton()

Returns an action that presses the current action button (next, done, search, etc) on the IME (Input Method Editor). The selected view will have its onEditorAction method called.

public static ViewAction pressBack()

Returns an action that clicks the back button.

public static ViewAction pressBackUnconditionally()

Similar to ViewActions.pressBack() but will not throw an exception when Espresso navigates outside the application or process under test.

public static ViewAction pressMenuKey()

Returns an action that presses the hardware menu key.

public static ViewAction pressKey(int keyCode)

Returns an action that presses the key specified by the keyCode (eg. Keyevent.KEYCODE_BACK).

public static ViewAction pressKey(EspressoKey key)

Returns an action that presses the specified key with the specified modifiers.

public static ViewAction doubleClick()

Returns an action that double clicks the view.

View preconditions:

  • must be displayed on screen

public static ViewAction longClick()

Returns an action that long clicks the view.

View preconditions:

  • must be displayed on screen

public static ViewAction scrollTo()

Returns an action that scrolls to the view.

View preconditions:

  • must be a descendant of ScrollView
  • must have visibility set to View.VISIBLE

public static ViewAction scrollTo(int isDisplayingAtLeastThreshold)

Returns an action that scrolls to the view.

In order for the scroll to be considered to have succeeded, the target view must match ViewMatchers.isDisplayingAtLeast(int) for the specified value.

View preconditions:

  • must be a descendant of ScrollView
  • must have visibility set to View.VISIBLE

public static ViewAction scrollCompletelyTo()

Returns an action that scrolls to the view.

In order for the scroll to be considered to have succeeded, the target view must match ViewMatchers for the specified value.
View preconditions:

  • must be a descendant of ScrollView
  • must have visibility set to View.VISIBLE

public static ViewAction typeTextIntoFocusedView(java.lang.String stringToBeTyped)

Returns an action that types the provided string into the view. Appending a \n to the end of the string translates to a ENTER key event. Note: this method does not change cursor position in the focused view - text is inserted at the location where the cursor is currently pointed.

View preconditions:

  • must be displayed on screen
  • must support input methods
  • must be already focused

public static ViewAction typeText(java.lang.String stringToBeTyped)

Returns an action that selects the view (by clicking on it) and types the provided string into the view. Appending a \n to the end of the string translates to a ENTER key event. Note: this method performs a tap on the view before typing to force the view into focus, if the view already contains text this tap may place the cursor at an arbitrary position within the text.

View preconditions:

  • must be displayed on screen
  • must support input methods

public static ViewAction replaceText(java.lang.String stringToBeSet)

Returns an action that updates the text attribute of a view.

View preconditions:

  • must be displayed on screen
  • must be assignable from EditText

public static ViewAction openLinkWithText(java.lang.String linkText)

Same as openLinkWithText(Matcher linkTextMatcher), but uses is(linkText) as the linkTextMatcher.

public static ViewAction openLinkWithText(<any> linkTextMatcher)

Same as openLink(Matcher linkTextMatcher, Matcher uriMatcher), but uses any(Uri.class) as the uriMatcher.

public static ViewAction openLinkWithUri(java.lang.String uri)

Same as openLinkWithUri(Matcher uriMatcher), but uses is(uri) as the uriMatcher.

public static ViewAction openLinkWithUri(<any> uriMatcher)

Same as openLink(Matcher linkTextMatcher, Matcher uriMatcher), but uses any(String.class) as the linkTextMatcher.

public static ViewAction openLink(<any> linkTextMatcher, <any> uriMatcher)

Returns an action that opens a link matching the given link text and uri matchers. The action is performed by invoking the link's onClick method (as opposed to actually issuing a click on the screen).

View preconditions:

  • must be displayed on screen
  • must be assignable from TextView
  • must have links

public static ViewAction repeatedlyUntil(ViewAction action, <any> desiredStateMatcher, int maxAttempts)

Returns an action that performs given ViewAction on the view until view matches the desired Matcher. It will repeat the given action until view matches the desired Matcher or PerformException will be thrown if given number of unsuccessful attempts are made.

Parameters:

action: action to be performed repeatedly
desiredStateMatcher: action is performed repeatedly until view matches this view matcher
maxAttempts: max number of times for which this action to be performed if view doesn't match the given view matcher

public static ViewAction captureToBitmap(ViewActions.BitmapReceiver bitmapReceiver)

Returns an action that captures an image of the desired View and performs some other operation on the result.

Parameters:

bitmapReceiver: the BitmapReceiver that receives the result. This will be called on main thread.

Returns:

the ViewAction

See also:

Source

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.test.espresso.action;

import static androidx.test.internal.util.Checks.checkArgument;
import static androidx.test.internal.util.Checks.checkNotNull;
import static org.hamcrest.Matchers.any;
import static org.hamcrest.Matchers.is;

import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Log;
import android.util.Pair;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.test.espresso.PerformException;
import androidx.test.espresso.UiController;
import androidx.test.espresso.ViewAction;
import androidx.test.espresso.ViewAssertion;
import com.google.errorprone.annotations.CheckReturnValue;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import org.hamcrest.Matcher;

/** A collection of common {@link ViewActions}. */
@CheckReturnValue
public final class ViewActions {

  private ViewActions() {}

  /**
   * The distance of a swipe's start position from the view's edge, in terms of the view's length.
   * We do not start the swipe exactly on the view's edge, but somewhat more inward, since swiping
   * from the exact edge may behave in an unexpected way (e.g. may open a navigation drawer).
   */
  private static final float EDGE_FUZZ_FACTOR = 0.083f;

  /** A set of {@code ViewAssertion}s to be executed before the ViewActions in this class. */
  private static Set<Pair<String, ViewAssertion>> globalAssertions =
      new CopyOnWriteArraySet<Pair<String, ViewAssertion>>();

  /**
   * Adds a {@code ViewAssertion} to be run every time a {@code ViewAction} in this class is
   * performed. The assertion will be run prior to performing the action.
   *
   * @param name a name of the assertion to be added
   * @param viewAssertion a {@code ViewAssertion} to be added
   * @throws IllegalArgumentException if the name/viewAssertion pair is already contained in the
   *     global assertions.
   */
  public static void addGlobalAssertion(String name, ViewAssertion viewAssertion) {
    checkNotNull(name);
    checkNotNull(viewAssertion);
    Pair<String, ViewAssertion> vaPair = new Pair<String, ViewAssertion>(name, viewAssertion);
    checkArgument(
        !globalAssertions.contains(vaPair),
        "ViewAssertion with name %s is already in the global assertions!",
        name);
    globalAssertions.add(vaPair);
  }

  /**
   * Removes the given assertion from the set of assertions to be run before actions are performed.
   *
   * @param viewAssertion the assertion to remove
   * @throws IllegalArgumentException if the name/viewAssertion pair is not already contained in the
   *     global assertions.
   */
  public static void removeGlobalAssertion(ViewAssertion viewAssertion) {
    boolean removed = false;
    for (Pair<String, ViewAssertion> vaPair : globalAssertions) {
      if (viewAssertion != null && viewAssertion.equals(vaPair.second)) {
        removed = removed || globalAssertions.remove(vaPair);
      }
    }
    checkArgument(removed, "ViewAssertion was not in global assertions!");
  }

  public static void clearGlobalAssertions() {
    globalAssertions.clear();
  }

  /**
   * Performs all assertions before the {@code ViewAction}s in this class and then performs the
   * given {@code ViewAction}
   *
   * @param viewAction the {@code ViewAction} to perform after the assertions
   */
  public static ViewAction actionWithAssertions(final ViewAction viewAction) {
    if (globalAssertions.isEmpty()) {
      return viewAction;
    }
    return new ViewAction() {
      @Override
      public String getDescription() {
        StringBuilder msg = new StringBuilder("Running view assertions[");
        for (Pair<String, ViewAssertion> vaPair : globalAssertions) {
          msg.append(vaPair.first);
          msg.append(", ");
        }
        msg.append("] and then running: ");
        msg.append(viewAction.getDescription());
        return msg.toString();
      }

      @Override
      public Matcher<View> getConstraints() {
        return viewAction.getConstraints();
      }

      @Override
      public void perform(UiController uic, View view) {
        for (Pair<String, ViewAssertion> vaPair : globalAssertions) {
          Log.i("ViewAssertion", "Asserting " + vaPair.first);
          vaPair.second.check(view, null);
        }
        viewAction.perform(uic, view);
      }
    };
  }

  /**
   * Returns an action that clears text on the view.<br>
   * <br>
   * View constraints:
   *
   * <ul>
   *   <li>must be displayed on screen
   * </ul>
   */
  public static ViewAction clearText() {
    return actionWithAssertions(new ReplaceTextAction(""));
  }

  /**
   * Returns an action that clicks the view for a specific input device and button state.
   *
   * <p><b>Note:</b> Not supported by API < 14. An {@link UnsupportedOperationException} will be
   * thrown if called on API < 14. For API < 14, call {@link #click()} instead.<br>
   * <br>
   * View constraints:
   *
   * <ul>
   *   <li>must be displayed on screen
   * </ul>
   *
   * @param inputDevice source input device of the click. Example: {@link InputDevice#SOURCE_MOUSE}
   * @param buttonState buttonState associated with the click. Example: {@link
   *     MotionEvent#BUTTON_PRIMARY}
   */
  public static ViewAction click(int inputDevice, int buttonState) {
    return actionWithAssertions(
        new GeneralClickAction(
            Tap.SINGLE, GeneralLocation.VISIBLE_CENTER, Press.FINGER, inputDevice, buttonState));
  }

  /**
   * Same as {@code click(int inputDevice, int buttonState)}, but uses {@link
   * InputDevice#SOURCE_UNKNOWN} as the inputDevice and {@link MotionEvent#BUTTON_PRIMARY} as the
   * buttonState.
   */
  public static ViewAction click() {
    return actionWithAssertions(
        new GeneralClickAction(
            Tap.SINGLE,
            GeneralLocation.VISIBLE_CENTER,
            Press.FINGER,
            InputDevice.SOURCE_UNKNOWN,
            MotionEvent.BUTTON_PRIMARY));
  }

  /**
   * Returns an action that performs a single click on the view.
   *
   * <p>If the click takes longer than the 'long press' duration (which is possible) the provided
   * rollback action is invoked on the view and a click is attempted again.
   *
   * <p>This is only necessary if the view being clicked on has some different behaviour for long
   * press versus a normal tap.
   *
   * <p>For example - if a long press on a particular view element opens a popup menu -
   * ViewActions.pressBack() may be an acceptable rollback action. <br>
   * View constraints:
   *
   * <ul>
   *   <li>must be displayed on screen
   *   <li>any constraints of the rollbackAction
   * </ul>
   */
  public static ViewAction click(ViewAction rollbackAction) {
    checkNotNull(rollbackAction);
    return actionWithAssertions(
        new GeneralClickAction(
            Tap.SINGLE,
            GeneralLocation.CENTER,
            Press.FINGER,
            InputDevice.SOURCE_UNKNOWN,
            MotionEvent.BUTTON_PRIMARY,
            rollbackAction));
  }

  /**
   * Returns an action that performs a fast swipe right-to-left across the vertical center of the
   * view. {@link #slowSwipeLeft()} should be used instead if a slow deliberate swipe is needed
   * (e.g. to avoid fling). The swipe doesn't start at the very edge of the view, but is a bit
   * offset.<br>
   * <br>
   * View constraints:
   *
   * <ul>
   *   <li>must be displayed on screen
   * </ul>
   */
  public static ViewAction swipeLeft() {
    return actionWithAssertions(
        new GeneralSwipeAction(
            Swipe.FAST,
            GeneralLocation.translate(GeneralLocation.CENTER_RIGHT, -EDGE_FUZZ_FACTOR, 0),
            GeneralLocation.CENTER_LEFT,
            Press.FINGER));
  }

  /**
   * Similar to {@link #swipeLeft()} but performs a slow and deliberate swipe instead. This is
   * useful, for example, to avoid fling. <br>
   * <br>
   * View constraints:
   *
   * <ul>
   *   <li>must be displayed on screen
   * </ul>
   */
  public static ViewAction slowSwipeLeft() {
    return actionWithAssertions(
        new GeneralSwipeAction(
            Swipe.SLOW,
            GeneralLocation.translate(GeneralLocation.CENTER_RIGHT, -EDGE_FUZZ_FACTOR, 0),
            GeneralLocation.CENTER_LEFT,
            Press.FINGER));
  }

  /**
   * Returns an action that performs a swipe left-to-right across the vertical center of the view.
   * The swipe doesn't start at the very edge of the view, but is a bit offset.<br>
   * <br>
   * View constraints:
   *
   * <ul>
   *   <li>must be displayed on screen
   * </ul>
   */
  public static ViewAction swipeRight() {
    return actionWithAssertions(
        new GeneralSwipeAction(
            Swipe.FAST,
            GeneralLocation.translate(GeneralLocation.CENTER_LEFT, EDGE_FUZZ_FACTOR, 0),
            GeneralLocation.CENTER_RIGHT,
            Press.FINGER));
  }

  /**
   * Returns an action that performs a swipe top-to-bottom across the horizontal center of the view.
   * The swipe doesn't start at the very edge of the view, but has a bit of offset.<br>
   * <br>
   * View constraints:
   *
   * <ul>
   *   <li>must be displayed on screen
   * </ul>
   */
  public static ViewAction swipeDown() {
    return actionWithAssertions(
        new GeneralSwipeAction(
            Swipe.FAST,
            GeneralLocation.translate(GeneralLocation.TOP_CENTER, 0, EDGE_FUZZ_FACTOR),
            GeneralLocation.BOTTOM_CENTER,
            Press.FINGER));
  }

  /**
   * Returns an action that performs a swipe bottom-to-top across the horizontal center of the view.
   * The swipe doesn't start at the very edge of the view, but has a bit of offset.<br>
   * <br>
   * View constraints:
   *
   * <ul>
   *   <li>must be displayed on screen
   * </ul>
   */
  public static ViewAction swipeUp() {
    return actionWithAssertions(
        new GeneralSwipeAction(
            Swipe.FAST,
            GeneralLocation.translate(GeneralLocation.BOTTOM_CENTER, 0, -EDGE_FUZZ_FACTOR),
            GeneralLocation.TOP_CENTER,
            Press.FINGER));
  }

  /**
   * Returns an action that closes soft keyboard. If the keyboard is already closed, it is a no-op.
   */
  public static ViewAction closeSoftKeyboard() {
    return actionWithAssertions(new CloseKeyboardAction());
  }

  /**
   * Returns an action that presses the current action button (next, done, search, etc) on the IME
   * (Input Method Editor). The selected view will have its onEditorAction method called.
   */
  public static ViewAction pressImeActionButton() {
    return actionWithAssertions(new EditorAction());
  }

  /**
   * Returns an action that clicks the back button.
   *
   * @throws PerformException if Espresso navigates outside the application or process under test.
   */
  public static ViewAction pressBack() {
    return actionWithAssertions(new PressBackAction(true));
  }

  /**
   * Similar to {@link #pressBack()} but will <b>not</b> throw an exception when Espresso navigates
   * outside the application or process under test.
   */
  public static ViewAction pressBackUnconditionally() {
    return actionWithAssertions(new PressBackAction(false));
  }

  /** Returns an action that presses the hardware menu key. */
  public static ViewAction pressMenuKey() {
    return pressKey(KeyEvent.KEYCODE_MENU);
  }

  /**
   * Returns an action that presses the key specified by the keyCode (eg. Keyevent.KEYCODE_BACK).
   */
  public static ViewAction pressKey(int keyCode) {
    return actionWithAssertions(
        new KeyEventAction(new EspressoKey.Builder().withKeyCode(keyCode).build()));
  }

  /** Returns an action that presses the specified key with the specified modifiers. */
  public static ViewAction pressKey(EspressoKey key) {
    return actionWithAssertions(new KeyEventAction(key));
  }

  /**
   * Returns an action that double clicks the view.<br>
   * <br>
   * View preconditions:
   *
   * <ul>
   *   <li>must be displayed on screen
   * </ul>
   */
  public static ViewAction doubleClick() {
    return actionWithAssertions(
        new GeneralClickAction(
            Tap.DOUBLE,
            GeneralLocation.CENTER,
            Press.FINGER,
            InputDevice.SOURCE_UNKNOWN,
            MotionEvent.BUTTON_PRIMARY));
  }

  /**
   * Returns an action that long clicks the view.<br>
   * <br>
   * View preconditions:
   *
   * <ul>
   *   <li>must be displayed on screen
   * </ul>
   */
  public static ViewAction longClick() {
    return actionWithAssertions(
        new GeneralClickAction(
            Tap.LONG,
            GeneralLocation.CENTER,
            Press.FINGER,
            InputDevice.SOURCE_UNKNOWN,
            MotionEvent.BUTTON_PRIMARY));
  }

  /**
   * Returns an action that scrolls to the view.<br>
   * <br>
   * View preconditions:
   *
   * <ul>
   *   <li>must be a descendant of ScrollView
   *   <li>must have visibility set to View.VISIBLE
   * </ul>
   */
  public static ViewAction scrollTo() {
    return actionWithAssertions(new ScrollToAction());
  }

  /**
   * Returns an action that scrolls to the view.<br>
   * <br>
   * In order for the scroll to be considered to have succeeded, the target view must match {@link
   * androidx.test.espresso.matcher.ViewMatchers#isDisplayingAtLeast(int)} for the specified value.
   * <br>
   * <br>
   * View preconditions:
   *
   * <ul>
   *   <li>must be a descendant of ScrollView
   *   <li>must have visibility set to View.VISIBLE
   * </ul>
   */
  public static ViewAction scrollTo(int isDisplayingAtLeastThreshold) {
    return actionWithAssertions(new ScrollToAction(isDisplayingAtLeastThreshold));
  }

  /**
   * Returns an action that scrolls to the view.<br>
   * <br>
   * In order for the scroll to be considered to have succeeded, the target view must match {@link
   * androidx.test.espresso.matcher.ViewMatchers#isDisplayingAtLeast()} for the specified value.
   * <br>
   * View preconditions:
   *
   * <ul>
   *   <li>must be a descendant of ScrollView
   *   <li>must have visibility set to View.VISIBLE
   * </ul>
   */
  public static ViewAction scrollCompletelyTo() {
    return scrollTo(100);
  }

  /**
   * Returns an action that types the provided string into the view. Appending a \n to the end of
   * the string translates to a ENTER key event. Note: this method does not change cursor position
   * in the focused view - text is inserted at the location where the cursor is currently pointed.
   * <br>
   * <br>
   * View preconditions:
   *
   * <ul>
   *   <li>must be displayed on screen
   *   <li>must support input methods
   *   <li>must be already focused
   * </ul>
   */
  public static ViewAction typeTextIntoFocusedView(String stringToBeTyped) {
    return actionWithAssertions(new TypeTextAction(stringToBeTyped, false /* tapToFocus */));
  }

  /**
   * Returns an action that selects the view (by clicking on it) and types the provided string into
   * the view. Appending a \n to the end of the string translates to a ENTER key event. Note: this
   * method performs a tap on the view before typing to force the view into focus, if the view
   * already contains text this tap may place the cursor at an arbitrary position within the text.
   * <br>
   * <br>
   * View preconditions:
   *
   * <ul>
   *   <li>must be displayed on screen
   *   <li>must support input methods
   * </ul>
   */
  public static ViewAction typeText(String stringToBeTyped) {
    return actionWithAssertions(new TypeTextAction(stringToBeTyped));
  }

  /**
   * Returns an action that updates the text attribute of a view. <br>
   * <br>
   * View preconditions:
   *
   * <ul>
   *   <li>must be displayed on screen
   *   <li>must be assignable from EditText
   * </ul>
   */
  public static ViewAction replaceText(@NonNull String stringToBeSet) {
    return actionWithAssertions(new ReplaceTextAction(stringToBeSet));
  }

  /**
   * Same as {@code openLinkWithText(Matcher<String> linkTextMatcher)}, but uses {@code
   * is(linkText)} as the linkTextMatcher.
   */
  public static ViewAction openLinkWithText(String linkText) {
    return openLinkWithText(is(linkText));
  }

  /**
   * Same as {@code openLink(Matcher<String> linkTextMatcher, Matcher<Uri> uriMatcher)}, but uses
   * {@code any(Uri.class)} as the uriMatcher.
   */
  public static ViewAction openLinkWithText(Matcher<String> linkTextMatcher) {
    return openLink(linkTextMatcher, any(Uri.class));
  }

  /**
   * Same as {@code openLinkWithUri(Matcher<Uri> uriMatcher)}, but uses {@code is(uri)} as the
   * uriMatcher.
   */
  public static ViewAction openLinkWithUri(String uri) {
    return openLinkWithUri(is(Uri.parse(uri)));
  }

  /**
   * Same as {@code openLink(Matcher<String> linkTextMatcher, Matcher<Uri> uriMatcher)}, but uses
   * {@code any(String.class)} as the linkTextMatcher.
   */
  public static ViewAction openLinkWithUri(Matcher<Uri> uriMatcher) {
    return openLink(any(String.class), uriMatcher);
  }

  /**
   * Returns an action that opens a link matching the given link text and uri matchers. The action
   * is performed by invoking the link's onClick method (as opposed to actually issuing a click on
   * the screen). <br>
   * <br>
   * View preconditions:
   *
   * <ul>
   *   <li>must be displayed on screen
   *   <li>must be assignable from TextView
   *   <li>must have links
   * </ul>
   */
  public static ViewAction openLink(Matcher<String> linkTextMatcher, Matcher<Uri> uriMatcher) {
    checkNotNull(linkTextMatcher);
    checkNotNull(uriMatcher);
    return actionWithAssertions(new OpenLinkAction(linkTextMatcher, uriMatcher));
  }

  /**
   * Returns an action that performs given {@code ViewAction} on the view until view matches the
   * desired {@code Matcher<View>}. It will repeat the given action until view matches the desired
   * {@code Matcher<View>} or PerformException will be thrown if given number of unsuccessful
   * attempts are made.
   *
   * @param action action to be performed repeatedly
   * @param desiredStateMatcher action is performed repeatedly until view matches this view matcher
   * @param maxAttempts max number of times for which this action to be performed if view doesn't
   *     match the given view matcher
   */
  public static ViewAction repeatedlyUntil(
      final ViewAction action, final Matcher<View> desiredStateMatcher, final int maxAttempts) {
    checkNotNull(action);
    checkNotNull(desiredStateMatcher);
    return actionWithAssertions(
        new RepeatActionUntilViewState(action, desiredStateMatcher, maxAttempts));
  }

  public interface BitmapReceiver {
    void onBitmapCaptured(Bitmap bitmap);
  }

  /**
   * Returns an action that captures an image of the desired View and performs some other operation
   * on the result.
   *
   * @see androidx.test.core.view.ViewCapture.captureToBitmap
   * @param bitmapReceiver the BitmapReceiver that receives the result. This will be called on main
   *     thread.
   * @return the ViewAction
   */
  public static ViewAction captureToBitmap(BitmapReceiver bitmapReceiver) {
    return new CaptureToBitmapAction(bitmapReceiver);
  }
}