public final class

InteractionRequest

extends java.lang.Object

implements EspressoRemoteMessage.To<MessageLite>

 java.lang.Object

↳androidx.test.espresso.remote.InteractionRequest

Gradle dependencies

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

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

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

Androidx artifact mapping:

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

Androidx class mapping:

androidx.test.espresso.remote.InteractionRequest android.support.test.espresso.remote.InteractionRequest

Overview

Encapsulates an UiInteraction.InteractionRequestProto request. Takes care of all the proto packing and unpacking.

Summary

Methods
public <any>getRootMatcher()

Returns the associated with this InteractionRequest or null if no was set.

public ViewActiongetViewAction()

Returns the ViewAction associated with this InteractionRequest or null if no ViewAction was set.

public ViewAssertiongetViewAssertion()

Returns the ViewAssertion associated with this InteractionRequest or null if no ViewAssertion was set.

public <any>getViewMatcher()

Returns the associated with this InteractionRequest or null if no view matcher was set.

public MessageLitetoProto()

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

Methods

public MessageLite toProto()

public <any> getRootMatcher()

Returns the associated with this InteractionRequest or null if no was set.

public <any> getViewMatcher()

Returns the associated with this InteractionRequest or null if no view matcher was set.

public ViewAction getViewAction()

Returns the ViewAction associated with this InteractionRequest or null if no ViewAction was set.

public ViewAssertion getViewAssertion()

Returns the ViewAssertion associated with this InteractionRequest or null if no ViewAssertion was set.

Source

/*
 * Copyright (C) 2016 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.remote;

import static androidx.test.internal.util.Checks.checkArgument;
import static androidx.test.internal.util.Checks.checkNotNull;
import static androidx.test.internal.util.Checks.checkState;

import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.test.espresso.Root;
import androidx.test.espresso.ViewAction;
import androidx.test.espresso.ViewAssertion;
import androidx.test.espresso.proto.UiInteraction.InteractionRequestProto;
import androidx.test.espresso.proto.UiInteraction.InteractionRequestProto.ActionOrAssertionCase;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import org.hamcrest.Matcher;

/**
 * Encapsulates an {@link InteractionRequestProto} request. Takes care of all the proto packing and
 * unpacking.
 */
public final class InteractionRequest implements EspressoRemoteMessage.To<MessageLite> {

  /**
   * This field is used to create an instance of {@link InteractionRequest} from its unwrapped proto
   * message.
   */
  private static final EspressoRemoteMessage.From<InteractionRequest, InteractionRequestProto>
      FROM =
          new EspressoRemoteMessage.From<InteractionRequest, InteractionRequestProto>() {
            @Override
            public InteractionRequest fromProto(InteractionRequestProto interactionRequestProto) {
              Builder interactionRequestBuilder = new Builder();
              interactionRequestBuilder
                  .setRootMatcher(
                      TypeProtoConverters.<Matcher<Root>>anyToType(
                          interactionRequestProto.getRootMatcher()))
                  .setViewMatcher(
                      TypeProtoConverters.<Matcher<View>>anyToType(
                          interactionRequestProto.getViewMatcher()));

              int actionOrAssertionCaseNumber =
                  interactionRequestProto.getActionOrAssertionCase().getNumber();

              if (ActionOrAssertionCase.VIEW_ACTION.getNumber() == actionOrAssertionCaseNumber) {
                interactionRequestBuilder.setViewAction(
                    TypeProtoConverters.<ViewAction>anyToType(
                        interactionRequestProto.getViewAction()));
              }

              if (ActionOrAssertionCase.VIEW_ASSERTION.getNumber() == actionOrAssertionCaseNumber) {
                interactionRequestBuilder.setViewAssertion(
                    TypeProtoConverters.<ViewAssertion>anyToType(
                        interactionRequestProto.getViewAssertion()));
              }
              return interactionRequestBuilder.build();
            }
          };

  @Nullable private final Matcher<Root> rootMatcher;
  @Nullable private final Matcher<View> viewMatcher;
  @Nullable private final ViewAction viewAction;
  @Nullable private final ViewAssertion viewAssertion;

