forked from upstream-mirrors/OpenTracks
Improve clicking behaviour
This commit is contained in:
committed by
mmarca.tech
parent
40494557d4
commit
b679f00cc5
@@ -2,20 +2,22 @@ package de.dennisguse.opentracks;
|
|||||||
|
|
||||||
|
|
||||||
import static androidx.test.espresso.Espresso.onView;
|
import static androidx.test.espresso.Espresso.onView;
|
||||||
import static androidx.test.espresso.action.ViewActions.click;
|
|
||||||
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
||||||
import static androidx.test.espresso.action.ViewActions.longClick;
|
|
||||||
import static androidx.test.espresso.action.ViewActions.replaceText;
|
import static androidx.test.espresso.action.ViewActions.replaceText;
|
||||||
import static androidx.test.espresso.action.ViewActions.scrollTo;
|
import static androidx.test.espresso.action.ViewActions.scrollTo;
|
||||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA;
|
import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
|
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||||
|
import static androidx.test.espresso.matcher.RootMatchers.isDialog;
|
||||||
|
import static androidx.test.espresso.matcher.RootMatchers.isPlatformPopup;
|
||||||
import static de.dennisguse.opentracks.util.ActivityTestUtils.waitForResumedActivity;
|
import static de.dennisguse.opentracks.util.ActivityTestUtils.waitForResumedActivity;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitForView;
|
import static de.dennisguse.opentracks.util.EspressoUtils.performClick;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.performClickOnAncestor;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.performLongClick;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.performLongClickOnAncestor;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedView;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedView;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedViewCondition;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedViewCondition;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.withRecyclerViewItemCount;
|
import static de.dennisguse.opentracks.util.EspressoUtils.withRecyclerViewItemCount;
|
||||||
@@ -66,11 +68,10 @@ public class EspressoDeleteTrackTest {
|
|||||||
|
|
||||||
// TrackStoppedActivity: discard the just-recorded track directly
|
// TrackStoppedActivity: discard the just-recorded track directly
|
||||||
onView(withId(R.id.discard_button))
|
onView(withId(R.id.discard_button))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitUntilDisplayedInCurrentRoot(withText(android.R.string.ok));
|
|
||||||
|
|
||||||
onView(withText(android.R.string.ok))
|
onView(withText(android.R.string.ok))
|
||||||
.perform(click());
|
.inRoot(isDialog())
|
||||||
|
.perform(performClick());
|
||||||
waitForResumedActivity(TrackListActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackListActivity.class, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_list));
|
waitUntilDisplayed(withId(R.id.track_list));
|
||||||
waitUntilRecyclerViewItemCount(withId(R.id.track_list), 0);
|
waitUntilRecyclerViewItemCount(withId(R.id.track_list), 0);
|
||||||
@@ -89,20 +90,19 @@ public class EspressoDeleteTrackTest {
|
|||||||
.perform(scrollTo(), replaceText(uniqueTrackName), closeSoftKeyboard());
|
.perform(scrollTo(), replaceText(uniqueTrackName), closeSoftKeyboard());
|
||||||
|
|
||||||
onView(withId(R.id.finish_button))
|
onView(withId(R.id.finish_button))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitForResumedActivity(TrackListActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackListActivity.class, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_list));
|
waitUntilDisplayed(withId(R.id.track_list));
|
||||||
waitUntilDisplayed(allOf(withId(R.id.track_list_item_name), withText(uniqueTrackName)));
|
waitUntilDisplayed(allOf(withId(R.id.track_list_item_name), withText(uniqueTrackName)));
|
||||||
waitUntilRecyclerViewItemCount(withId(R.id.track_list), 1);
|
waitUntilRecyclerViewItemCount(withId(R.id.track_list), 1);
|
||||||
|
|
||||||
onView(allOf(withId(R.id.track_list_item_name), withText(uniqueTrackName)))
|
onView(allOf(withId(R.id.track_list_item_name), withText(uniqueTrackName)))
|
||||||
.perform(longClick());
|
.perform(performLongClickOnAncestor());
|
||||||
|
|
||||||
clickDeleteSelectedTrackAction();
|
clickDeleteSelectedTrackAction();
|
||||||
waitUntilDisplayedInCurrentRoot(withText(android.R.string.ok));
|
|
||||||
|
|
||||||
onView(withText(android.R.string.ok))
|
onView(withText(android.R.string.ok))
|
||||||
.perform(click());
|
.inRoot(isDialog())
|
||||||
|
.perform(performClick());
|
||||||
waitUntilRecyclerViewItemCount(withId(R.id.track_list), 0);
|
waitUntilRecyclerViewItemCount(withId(R.id.track_list), 0);
|
||||||
|
|
||||||
onView(withId(R.id.track_list))
|
onView(withId(R.id.track_list))
|
||||||
@@ -112,14 +112,14 @@ public class EspressoDeleteTrackTest {
|
|||||||
private void recordTrackAndOpenTrackStoppedActivity() {
|
private void recordTrackAndOpenTrackStoppedActivity() {
|
||||||
// TrackListActivity: start recording
|
// TrackListActivity: start recording
|
||||||
onView(withId(R.id.track_list_fab_action))
|
onView(withId(R.id.track_list_fab_action))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
||||||
waitForRecordingState(true, UI_TIMEOUT);
|
waitForRecordingState(true, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
||||||
|
|
||||||
// TrackRecordingActivity: stop recording and open TrackStoppedActivity
|
// TrackRecordingActivity: stop recording and open TrackStoppedActivity
|
||||||
onView(withId(R.id.track_recording_fab_action))
|
onView(withId(R.id.track_recording_fab_action))
|
||||||
.perform(longClick());
|
.perform(performLongClick());
|
||||||
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_edit_name));
|
waitUntilDisplayed(withId(R.id.track_edit_name));
|
||||||
waitUntilDisplayed(withId(R.id.discard_button));
|
waitUntilDisplayed(withId(R.id.discard_button));
|
||||||
@@ -132,15 +132,15 @@ public class EspressoDeleteTrackTest {
|
|||||||
try {
|
try {
|
||||||
waitUntilDisplayed(withId(R.id.list_context_menu_delete));
|
waitUntilDisplayed(withId(R.id.list_context_menu_delete));
|
||||||
onView(withId(R.id.list_context_menu_delete))
|
onView(withId(R.id.list_context_menu_delete))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
} catch (AssertionError ignored) {
|
} catch (AssertionError ignored) {
|
||||||
onView(allOf(
|
onView(allOf(
|
||||||
withContentDescription(androidx.appcompat.R.string.abc_action_menu_overflow_description),
|
withContentDescription(androidx.appcompat.R.string.abc_action_menu_overflow_description),
|
||||||
isDescendantOfA(withId(androidx.appcompat.R.id.action_mode_bar))))
|
isDescendantOfA(withId(androidx.appcompat.R.id.action_mode_bar))))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitUntilDisplayedInCurrentRoot(withText(R.string.menu_delete));
|
|
||||||
onView(withText(R.string.menu_delete))
|
onView(withText(R.string.menu_delete))
|
||||||
.perform(click());
|
.inRoot(isPlatformPopup())
|
||||||
|
.perform(performClickOnAncestor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,10 +148,6 @@ public class EspressoDeleteTrackTest {
|
|||||||
waitForResumedView(allOf(viewMatcher, isDisplayed()), UI_TIMEOUT);
|
waitForResumedView(allOf(viewMatcher, isDisplayed()), UI_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitUntilDisplayedInCurrentRoot(Matcher<View> viewMatcher) {
|
|
||||||
onView(isRoot()).perform(waitForView(allOf(viewMatcher, isDisplayed()), UI_TIMEOUT));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void waitUntilRecyclerViewItemCount(Matcher<View> viewMatcher, int expectedCount) {
|
private void waitUntilRecyclerViewItemCount(Matcher<View> viewMatcher, int expectedCount) {
|
||||||
waitForResumedViewCondition(
|
waitForResumedViewCondition(
|
||||||
viewMatcher,
|
viewMatcher,
|
||||||
|
|||||||
@@ -2,18 +2,20 @@ package de.dennisguse.opentracks;
|
|||||||
|
|
||||||
|
|
||||||
import static androidx.test.espresso.Espresso.onView;
|
import static androidx.test.espresso.Espresso.onView;
|
||||||
import static androidx.test.espresso.Espresso.openContextualActionModeOverflowMenu;
|
|
||||||
import static androidx.test.espresso.action.ViewActions.click;
|
|
||||||
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
||||||
import static androidx.test.espresso.action.ViewActions.longClick;
|
|
||||||
import static androidx.test.espresso.action.ViewActions.replaceText;
|
import static androidx.test.espresso.action.ViewActions.replaceText;
|
||||||
import static androidx.test.espresso.action.ViewActions.scrollTo;
|
import static androidx.test.espresso.action.ViewActions.scrollTo;
|
||||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||||
|
import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
||||||
|
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||||
import static de.dennisguse.opentracks.util.ActivityTestUtils.waitForResumedActivity;
|
import static de.dennisguse.opentracks.util.ActivityTestUtils.waitForResumedActivity;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.performClick;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.performClickOnAncestor;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.performLongClick;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitForView;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitForView;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedView;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedView;
|
||||||
import static de.dennisguse.opentracks.util.TrackRecordingServiceTestUtils.waitForRecordingState;
|
import static de.dennisguse.opentracks.util.TrackRecordingServiceTestUtils.waitForRecordingState;
|
||||||
@@ -67,7 +69,7 @@ public class EspressoEditTrackRecordingTest {
|
|||||||
{
|
{
|
||||||
// TrackListActivity: start recording
|
// TrackListActivity: start recording
|
||||||
onView(withId(R.id.track_list_fab_action))
|
onView(withId(R.id.track_list_fab_action))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
||||||
waitForRecordingState(true, UI_TIMEOUT);
|
waitForRecordingState(true, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
||||||
@@ -76,12 +78,15 @@ public class EspressoEditTrackRecordingTest {
|
|||||||
// TrackRecordingActivity
|
// TrackRecordingActivity
|
||||||
|
|
||||||
// open menu
|
// open menu
|
||||||
openContextualActionModeOverflowMenu();
|
onView(allOf(
|
||||||
|
withContentDescription(androidx.appcompat.R.string.abc_action_menu_overflow_description),
|
||||||
|
isDescendantOfA(withId(R.id.bottom_app_bar))))
|
||||||
|
.perform(performClick());
|
||||||
waitUntilDisplayedInCurrentRoot(withText(R.string.menu_edit));
|
waitUntilDisplayedInCurrentRoot(withText(R.string.menu_edit));
|
||||||
|
|
||||||
// Click the item.
|
// Click the item.
|
||||||
onView(withText(R.string.menu_edit))
|
onView(withText(R.string.menu_edit))
|
||||||
.perform(click());
|
.perform(performClickOnAncestor());
|
||||||
waitUntilDisplayed(withId(R.id.track_edit_name));
|
waitUntilDisplayed(withId(R.id.track_edit_name));
|
||||||
|
|
||||||
// change name for "New Name"
|
// change name for "New Name"
|
||||||
@@ -93,12 +98,12 @@ public class EspressoEditTrackRecordingTest {
|
|||||||
|
|
||||||
// save edition
|
// save edition
|
||||||
onView(withId(R.id.track_edit_save))
|
onView(withId(R.id.track_edit_save))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
||||||
|
|
||||||
// stop;
|
// stop;
|
||||||
onView(withId(R.id.track_recording_fab_action))
|
onView(withId(R.id.track_recording_fab_action))
|
||||||
.perform(longClick());
|
.perform(performLongClick());
|
||||||
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.resume_button));
|
waitUntilDisplayed(withId(R.id.resume_button));
|
||||||
waitUntilDisplayed(withId(R.id.finish_button));
|
waitUntilDisplayed(withId(R.id.finish_button));
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package de.dennisguse.opentracks;
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
import static androidx.test.espresso.Espresso.onView;
|
import static androidx.test.espresso.Espresso.onView;
|
||||||
import static androidx.test.espresso.action.ViewActions.click;
|
|
||||||
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
|
||||||
import static androidx.test.espresso.action.ViewActions.longClick;
|
|
||||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isClickable;
|
import static androidx.test.espresso.matcher.ViewMatchers.isClickable;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||||
import static de.dennisguse.opentracks.util.ActivityTestUtils.waitForResumedActivity;
|
import static de.dennisguse.opentracks.util.ActivityTestUtils.waitForResumedActivity;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.performClick;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.performLongClick;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.performLongClickOnAncestor;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.selectTabAtIndex;
|
import static de.dennisguse.opentracks.util.EspressoUtils.selectTabAtIndex;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedView;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedView;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedViewCondition;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedViewCondition;
|
||||||
@@ -34,6 +35,7 @@ import org.hamcrest.Matcher;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.RuleChain;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
@@ -50,11 +52,12 @@ public class EspressoUITest {
|
|||||||
|
|
||||||
private static final Duration UI_TIMEOUT = Duration.ofSeconds(10);
|
private static final Duration UI_TIMEOUT = Duration.ofSeconds(10);
|
||||||
|
|
||||||
@Rule
|
private final ActivityScenarioRule<TrackListActivity> activityRule = new ActivityScenarioRule<>(TrackListActivity.class);
|
||||||
public ActivityScenarioRule<TrackListActivity> mActivityTestRule = new ActivityScenarioRule<>(TrackListActivity.class);
|
private final GrantPermissionRule grantPermissionRule = TestUtil.createGrantPermissionRule();
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public GrantPermissionRule mGrantPermissionRule = TestUtil.createGrantPermissionRule();
|
public RuleChain rules = RuleChain.outerRule(grantPermissionRule)
|
||||||
|
.around(activityRule);
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
@@ -69,7 +72,7 @@ public class EspressoUITest {
|
|||||||
{
|
{
|
||||||
// TrackListActivity: start recording
|
// TrackListActivity: start recording
|
||||||
onView(withId(R.id.track_list_fab_action))
|
onView(withId(R.id.track_list_fab_action))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
||||||
waitForRecordingState(true, UI_TIMEOUT);
|
waitForRecordingState(true, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
||||||
@@ -77,7 +80,7 @@ public class EspressoUITest {
|
|||||||
{
|
{
|
||||||
// TrackRecordingActivity: stop
|
// TrackRecordingActivity: stop
|
||||||
onView(withId(R.id.track_recording_fab_action))
|
onView(withId(R.id.track_recording_fab_action))
|
||||||
.perform(longClick());
|
.perform(performLongClick());
|
||||||
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_edit_name));
|
waitUntilDisplayed(withId(R.id.track_edit_name));
|
||||||
waitUntilDisplayed(withId(R.id.resume_button));
|
waitUntilDisplayed(withId(R.id.resume_button));
|
||||||
@@ -86,14 +89,14 @@ public class EspressoUITest {
|
|||||||
|
|
||||||
// TrackStoppedActivity: resume
|
// TrackStoppedActivity: resume
|
||||||
onView(allOf(withId(R.id.resume_button), isClickable()))
|
onView(allOf(withId(R.id.resume_button), isClickable()))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
||||||
waitForRecordingState(true, UI_TIMEOUT);
|
waitForRecordingState(true, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
waitUntilDisplayed(withId(R.id.track_recording_fab_action));
|
||||||
|
|
||||||
// TrackRecordingActivity: stop again
|
// TrackRecordingActivity: stop again
|
||||||
onView(withId(R.id.track_recording_fab_action))
|
onView(withId(R.id.track_recording_fab_action))
|
||||||
.perform(longClick());
|
.perform(performLongClick());
|
||||||
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_edit_name));
|
waitUntilDisplayed(withId(R.id.track_edit_name));
|
||||||
waitUntilDisplayed(withId(R.id.finish_button));
|
waitUntilDisplayed(withId(R.id.finish_button));
|
||||||
@@ -102,7 +105,7 @@ public class EspressoUITest {
|
|||||||
|
|
||||||
// TrackStoppedActivity
|
// TrackStoppedActivity
|
||||||
onView(withId(R.id.finish_button))
|
onView(withId(R.id.finish_button))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitForResumedActivity(TrackListActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackListActivity.class, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_list));
|
waitUntilDisplayed(withId(R.id.track_list));
|
||||||
}
|
}
|
||||||
@@ -114,7 +117,7 @@ public class EspressoUITest {
|
|||||||
{
|
{
|
||||||
// TrackListActivity: start recording
|
// TrackListActivity: start recording
|
||||||
onView(withId(R.id.track_list_fab_action))
|
onView(withId(R.id.track_list_fab_action))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackRecordingActivity.class, UI_TIMEOUT);
|
||||||
waitForRecordingState(true, UI_TIMEOUT);
|
waitForRecordingState(true, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.track_detail_activity_tablayout));
|
waitUntilDisplayed(withId(R.id.track_detail_activity_tablayout));
|
||||||
@@ -138,7 +141,7 @@ public class EspressoUITest {
|
|||||||
|
|
||||||
// stop
|
// stop
|
||||||
onView(withId(R.id.track_recording_fab_action))
|
onView(withId(R.id.track_recording_fab_action))
|
||||||
.perform(longClick());
|
.perform(performLongClick());
|
||||||
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
waitForResumedActivity(TrackStoppedActivity.class, UI_TIMEOUT);
|
||||||
waitUntilDisplayed(withId(R.id.resume_button));
|
waitUntilDisplayed(withId(R.id.resume_button));
|
||||||
}
|
}
|
||||||
@@ -152,11 +155,12 @@ public class EspressoUITest {
|
|||||||
TrackBuilder trackBuilder = new TrackBuilder(pair.first);
|
TrackBuilder trackBuilder = new TrackBuilder(pair.first);
|
||||||
trackBuilder.setName(uniqueTrackName);
|
trackBuilder.setName(uniqueTrackName);
|
||||||
TestDataUtil.insertTrackWithLocations(new ContentProviderUtils(ApplicationProvider.getApplicationContext()), trackBuilder.getTrack(), pair.second);
|
TestDataUtil.insertTrackWithLocations(new ContentProviderUtils(ApplicationProvider.getApplicationContext()), trackBuilder.getTrack(), pair.second);
|
||||||
mActivityTestRule.getScenario().recreate();
|
activityRule.getScenario().recreate();
|
||||||
waitUntilDisplayed(allOf(withId(R.id.track_list_item_name), withText(uniqueTrackName)));
|
waitUntilDisplayed(allOf(withId(R.id.track_list_item_name), withText(uniqueTrackName)));
|
||||||
|
|
||||||
onView(withId(R.id.track_list)).check(matches(isDisplayed()));
|
onView(withId(R.id.track_list)).check(matches(isDisplayed()));
|
||||||
onView(allOf(withId(R.id.track_list_item_name), withText(uniqueTrackName))).perform(longClick());
|
onView(allOf(withId(R.id.track_list_item_name), withText(uniqueTrackName)))
|
||||||
|
.perform(performLongClickOnAncestor());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitUntilDisplayed(Matcher<View> viewMatcher) {
|
private void waitUntilDisplayed(Matcher<View> viewMatcher) {
|
||||||
|
|||||||
+26
-9
@@ -1,18 +1,21 @@
|
|||||||
package de.dennisguse.opentracks.ui.aggregatedStatistics;
|
package de.dennisguse.opentracks.ui.aggregatedStatistics;
|
||||||
|
|
||||||
import static androidx.test.espresso.Espresso.onView;
|
import static androidx.test.espresso.Espresso.onView;
|
||||||
import static androidx.test.espresso.action.ViewActions.click;
|
|
||||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||||
|
import static androidx.test.espresso.matcher.RootMatchers.isDialog;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
|
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withParent;
|
import static androidx.test.espresso.matcher.ViewMatchers.withParent;
|
||||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitForView;
|
import static de.dennisguse.opentracks.util.EspressoUtils.performClick;
|
||||||
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedView;
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedView;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.waitForResumedViewCondition;
|
||||||
|
import static de.dennisguse.opentracks.util.EspressoUtils.withRecyclerViewItemCount;
|
||||||
import static org.hamcrest.Matchers.allOf;
|
import static org.hamcrest.Matchers.allOf;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
@@ -40,6 +43,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
|
|||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.data.models.TrackBuilder;
|
import de.dennisguse.opentracks.data.models.TrackBuilder;
|
||||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
|
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -56,8 +60,11 @@ public class EspressoAggregatedFilterTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(ApplicationProvider.getApplicationContext());
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
contentProviderUtils.deleteAllTracks(ApplicationProvider.getApplicationContext());
|
context.stopService(new Intent(context, TrackRecordingService.class));
|
||||||
|
|
||||||
|
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
|
||||||
|
contentProviderUtils.deleteAllTracks(context);
|
||||||
|
|
||||||
Pair<Track, List<TrackPoint>> pair = TestDataUtil.createTrack(new Track.Id(System.currentTimeMillis()), 20);
|
Pair<Track, List<TrackPoint>> pair = TestDataUtil.createTrack(new Track.Id(System.currentTimeMillis()), 20);
|
||||||
TrackBuilder trackBuilder = new TrackBuilder(pair.first);
|
TrackBuilder trackBuilder = new TrackBuilder(pair.first);
|
||||||
@@ -69,6 +76,8 @@ public class EspressoAggregatedFilterTest {
|
|||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
context.stopService(new Intent(context, TrackRecordingService.class));
|
||||||
if (scenario != null) {
|
if (scenario != null) {
|
||||||
scenario.close();
|
scenario.close();
|
||||||
}
|
}
|
||||||
@@ -78,6 +87,8 @@ public class EspressoAggregatedFilterTest {
|
|||||||
public void espressoAggregatedFilterTest() {
|
public void espressoAggregatedFilterTest() {
|
||||||
waitUntilDisplayed(withId(R.id.bottom_app_bar));
|
waitUntilDisplayed(withId(R.id.bottom_app_bar));
|
||||||
waitUntilDisplayed(withId(R.id.aggregated_statistics_filter));
|
waitUntilDisplayed(withId(R.id.aggregated_statistics_filter));
|
||||||
|
waitUntilRecyclerViewItemCount(withId(R.id.aggregated_stats_list), 1);
|
||||||
|
waitUntilDisplayed(allOf(withId(R.id.aggregated_stats_type_label), withText(ACTIVITY_TYPE_LOCALIZED)));
|
||||||
|
|
||||||
// open FilterDialogFragment through the current bottom app bar action item
|
// open FilterDialogFragment through the current bottom app bar action item
|
||||||
onView(withId(R.id.bottom_app_bar))
|
onView(withId(R.id.bottom_app_bar))
|
||||||
@@ -85,23 +96,25 @@ public class EspressoAggregatedFilterTest {
|
|||||||
onView(withId(R.id.bottom_app_bar))
|
onView(withId(R.id.bottom_app_bar))
|
||||||
.check(matches(hasDescendant(withId(R.id.aggregated_statistics_filter))));
|
.check(matches(hasDescendant(withId(R.id.aggregated_statistics_filter))));
|
||||||
onView(withId(R.id.aggregated_statistics_filter))
|
onView(withId(R.id.aggregated_statistics_filter))
|
||||||
.perform(click());
|
.perform(performClick());
|
||||||
|
|
||||||
// check there's a checkbox with ACTIVITY_TYPE_LOCALIZED text
|
// check there's a checkbox with ACTIVITY_TYPE_LOCALIZED text
|
||||||
Matcher<View> activityTypeFilter = allOf(withId(R.id.filter_dialog_check_button), withText(ACTIVITY_TYPE_LOCALIZED),
|
Matcher<View> activityTypeFilter = allOf(withId(R.id.filter_dialog_check_button), withText(ACTIVITY_TYPE_LOCALIZED),
|
||||||
withParent(allOf(withId(R.id.filter_items),
|
withParent(allOf(withId(R.id.filter_items),
|
||||||
withParent(IsInstanceOf.instanceOf(android.view.ViewGroup.class)))),
|
withParent(IsInstanceOf.instanceOf(android.view.ViewGroup.class)))),
|
||||||
isDisplayed());
|
isDisplayed());
|
||||||
waitUntilDisplayedInCurrentRoot(activityTypeFilter);
|
|
||||||
onView(activityTypeFilter)
|
onView(activityTypeFilter)
|
||||||
|
.inRoot(isDialog())
|
||||||
.check(matches(isDisplayed()));
|
.check(matches(isDisplayed()));
|
||||||
|
|
||||||
// check there's an edit text for "from date"
|
// check there's an edit text for "from date"
|
||||||
onView(withId(R.id.filter_date_edit_text_from))
|
onView(withId(R.id.filter_date_edit_text_from))
|
||||||
|
.inRoot(isDialog())
|
||||||
.check(matches(isDisplayed()));
|
.check(matches(isDisplayed()));
|
||||||
|
|
||||||
// check there's an edit text for "to date"
|
// check there's an edit text for "to date"
|
||||||
onView(withId(R.id.filter_date_edit_text_to))
|
onView(withId(R.id.filter_date_edit_text_to))
|
||||||
|
.inRoot(isDialog())
|
||||||
.check(matches(isDisplayed()));
|
.check(matches(isDisplayed()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +122,11 @@ public class EspressoAggregatedFilterTest {
|
|||||||
waitForResumedView(allOf(viewMatcher, isDisplayed()), UI_TIMEOUT);
|
waitForResumedView(allOf(viewMatcher, isDisplayed()), UI_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitUntilDisplayedInCurrentRoot(Matcher<View> viewMatcher) {
|
private void waitUntilRecyclerViewItemCount(Matcher<View> viewMatcher, int expectedCount) {
|
||||||
onView(isRoot()).perform(waitForView(allOf(viewMatcher, isDisplayed()), UI_TIMEOUT));
|
waitForResumedViewCondition(
|
||||||
|
allOf(viewMatcher, isDisplayed()),
|
||||||
|
view -> withRecyclerViewItemCount(expectedCount).matches(view),
|
||||||
|
"RecyclerView item count to be " + expectedCount,
|
||||||
|
UI_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import android.os.SystemClock;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewParent;
|
import android.view.ViewParent;
|
||||||
|
import android.widget.AdapterView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
@@ -221,4 +222,135 @@ public class EspressoUtils {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ViewAction performClick() {
|
||||||
|
return new ViewAction() {
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "invoke View.performClick()";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Matcher<View> getConstraints() {
|
||||||
|
return isDisplayed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(UiController uiController, View view) {
|
||||||
|
if (!view.performClick()) {
|
||||||
|
throw new PerformException.Builder()
|
||||||
|
.withActionDescription(getDescription())
|
||||||
|
.withViewDescription(HumanReadables.describe(view))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
uiController.loopMainThreadUntilIdle();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ViewAction performClickOnAncestor() {
|
||||||
|
return new ViewAction() {
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "invoke performClick() on the matched view or its ancestor";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Matcher<View> getConstraints() {
|
||||||
|
return isDisplayed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(UiController uiController, View view) {
|
||||||
|
View current = view;
|
||||||
|
while (current != null) {
|
||||||
|
if (current.performClick()) {
|
||||||
|
uiController.loopMainThreadUntilIdle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewParent parent = current.getParent();
|
||||||
|
current = parent instanceof View ? (View) parent : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = view;
|
||||||
|
while (current != null) {
|
||||||
|
ViewParent parent = current.getParent();
|
||||||
|
if (parent instanceof AdapterView<?> adapterView) {
|
||||||
|
int position = adapterView.getPositionForView(current);
|
||||||
|
if (position != AdapterView.INVALID_POSITION
|
||||||
|
&& adapterView.performItemClick(current, position, adapterView.getAdapter().getItemId(position))) {
|
||||||
|
uiController.loopMainThreadUntilIdle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current = parent instanceof View ? (View) parent : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PerformException.Builder()
|
||||||
|
.withActionDescription(getDescription())
|
||||||
|
.withViewDescription(HumanReadables.describe(view))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ViewAction performLongClick() {
|
||||||
|
return new ViewAction() {
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "invoke View.performLongClick()";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Matcher<View> getConstraints() {
|
||||||
|
return isDisplayed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(UiController uiController, View view) {
|
||||||
|
if (!view.performLongClick()) {
|
||||||
|
throw new PerformException.Builder()
|
||||||
|
.withActionDescription(getDescription())
|
||||||
|
.withViewDescription(HumanReadables.describe(view))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
uiController.loopMainThreadUntilIdle();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ViewAction performLongClickOnAncestor() {
|
||||||
|
return new ViewAction() {
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "invoke performLongClick() on the matched view or its ancestor";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Matcher<View> getConstraints() {
|
||||||
|
return isDisplayed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(UiController uiController, View view) {
|
||||||
|
View current = view;
|
||||||
|
while (current != null) {
|
||||||
|
if (current.performLongClick()) {
|
||||||
|
uiController.loopMainThreadUntilIdle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewParent parent = current.getParent();
|
||||||
|
current = parent instanceof View ? (View) parent : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PerformException.Builder()
|
||||||
|
.withActionDescription(getDescription())
|
||||||
|
.withViewDescription(HumanReadables.describe(view))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user