Skip to content

Commit

Permalink
Bug/androidtests (#466)
Browse files Browse the repository at this point in the history
* Fixed issue with selecting tabs

* Fixed issue with switching host on other thread than UI thread

* Fixed concurrent modification exception in JSONConnectionHandlerManager

* Fixed issue with drawer not closing

* Fixes issue with running method only supported on API 21 and higher
  • Loading branch information
poisdeux authored and SyncedSynapse committed Oct 10, 2017
1 parent 108fb88 commit 9e65350
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -207,36 +207,54 @@ public void perform(UiController uiController, View view) {
return activity[0];
}

/**
* Clicks on tab that contains the text given by stringResourceId.
* If the click fails tries again after a swipe left. If the click fails
* after that try once more after swiping right two times. The first swipe right
* is performed to negate the previous swipe left.
* @param stringResourceId text displayed in Tab that should be clicked
*/
public static void clickTab(int stringResourceId) {
try {
onView(withText(stringResourceId)).perform(click());
} catch (Exception e1) {
try {
onView(withId(R.id.pager_tab_strip)).perform(swipeLeft());
onView(withText(stringResourceId)).perform(click());
} catch (Exception e2) {
onView(withId(R.id.pager_tab_strip)).perform(swipeRight());
onView(withId(R.id.pager_tab_strip)).perform(swipeRight());
onView(withText(stringResourceId)).perform(click());
}
}
}

/**
* Clicks the album tab in the music activity
*/
public static void clickAlbumsTab() {
onView(withId(R.id.pager_tab_strip)).perform(swipeLeft());
onView(withText(R.string.albums)).perform(click());
clickTab(R.string.albums);
}

/**
* Clicks the artists tab in the music activity
*/
public static void clickArtistsTab() {
onView(withId(R.id.pager_tab_strip)).perform(swipeRight());
onView(withText(R.string.artists)).perform(click());
clickTab(R.string.artists);
}

/**
* Clicks the genres tab in the music activity
*/
public static void clickGenresTab() {
onView(withId(R.id.pager_tab_strip)).perform(swipeLeft());
onView(withText(R.string.genres)).perform(click());
clickTab(R.string.genres);
}

/**
* Clicks the music videos tab in the music activity
*/
public static void clickMusicVideosTab() {
onView(withId(R.id.pager_tab_strip)).perform(swipeLeft());
onView(withText(R.string.videos)).perform(click());
clickTab(R.string.videos);
}

/**
Expand Down
66 changes: 31 additions & 35 deletions app/src/androidTest/java/org/xbmc/kore/testhelpers/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,39 @@

package org.xbmc.kore.testhelpers;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.support.annotation.IntDef;
import android.support.test.rule.ActivityTestRule;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.preference.PreferenceManager;
import android.util.Log;
import android.view.Gravity;
import android.view.View;

import org.junit.internal.runners.statements.RunAfters;
import org.xbmc.kore.R;
import org.xbmc.kore.host.HostInfo;
import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.provider.MediaProvider;
import org.xbmc.kore.testutils.Database;
import org.xbmc.kore.utils.LogUtils;

import java.lang.reflect.Method;

import static org.xbmc.kore.ui.generic.NavigationDrawerFragment.PREF_USER_LEARNED_DRAWER;

public class Utils {
private static final String TAG = LogUtils.makeLogTag(Utils.class);

private static final String ANIMATION_PERMISSION = "android.permission.SET_ANIMATION_SCALE";
private static final float DISABLED = 0.0f;
private static final float DEFAULT = 1.0f;

private static boolean isInitialized;

private static HostInfo hostInfo;
private static Context context;

public static void closeDrawer(final ActivityTestRule<?> activityTestRule) throws Throwable {
activityTestRule.runOnUiThread(new Runnable() {
public static void closeDrawer(final Activity activity) throws Throwable {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
DrawerLayout drawerLayout = (DrawerLayout) activityTestRule.getActivity().findViewById(R.id.drawer_layout);
DrawerLayout drawerLayout = (DrawerLayout) activity.findViewById(R.id.drawer_layout);
drawerLayout.closeDrawers();
}
});
Expand All @@ -73,43 +69,43 @@ public void run() {
}
}

public static void initialize(ActivityTestRule<?> activityTestRule, HostInfo info) throws Throwable {
if (isInitialized)
return;
public static void switchHost(final Context context, Activity activity, final HostInfo hostInfo) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
HostManager.getInstance(context).switchHost(hostInfo);
}
});
}

hostInfo = info;
context = activityTestRule.getActivity();
public static void clearSharedPreferences(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
editor.commit();
}

disableAnimations();
public static void setLearnedAboutDrawerPreference(Context context, boolean learned) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(PREF_USER_LEARNED_DRAWER, true);
editor.commit();
}

public static void setupMediaProvider(Context context) {
MediaProvider mediaProvider = new MediaProvider();
mediaProvider.setContext(context);
mediaProvider.onCreate();

Database.fill(hostInfo, context, context.getContentResolver());

HostManager.getInstance(context).switchHost(hostInfo);
Utils.closeDrawer(activityTestRule);

isInitialized = true;
}

public static void cleanup() {
Database.flush(context.getContentResolver(), hostInfo);

enableAnimations();

isInitialized = false;
}

private static void disableAnimations() {
public static void disableAnimations(Context context) {
int permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION);
if (permStatus == PackageManager.PERMISSION_GRANTED) {
setSystemAnimationsScale(DISABLED);
}
}

private static void enableAnimations() {
public static void enableAnimations(Context context) {
int permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION);
if (permStatus == PackageManager.PERMISSION_GRANTED) {
setSystemAnimationsScale(DEFAULT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@

package org.xbmc.kore.tests.ui;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
Expand All @@ -31,7 +33,9 @@
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.xbmc.kore.host.HostInfo;
import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.HostConnection;
import org.xbmc.kore.provider.MediaProvider;
import org.xbmc.kore.testhelpers.LoaderIdlingResource;
import org.xbmc.kore.testhelpers.Utils;
import org.xbmc.kore.testutils.Database;
Expand All @@ -58,6 +62,8 @@ abstract public class AbstractTestClass<T extends AppCompatActivity> {
private static PlayerHandler playerHandler;
private static ApplicationHandler applicationHandler;

private HostInfo hostInfo;

@BeforeClass
public static void setupMockTCPServer() throws Throwable {
playerHandler = new PlayerHandler();
Expand All @@ -75,31 +81,38 @@ public void setUp() throws Throwable {

activityTestRule = getActivityTestRule();

// final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
final Context context = activityTestRule.getActivity();

//Note: as the activity is not yet available in @BeforeClass we need
// to add the handler here
if (addonsHandler == null) {
addonsHandler = new AddonsHandler(activityTestRule.getActivity());
addonsHandler = new AddonsHandler(context);
manager.addHandler(addonsHandler);
}

HostInfo hostInfo = Database.addHost(activityTestRule.getActivity(), server.getHostName(),
HostConnection.PROTOCOL_TCP, HostInfo.DEFAULT_HTTP_PORT,
server.getPort());
hostInfo = Database.addHost(context, server.getHostName(),
HostConnection.PROTOCOL_TCP, HostInfo.DEFAULT_HTTP_PORT,
server.getPort());

Utils.initialize(activityTestRule, hostInfo);
Utils.clearSharedPreferences(context);

//Prevent drawer from opening when we start a new activity
Utils.setLearnedAboutDrawerPreference(context, true);

loaderIdlingResource = new LoaderIdlingResource(activityTestRule.getActivity().getSupportLoaderManager());
Espresso.registerIdlingResources(loaderIdlingResource);

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activityTestRule.getActivity());
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
editor.commit();
Utils.disableAnimations(context);

//Relaunch the activity for the changes (Host selections, preference reset) to take effect
activityTestRule.launchActivity(new Intent());
Utils.setupMediaProvider(context);

Utils.closeDrawer(activityTestRule);
Database.fill(hostInfo, context, context.getContentResolver());

Utils.switchHost(context, activityTestRule.getActivity(), hostInfo);

//Relaunch the activity for the changes (Host selection and database fill) to take effect
activityTestRule.launchActivity(new Intent());
}

@After
Expand All @@ -110,7 +123,9 @@ public void tearDown() throws Exception {
applicationHandler.reset();
playerHandler.reset();

Utils.cleanup();
Context context = activityTestRule.getActivity();
Database.flush(context.getContentResolver(), hostInfo);
Utils.enableAnimations(context);
}

@AfterClass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.xbmc.kore.tests.ui.addons;

import android.content.Intent;
import android.os.SystemClock;
import android.support.test.rule.ActivityTestRule;
import android.widget.TextView;

Expand All @@ -27,6 +29,7 @@
import org.xbmc.kore.testhelpers.Utils;
import org.xbmc.kore.tests.ui.AbstractTestClass;
import org.xbmc.kore.tests.ui.BaseMediaActivityTests;
import org.xbmc.kore.ui.sections.addon.AddonsActivity;
import org.xbmc.kore.ui.sections.video.MoviesActivity;

import static android.support.test.espresso.Espresso.onView;
Expand Down Expand Up @@ -71,9 +74,9 @@ protected ActivityTestRule<MoviesActivity> getActivityTestRule() {
@Override
public void setUp() throws Throwable {
super.setUp();
//Start the AddonsActivity from the MoviesActivity
Utils.openDrawer(getActivityTestRule());
EspressoTestUtils.clickAdapterViewItem(7, R.id.navigation_drawer);

Intent intent = new Intent(getActivity(), AddonsActivity.class);
getActivity().startActivity(intent);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.xbmc.kore.tests.ui.movies;

import android.os.SystemClock;
import android.support.test.rule.ActivityTestRule;
import android.widget.TextView;

Expand Down Expand Up @@ -80,7 +81,7 @@ public void setActionBarTitle() {
public void restoreActionBarTitleOnConfigurationStateChanged() {
EspressoTestUtils.selectListItemRotateDeviceAndCheckActionbarTitle(0, R.id.list,
"#Rookie93 Marc Marquez: Beyond the Smile",
mActivityRule.getActivity());
getActivity());
}

/**
Expand All @@ -94,6 +95,6 @@ public void restoreActionBarTitleOnConfigurationStateChanged() {
@Test
public void restoreActionBarTitleOnReturningFromMovie() {
selectListItemPressBackAndCheckActionbarTitle(0, R.id.list,
mActivityRule.getActivity().getString(R.string.movies));
getActivity().getString(R.string.movies));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class NavigationDrawerFragment extends Fragment {
* Per the design guidelines, you should show the drawer on launch until the user manually
* expands it. This shared preference tracks this.
*/
private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
public static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";

public static final int ACTIVITY_HOSTS = 0,
ACTIVITY_REMOTE = 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.xbmc.kore.ui.BaseMediaActivity;
import org.xbmc.kore.ui.sections.remote.RemoteActivity;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.Utils;

/**
* Controls the presentation of Addons information (list, details)
Expand Down Expand Up @@ -127,8 +128,9 @@ public void onAddonSelected(AddonListFragment.ViewHolder vh) {
;
addonDetailsFragment.setDataHolder(vh.dataHolder);
vh.dataHolder.setSquarePoster(true);
vh.dataHolder.setPosterTransitionName(vh.artView.getTransitionName());

if(Utils.isLollipopOrLater()) {
vh.dataHolder.setPosterTransitionName(vh.artView.getTransitionName());
}
showFragment(addonDetailsFragment, vh.artView, vh.dataHolder);

updateActionBar(getActionBarTitle(), true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,17 @@ private void processJSONInput(String input) {
@Override
public String getResponse() {
StringBuffer stringBuffer = new StringBuffer();

//Handle responses
Collection<ArrayList<JsonResponse>> jsonResponses = clientResponses.values();
for(ArrayList<JsonResponse> arrayList : jsonResponses) {
for (JsonResponse response : arrayList) {
stringBuffer.append(response.toJsonString() + "\n");

synchronized (clientResponses) {
//Handle responses
Collection<ArrayList<JsonResponse>> jsonResponses = clientResponses.values();
for (ArrayList<JsonResponse> arrayList : jsonResponses) {
for (JsonResponse response : arrayList) {
stringBuffer.append(response.toJsonString() + "\n");
}
}
clientResponses.clear();
}
clientResponses.clear();

//Handle notifications
for(ConnectionHandler handler : handlers) {
Expand Down Expand Up @@ -168,7 +170,9 @@ private void addResponse(int id, ArrayList<JsonResponse> jsonResponses) {
ArrayList<JsonResponse> responses = clientResponses.get(String.valueOf(id));
if (responses == null) {
responses = new ArrayList<>();
clientResponses.put(String.valueOf(id), responses);
synchronized (clientResponses) {
clientResponses.put(String.valueOf(id), responses);
}
}
responses.addAll(jsonResponses);
}
Expand Down

0 comments on commit 9e65350

Please sign in to comment.