  @VisibleForTesting
  InteractionRequest(
      @Nullable Matcher<Root> rootMatcher,
      @Nullable Matcher<View> viewMatcher,
      @Nullable ViewAction viewAction,
      @Nullable ViewAssertion viewAssertion) {
    this.rootMatcher = rootMatcher;
    this.viewMatcher = viewMatcher;
    this.viewAction = viewAction;
    this.viewAssertion = viewAssertion;
  }

  private InteractionRequest(Builder builder) {
    this(builder.rootMatcher, builder.viewMatcher, builder.viewAction, builder.viewAssertion);
  }

  /** {@inheritDoc} */
  @Override
  @SuppressWarnings("unchecked") // safe covariant cast
  public MessageLite toProto() {
    try {
      InteractionRequestProto.Builder interactionRequestBuilder =
          InteractionRequestProto.newBuilder();
      interactionRequestBuilder.setRootMatcher(TypeProtoConverters.typeToAny(rootMatcher));
      if (viewMatcher != null) {
        interactionRequestBuilder.setViewMatcher(TypeProtoConverters.typeToAny(viewMatcher));
      }

      if (viewAction != null) {
        interactionRequestBuilder.setViewAction(TypeProtoConverters.typeToAny(viewAction));
      }

      if (viewAssertion != null) {
        interactionRequestBuilder.setViewAssertion(TypeProtoConverters.typeToAny(viewAssertion));
      }
      return interactionRequestBuilder.build();
    } catch (ClassCastException cce) {
      throw new RemoteProtocolException(
          "Type does not implement the EspressoRemoteMessage.TO interface", cce);
    }
  }

  /**
   * Returns the {@link Matcher<Root>} associated with this {@link InteractionRequest} or {@code
   * null} if no {@link Matcher<Root>} was set.
   */
  public Matcher<Root> getRootMatcher() {
    return rootMatcher;
  }

  /**
   * Returns the {@link Matcher<View>} associated with this {@link InteractionRequest} or {@code
   * null} if no view matcher was set.
   */
  public Matcher<View> getViewMatcher() {
    return viewMatcher;
  }

  /**
   * Returns the {@link ViewAction} associated with this {@link InteractionRequest} or {@code null}
   * if no {@link ViewAction} was set.
   */
  public ViewAction getViewAction() {
    return viewAction;
  }

  /**
   * Returns the {@link ViewAssertion} associated with this {@link InteractionRequest} or {@code
   * null} if no {@link ViewAssertion} was set.
   */
  public ViewAssertion getViewAssertion() {
    return viewAssertion;
  }

  /**
   * Creates an instance of {@link InteractionRequest} from a View matcher and action.
   */
  public static class Builder {
    private final RemoteDescriptorRegistry remoteDescriptorRegistry;
    private Matcher<Root> rootMatcher;
    private Matcher<View> viewMatcher;
    private ViewAction viewAction;
    private ViewAssertion viewAssertion;
    private byte[] interactionRequestProtoByteArray;

    /** Creates a new {@link Builder} instance. */
    public Builder() {
      remoteDescriptorRegistry = RemoteDescriptorRegistry.getInstance();
    }

    /**
     * Sets the root matcher for this {@link InteractionRequest}
     *
     * @see Root
     * @param rootMatcher the root matcher to set
     * @return fluent interface
     */
    public Builder setRootMatcher(@NonNull Matcher<Root> rootMatcher) {
      this.rootMatcher = checkNotNull(rootMatcher);
      checkArgument(
          remoteDescriptorRegistry.hasArgForInstanceType(rootMatcher.getClass()),
          "No RemoteDescriptor registered for ViewMatcher: %s",
          rootMatcher);
      return this;
    }

    /**
     * Sets the view matcher for this {@link InteractionRequest}
     *
     * @param viewMatcher the view matcher to set
     * @return fluent interface
     */
    public Builder setViewMatcher(@NonNull Matcher<View> viewMatcher) {
      this.viewMatcher = checkNotNull(viewMatcher);
      checkArgument(
          remoteDescriptorRegistry.hasArgForInstanceType(viewMatcher.getClass()),
          "No RemoteDescriptor registered for ViewMatcher: %s",
          viewMatcher);
      return this;
    }

