package com.mindbodyonline.ironhide.Infrastructure.Extensions;
import android.support.test.espresso.PerformException;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.action.CoordinatesProvider;
import android.support.test.espresso.action.PrecisionDescriber;
import android.view.View;
import android.view.ViewConfiguration;
import com.mindbodyonline.ironhide.Infrastructure.Extensions.Zoomer.Status;
import org.hamcrest.Matcher;
import java.util.Arrays;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
import static android.support.test.espresso.util.HumanReadables.describe;
import static com.mindbodyonline.ironhide.Infrastructure.Extensions.Zoomer.Status.FAILURE;
import static com.mindbodyonline.ironhide.Infrastructure.Extensions.Zoomer.Status.SUCCESS;
import static java.lang.String.format;
/**
* Enables zooming across a view.
*/
public class GeneralZoomAction implements ViewAction {
/** Maximum number of times to attempt sending a zoom action. */
private static final int MAX_TRIES = 3;
/** The minimum amount of a view that must be displayed in order to zoom across it. */
private static final int VIEW_DISPLAY_PERCENTAGE = 90;
private final CoordinatesProvider[] startCoordinatesProviders;
private final CoordinatesProvider[] endCoordinatesProviders;
private final Zoomer zoomer;
private final PrecisionDescriber precisionDescriber;
public GeneralZoomAction(Zoomer zoomer,
CoordinatesProvider[] startCoordinatesProviders,
CoordinatesProvider[] endCoordinatesProviders,
PrecisionDescriber precisionDescriber) {
this.zoomer = zoomer;
this.startCoordinatesProviders = startCoordinatesProviders;
this.endCoordinatesProviders = endCoordinatesProviders;
this.precisionDescriber = precisionDescriber;
}
@Override
public Matcher<View> getConstraints() {
return isDisplayingAtLeast(VIEW_DISPLAY_PERCENTAGE);
}
@Override
public void perform(UiController uiController, View view) {
float[][] startCoordinates = new float[][]{
startCoordinatesProviders[0].calculateCoordinates(view),
startCoordinatesProviders[1].calculateCoordinates(view)
};
float[][] endCoordinates = new float[][]{
endCoordinatesProviders[0].calculateCoordinates(view),
endCoordinatesProviders[1].calculateCoordinates(view)
};
float[] precision = precisionDescriber.describePrecision();
Status status = FAILURE;
for (int tries = 0; tries < MAX_TRIES && status != SUCCESS; tries++) {
try {
status = zoomer.sendZoom(uiController, startCoordinates, endCoordinates, precision);
} catch (RuntimeException e) {
throw new PerformException.Builder()
.withActionDescription(getDescription())
.withViewDescription(describe(view))
.withCause(e)
.build();
}
// ensures that all work queued to process the zoom has been run.
uiController.loopMainThreadForAtLeast(ViewConfiguration.getPressedStateDuration());
}
if (status == FAILURE) {
String failure = format("Couldn't zoom from: %s to: %s"
+ " precision: %s. Zoomer: %s start coordinate providers: %s"
+ " precision describer: %s. Tried %s times",
Arrays.deepToString(startCoordinates), Arrays.deepToString(endCoordinates),
Arrays.toString(precision), zoomer, Arrays.toString(startCoordinatesProviders),
precisionDescriber, MAX_TRIES);
throw new PerformException.Builder()
.withActionDescription(getDescription())
.withViewDescription(describe(view))
.withCause(new RuntimeException(failure))
.build();
}
}
@Override
public String getDescription() {
return zoomer.toString().toLowerCase() + " zoom";
}
}