Kore/app/src/androidTest/java/org/xbmc/kore/testhelpers/action/ViewActions.java

199 lines
7.0 KiB
Java

/*
* Copyright 2016 Martijn Brekhof. All rights reserved.
*
* 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 org.xbmc.kore.testhelpers.action;
import androidx.test.espresso.PerformException;
import androidx.test.espresso.UiController;
import androidx.test.espresso.ViewAction;
import androidx.test.espresso.action.MotionEvents;
import androidx.test.espresso.action.Press;
import androidx.test.espresso.util.HumanReadables;
import androidx.test.espresso.util.TreeIterables;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import android.view.View;
import android.widget.SeekBar;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import java.util.concurrent.TimeoutException;
import static androidx.test.espresso.action.ViewActions.actionWithAssertions;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
public final class ViewActions {
/**
* Returns an action that clears the focus on the view.
* <br/>
* View constraints:
* <ul>
* <li>must be displayed on screen</li>
* </ul>
*/
public static ViewAction clearFocus() {
return actionWithAssertions(new ClearFocus());
}
/**
* Returns an action that scrolls to the view in a nested scroll view.<br>
* <br>
* View preconditions:
* <ul>
* <li>must be a descendant of NestedScrollView
* <li>must have visibility set to View.VISIBLE
* <ul></ul>
*/
public static ViewAction nestedScrollTo() {
return actionWithAssertions(new NestedScrollTo());
}
public interface CheckStatus {
boolean check(View v);
}
/**
* 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();
}
};
}
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);
}
};
}
public static ViewAction setCurrentViewPagerItem(final int pageTitleResourceId) {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return new TypeSafeMatcher<View>() {
@Override
protected boolean matchesSafely(View item) {
return item instanceof ViewPager;
}
@Override
public void describeTo(Description description) {
description.appendText("is a SeekBar.");
}
};
}
@Override
public String getDescription() {
return null;
}
@Override
public void perform(UiController uiController, View view) {
ViewPager viewPager = (ViewPager) view;
String expectedTitle = view.getResources().getString(pageTitleResourceId);
PagerAdapter pagerAdapter = viewPager.getAdapter();
for(int i = 0; i < pagerAdapter.getCount(); i++) {
if (expectedTitle.contentEquals(pagerAdapter.getPageTitle(i))) {
viewPager.setCurrentItem(i);
return;
}
}
}
};
}
}