    /**
     * Sets the {@link ViewAction} for this {@link InteractionRequest}
     *
     * @param viewAction the view action to set
     * @return fluent interface
     * @throws IllegalStateException if a {@link ViewAssertion} was already set through {@link
     *     InteractionRequest.Builder#setViewAssertion(ViewAssertion)} before. {@link
     *     InteractionRequest} supports only one of {@link ViewAction} or {@link ViewAssertion}, but
     *     not both.
     */
    public Builder setViewAction(@NonNull ViewAction viewAction) {
      this.viewAction = checkNotNull(viewAction);
      checkArgument(
          remoteDescriptorRegistry.hasArgForInstanceType(viewAction.getClass()),
          "No RemoteDescriptor registered for ViewAction: %s",
          viewAction);
      return this;
    }

    /**
     * Sets the {@link ViewAssertion} for this {@link InteractionRequest}
     *
     * @param viewAssertion the view action to set
     * @return fluent interface
     * @throws IllegalStateException if a {@link ViewAction} was already set through {@link
     *     InteractionRequest.Builder#setViewAction(ViewAction)} before. {@link InteractionRequest}
     *     supports only one of {@link ViewAction} or {@link ViewAssertion}, but not both.
     */
    public Builder setViewAssertion(@NonNull ViewAssertion viewAssertion) {
      this.viewAssertion = checkNotNull(viewAssertion);
      checkArgument(
          remoteDescriptorRegistry.hasArgForInstanceType(viewAssertion.getClass()),
          "No RemoteDescriptor registered for ViewAssertion: %s",
          viewAssertion);
      return this;
    }

    /**
     * Set the result proto as a byte array. This byte array will be parsed into an {@link
     * InteractionRequestProto}. Providing an invalid byte array will result in a {@link
     * RemoteProtocolException} when the {@link #build()} method is called!
     *
     * @param protoByteArray the proto byte array to set
     * @return fluent interface {@link Builder}
     */
    public Builder setRequestProto(@NonNull byte[] protoByteArray) {
      this.interactionRequestProtoByteArray =
          checkNotNull(protoByteArray, "protoByteArray cannot be null!");
      return this;
    }

    /**
     * Builds an {@link InteractionRequest} object.
     *
     * @return an {@link InteractionRequest} object.
     * @throws IllegalStateException when conflicting properties are set. You can either set a
     *     {@link Matcher<View>} and a {@link ViewAction} or set the proto byte array but not both.
     *     Setting all values would result in an override, therefore setting both properties will
     *     result in an exception.
     * @throws RemoteProtocolException when the provided proto byte array cannot be parsed into a
     *     protocol buffer of type {@link InteractionRequestProto}
     */
    public InteractionRequest build() {
      if (viewAction != null && viewAssertion != null) {
        throw new IllegalStateException(
            "View Action and Assertion set. Either set a View Action "
                + "or a View Assertion but not both at the same time!");
      }

      if (viewMatcher != null || viewAction != null || viewAssertion != null) {
        if (interactionRequestProtoByteArray != null) {
          throw new IllegalStateException(
              "Instances can either be create from an view matcher. "
                  + "view action and assertion or an interaction request proto byte array but not "
                  + "both!");
        }
      }

      if (interactionRequestProtoByteArray != null) {
        InteractionRequestProto interactionRequestProto;
        try {
          interactionRequestProto =
              InteractionRequestProto.parseFrom(interactionRequestProtoByteArray);
        } catch (InvalidProtocolBufferException ipbe) {
          throw new RemoteProtocolException("Cannot parse interactionResultProto", ipbe);
        }
        return InteractionRequest.FROM.fromProto(interactionRequestProto);
      }

      checkState(
          rootMatcher != null,
          "root matcher is mandatory and needs to be set using:"
              + "Builder.setRootMatcher(Matcher)");

      return new InteractionRequest(this);
    }
  }
}