Skip to content

Commit

Permalink
Feature/issue 95/change track slide (#96)
Browse files Browse the repository at this point in the history
Issue-95 - added swipe to change track functionality, added a mechanism to kill notifications when the app is not in use, started to work on end to end test compatibility
  • Loading branch information
goldy1992 authored Nov 8, 2019
1 parent ab94750 commit 7138c94
Show file tree
Hide file tree
Showing 68 changed files with 1,839 additions and 540 deletions.
9 changes: 7 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ dependencies {
def JUNIT_EXT_VERSION = '1.1.0'
def ROBOLECTRIC_VERSION = '4.3'
def TEST_CORE_VERSION = '1.2.0-alpha03'
def TEST_RUNNER_VERSION = '1.0.2'
def TEST_RUNNER_VERSION = '1.2.0'
def TEST_RULES_VERSION = '1.1.1'
def ESPRESSO_CORE_VERSION = '3.1.0'
def ESPRESSO_CORE_VERSION = '3.2.0'
def GOOGLE_GUAVA_VERSION = '27.1-android'
def COORDINATOR_LAYOUT_VERSION = '1.0.0'
def TEST_UI_AUTOMATOR_VERSION= '2.2.0'
Expand Down Expand Up @@ -153,6 +153,7 @@ dependencies {
implementation group: 'androidx.room', name: 'room-runtime', version: ROOM_VERSION
annotationProcessor group: 'androidx.room', name: 'room-compiler', version: ROOM_VERSION

implementation 'androidx.viewpager2:viewpager2:1.0.0-rc01'
// added to remove compile time warning
testAnnotationProcessor group: 'com.google.auto.service', name: 'auto-service', version: '1.0-rc4'

Expand Down Expand Up @@ -195,6 +196,10 @@ dependencies {
androidTestImplementation group: 'androidx.test.ext', name: 'junit', version: JUNIT_EXT_VERSION
androidTestImplementation group: 'androidx.test', name: 'rules', version: TEST_RULES_VERSION
androidTestImplementation group: 'androidx.test', name: 'runner', version: TEST_RUNNER_VERSION
androidTestImplementation group: 'androidx.test.espresso', name: 'espresso-contrib', version: ESPRESSO_CORE_VERSION

automationImplementation group: 'androidx.test', name: 'rules', version: TEST_RULES_VERSION
automationImplementation group: 'androidx.test.espresso', name: 'espresso-core', version: ESPRESSO_CORE_VERSION

androidTestImplementation(group: 'androidx.test.espresso', name: 'espresso-core', version: ESPRESSO_CORE_VERSION) {
exclude module: "support-annotations"
Expand Down
14 changes: 0 additions & 14 deletions app/src/androidTest/AndroidManifest.xml

This file was deleted.

103 changes: 71 additions & 32 deletions app/src/androidTest/java/com/example/mike/mp3player/EndToEndTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,98 @@
import android.view.ViewGroup;
import android.view.ViewParent;

import androidx.test.espresso.Espresso;
import androidx.test.espresso.IdlingRegistry;
import androidx.test.espresso.IdlingResource;
import androidx.test.espresso.matcher.ViewMatchers;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.rule.GrantPermissionRule;

import com.example.mike.mp3player.client.activities.SplashScreenEntryActivity;
import com.example.mike.mp3player.client.activities.MainActivity;
import com.example.mike.mp3player.client.activities.MainActivityInjectorAndroidTestImpl;
import com.example.mike.mp3player.commons.MediaItemType;
import com.google.android.material.tabs.TabLayout;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static com.example.mike.mp3player.TestUtils.assertTabName;
import static com.example.mike.mp3player.TestUtils.withRecyclerView;
import static org.hamcrest.core.AllOf.allOf;
import static org.junit.Assert.assertEquals;

@LargeTest
@RunWith(androidx.test.ext.junit.runners.AndroidJUnit4.class)
public class EndToEndTest {

IdlingResource idlingResource;
@Rule
public ActivityTestRule<SplashScreenEntryActivity> mActivityTestRule = new ActivityTestRule<>(SplashScreenEntryActivity.class);
public ActivityTestRule<MainActivityInjectorAndroidTestImpl> mActivityTestRule = new ActivityTestRule<>(MainActivityInjectorAndroidTestImpl.class);

@Rule
public GrantPermissionRule mGrantPermissionRule =
GrantPermissionRule.grant(
"android.permission.WRITE_EXTERNAL_STORAGE");
// TODO: rewrite test
// @Test
// public void splashScreenEntryActivityTest() {
// ViewInteraction textView = onView(
// allOf(withText("Songs"),
// childAtPosition(
// allOf(withId(R.id.pagerTabStrip),
// withParent(withId(R.id.rootItemsPager))),
// 1),
// isDisplayed()));
// textView.check(matches(withText("Songs")));
//
// ViewInteraction textView2 = onView(
// allOf(withText("Folders"),
// childAtPosition(
// allOf(withId(R.id.pagerTabStrip),
// withParent(withId(R.id.rootItemsPager))),
// 2),
// isDisplayed()));
// textView2.check(matches(withText("Folders")));
//
// ViewInteraction textView3 = onView(
// allOf(withText("Folders"),
// childAtPosition(
// allOf(withId(R.id.pagerTabStrip),
// withParent(withId(R.id.rootItemsPager))),
// 2),
// isDisplayed()));
// textView3.perform(click());
// }

@Before
public void setup() {
this.idlingResource = mActivityTestRule.getActivity();
IdlingRegistry.getInstance().register(idlingResource);
}

@After
public void tearDown() {
IdlingRegistry.getInstance().unregister(idlingResource);
}

@Test
public void splashScreenEntryActivityTest() {
Espresso.onIdle();
MainActivity mainActivity = mActivityTestRule.getActivity();
TabLayout tabLayout = mainActivity.findViewById(R.id.tabs);

final int expectedTabCount = 2;
final int actualTabCount = tabLayout.getTabCount();
assertEquals(expectedTabCount, actualTabCount);

assertTabName(tabLayout, 0, MediaItemType.SONGS.getTitle());
assertTabName(tabLayout, 1, MediaItemType.FOLDERS.getTitle());

onView(allOf(
withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE),
withId(R.id.recycler_view)))
.check(matches(isDisplayed()));

onView(withRecyclerView(R.id.recycler_view)
.atPositionOnView(0, R.id.title))
.check(matches(withText("#Dprimera")))

.perform(scrollToPosition(14));


onView(withRecyclerView(R.id.recycler_view)
.atPositionOnView(14, R.id.title))
.check(matches(withText("Yuya")));





}

private static Matcher<View> childAtPosition(
final Matcher<View> parentMatcher, final int position) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.example.mike.mp3player;


import android.content.res.Resources;
import android.view.View;

import androidx.recyclerview.widget.RecyclerView;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

/**
* Created by dannyroa on 5/10/15.
*/
public class RecyclerViewMatcher {
private final int recyclerViewId;

public RecyclerViewMatcher(int recyclerViewId) {
this.recyclerViewId = recyclerViewId;
}

public Matcher<View> atPosition(final int position) {
return atPositionOnView(position, -1);
}

public Matcher<View> atPositionOnView(final int position, final int targetViewId) {

return new TypeSafeMatcher<View>() {
Resources resources = null;
View childView;

public void describeTo(Description description) {
String idDescription = Integer.toString(recyclerViewId);
if (this.resources != null) {
try {
idDescription = this.resources.getResourceName(recyclerViewId);
} catch (Resources.NotFoundException var4) {
idDescription = String.format("%s (resource name not found)",
new Object[] { Integer.valueOf
(recyclerViewId) });
}
}

description.appendText("with id: " + idDescription);
}

public boolean matchesSafely(View view) {

this.resources = view.getResources();

if (childView == null) {
RecyclerView recyclerView =
(RecyclerView) view.getRootView().findViewById(recyclerViewId);
if (recyclerView != null && recyclerView.getId() == recyclerViewId) {
childView = recyclerView.findViewHolderForAdapterPosition(position).itemView;
} else {
return false;
}
}

if (targetViewId == -1) {
return view == childView;
} else {
View targetView = childView.findViewById(targetViewId);
return view == targetView;
}

}
};
}
}
118 changes: 117 additions & 1 deletion app/src/androidTest/java/com/example/mike/mp3player/TestUtils.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,125 @@
package com.example.mike.mp3player;

import android.view.View;

import androidx.annotation.IdRes;
import androidx.recyclerview.widget.RecyclerView;
import androidx.test.espresso.PerformException;
import androidx.test.espresso.UiController;
import androidx.test.espresso.ViewAction;
import androidx.test.espresso.matcher.ViewMatchers;
import androidx.test.espresso.util.HumanReadables;

import com.google.android.material.tabs.TabLayout;

import org.hamcrest.Matcher;
import org.hamcrest.Matchers;

import static org.junit.Assert.assertEquals;

/**
* This class will be used for utility methods in the automation framework.
*/
public final class TestUtils {
public class TestUtils {

public static void assertTabName(TabLayout tabLayout, int position, String expectedTabTitle) {
TabLayout.Tab tab = tabLayout.getTabAt(position);
final String actualNameFirstTab = tab.getText().toString();
assertEquals(expectedTabTitle, actualNameFirstTab);
}




// RECYCLER VIEW
public static <VH extends RecyclerView.ViewHolder> ViewAction actionOnItemViewAtPosition(int position,
@IdRes
int viewId,
ViewAction viewAction) {
return new ActionOnItemViewAtPositionViewAction(position, viewId, viewAction);
}

private static final class ActionOnItemViewAtPositionViewAction<VH extends RecyclerView
.ViewHolder>
implements

ViewAction {
private final int position;
private final ViewAction viewAction;
private final int viewId;

private ActionOnItemViewAtPositionViewAction(int position,
@IdRes int viewId,
ViewAction viewAction) {
this.position = position;
this.viewAction = viewAction;
this.viewId = viewId;
}

public Matcher<View> getConstraints() {
return Matchers.allOf(new Matcher[] {
ViewMatchers.isAssignableFrom(RecyclerView.class), ViewMatchers.isDisplayed()
});
}

public String getDescription() {
return "actionOnItemAtPosition performing ViewAction: "
+ this.viewAction.getDescription()
+ " on item at position: "
+ this.position;
}

public void perform(UiController uiController, View view) {
RecyclerView recyclerView = (RecyclerView) view;
(new ScrollToPositionViewAction(this.position)).perform(uiController, view);
uiController.loopMainThreadUntilIdle();

View targetView = recyclerView.getChildAt(this.position).findViewById(this.viewId);

if (targetView == null) {
throw (new PerformException.Builder()).withActionDescription(this.toString())
.withViewDescription(

HumanReadables.describe(view))
.withCause(new IllegalStateException(
"No view with id "
+ this.viewId
+ " found at position: "
+ this.position))
.build();
} else {
this.viewAction.perform(uiController, targetView);
}
}
}

private static final class ScrollToPositionViewAction implements ViewAction {
private final int position;

private ScrollToPositionViewAction(int position) {
this.position = position;
}

public Matcher<View> getConstraints() {
return Matchers.allOf(new Matcher[] {
ViewMatchers.isAssignableFrom(RecyclerView.class), ViewMatchers.isDisplayed()
});
}

public String getDescription() {
return "scroll RecyclerView to position: " + this.position;
}

public void perform(UiController uiController, View view) {
RecyclerView recyclerView = (RecyclerView) view;
recyclerView.scrollToPosition(this.position);
}
}


public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) {

return new RecyclerViewMatcher(recyclerViewId);
}

}
Loading

0 comments on commit 7138c94

Please sign in to comment.