Merge pull request #3654 from ByteHamster/emulator-test

Run integration tests on CI
This commit is contained in:
H. Lehmann 2019-12-20 00:12:51 +01:00 committed by GitHub
commit 707fcdbc7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 302 additions and 272 deletions

29
.github/workflows/android-emulator.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Android Emulator test
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v1
- name: set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Gradle
run: ./gradlew assemblePlayDebugAndroidTest
- name: Android Emulator test
uses: ReactiveCircus/android-emulator-runner@v1.0.1
with:
api-level: 28
headless: true
disable-animations: true
script: ./gradlew connectedPlayDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.notAnnotation=de.test.antennapod.IgnoreOnCi
- uses: actions/upload-artifact@v1
if: failure()
with:
name: test-report
path: app/build/reports/androidTests/connected/flavors/PLAY/

View File

@ -1,6 +1,8 @@
package de.test.antennapod;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.IdRes;
import androidx.annotation.StringRes;
import androidx.test.InstrumentationRegistry;
import androidx.test.espresso.PerformException;
@ -14,11 +16,16 @@ import androidx.test.espresso.util.TreeIterables;
import android.view.View;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.dialog.RatingDialog;
import org.awaitility.Awaitility;
import org.awaitility.core.ConditionTimeoutException;
import org.hamcrest.Matcher;
import java.io.File;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static androidx.test.espresso.Espresso.onView;
@ -76,6 +83,31 @@ public class EspressoTestUtils {
};
}
/**
* Perform action of waiting for a specific view id.
* https://stackoverflow.com/a/30338665/
* @param id The id of the child to click.
*/
public static ViewAction clickChildViewWithId(final @IdRes int id) {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return null;
}
@Override
public String getDescription() {
return "Click on a child view with specified id.";
}
@Override
public void perform(UiController uiController, View view) {
View v = view.findViewById(id);
v.performClick();
}
};
}
/**
* Clear all app databases
*/
@ -127,12 +159,37 @@ public class EspressoTestUtils {
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open());
}
public static void closeNavDrawer() {
onView(isRoot()).perform(waitForView(withId(R.id.drawer_layout), 1000));
onView(withId(R.id.drawer_layout)).perform(DrawerActions.close());
}
public static ViewInteraction onDrawerItem(Matcher<View> viewMatcher) {
return onView(allOf(viewMatcher, withId(R.id.txtvTitle)));
}
public static void tryKillPlaybackService() {
Context context = InstrumentationRegistry.getTargetContext();
context.stopService(new Intent(context, PlaybackService.class));
try {
// Android has no reliable way to stop a service instantly.
// Calling stopSelf marks allows the system to destroy the service but the actual call
// to onDestroy takes until the next GC of the system, which we can not influence.
// Try to wait for the service at least a bit.
Awaitility.await().atMost(10, TimeUnit.SECONDS).until(() -> !PlaybackService.isRunning);
} catch (ConditionTimeoutException e) {
e.printStackTrace();
}
androidx.test.platform.app.InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
public static void tryKillDownloadService() {
Context context = InstrumentationRegistry.getTargetContext();
context.stopService(new Intent(context, DownloadService.class));
try {
// Android has no reliable way to stop a service instantly.
// Calling stopSelf marks allows the system to destroy the service but the actual call
// to onDestroy takes until the next GC of the system, which we can not influence.
// Try to wait for the service at least a bit.
Awaitility.await().atMost(10, TimeUnit.SECONDS).until(() -> !DownloadService.isRunning);
} catch (ConditionTimeoutException e) {
e.printStackTrace();
}
androidx.test.platform.app.InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
}

View File

@ -0,0 +1,15 @@
package de.test.antennapod;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Tests with this annotation are ignored on CI. This could be reasonable
* if the performance of the CI server is not enough to provide a reliable result.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IgnoreOnCi {
}

View File

@ -11,10 +11,6 @@ public class NthMatcher {
return nth(matcher, 1);
}
public static <T> Matcher<T> second(final Matcher<T> matcher) {
return nth(matcher, 2);
}
public static <T> Matcher<T> nth(final Matcher<T> matcher, final int index) {
return new BaseMatcher<T>() {
AtomicInteger count = new AtomicInteger(0);
@ -31,7 +27,8 @@ public class NthMatcher {
@Override
public void describeTo(final Description description) {
description.appendText("should return first matching item");
description.appendText("Item #" + index + " ");
description.appendDescriptionOf(matcher);
}
};
}

View File

@ -1,17 +0,0 @@
package de.test.antennapod.playback;
import androidx.test.filters.LargeTest;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import org.junit.Before;
/**
* Test cases for starting and ending playback from the MainActivity and AudioPlayerActivity.
*/
@LargeTest
public class PlaybackBuiltinTest extends PlaybackTest {
@Before
public void setUp() throws Exception {
super.setUp();
UserPreferences.enableBuiltin();
}
}

View File

@ -1,17 +0,0 @@
package de.test.antennapod.playback;
import androidx.test.filters.LargeTest;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import org.junit.Before;
/**
* Test cases for starting and ending playback from the MainActivity and AudioPlayerActivity.
*/
@LargeTest
public class PlaybackExoplayerTest extends PlaybackTest {
@Before
public void setUp() throws Exception {
super.setUp();
UserPreferences.enableExoplayer();
}
}

View File

@ -1,17 +0,0 @@
package de.test.antennapod.playback;
import androidx.test.filters.LargeTest;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import org.junit.Before;
/**
* Test cases for starting and ending playback from the MainActivity and AudioPlayerActivity.
*/
@LargeTest
public class PlaybackSonicTest extends PlaybackTest {
@Before
public void setUp() throws Exception {
super.setUp();
UserPreferences.enableSonic();
}
}

View File

@ -4,55 +4,79 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.view.KeyEvent;
import android.view.View;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.test.antennapod.EspressoTestUtils;
import de.test.antennapod.IgnoreOnCi;
import de.test.antennapod.ui.UITestUtils;
import org.awaitility.Awaitility;
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
import static androidx.test.espresso.matcher.ViewMatchers.hasMinimumChildCount;
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.withText;
import static de.test.antennapod.EspressoTestUtils.clickChildViewWithId;
import static de.test.antennapod.EspressoTestUtils.onDrawerItem;
import static de.test.antennapod.EspressoTestUtils.openNavDrawer;
import static de.test.antennapod.EspressoTestUtils.waitForView;
import static de.test.antennapod.NthMatcher.first;
import static de.test.antennapod.NthMatcher.nth;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Test cases for starting and ending playback from the MainActivity and AudioPlayerActivity.
*/
public abstract class PlaybackTest {
@LargeTest
@IgnoreOnCi
@RunWith(Parameterized.class)
public class PlaybackTest {
@Rule
public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class, false, false);
@Parameterized.Parameter(value = 0)
public String playerToUse;
private UITestUtils uiTestUtils;
protected Context context;
@Parameterized.Parameters(name = "{0}")
public static Collection<Object[]> initParameters() {
return Arrays.asList(new Object[][] { { "exoplayer" }, { "builtin" }, { "sonic" } });
}
@Before
public void setUp() throws Exception {
context = InstrumentationRegistry.getInstrumentation().getTargetContext();
@ -60,6 +84,9 @@ public abstract class PlaybackTest {
EspressoTestUtils.clearDatabase();
EspressoTestUtils.makeNotFirstRun();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putString(UserPreferences.PREF_MEDIA_PLAYER, playerToUse).apply();
uiTestUtils = new UITestUtils(context);
uiTestUtils.setup();
}
@ -67,10 +94,8 @@ public abstract class PlaybackTest {
@After
public void tearDown() throws Exception {
activityTestRule.finishActivity();
EspressoTestUtils.tryKillPlaybackService();
uiTestUtils.tearDown();
// shut down playback service
context.sendBroadcast(new Intent(PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
Awaitility.await().until(() -> !PlaybackService.isRunning);
}
@Test
@ -78,23 +103,9 @@ public abstract class PlaybackTest {
setContinuousPlaybackPreference(false);
uiTestUtils.addLocalFeedData(true);
activityTestRule.launchActivity(new Intent());
List<FeedItem> queue = DBReader.getQueue();
final FeedItem first = queue.get(0);
playFromQueue(0);
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(() -> {
if (uiTestUtils.getPlaybackController(getActivity()).getStatus()
!= PlayerStatus.PLAYING) {
return true;
} else if (uiTestUtils.getCurrentMedia(getActivity()) != null) {
return uiTestUtils.getCurrentMedia(getActivity()).getId()
!= first.getMedia().getId();
} else {
return true;
}
});
Thread.sleep(1000);
assertNotEquals(PlayerStatus.PLAYING, uiTestUtils.getPlaybackController(getActivity()).getStatus());
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(
() -> uiTestUtils.getPlaybackController(getActivity()).getStatus() == PlayerStatus.INITIALIZED);
}
@Test
@ -108,22 +119,10 @@ public abstract class PlaybackTest {
final FeedItem second = queue.get(1);
playFromQueue(0);
Awaitility.await().atMost(2, TimeUnit.SECONDS).until(() -> {
if (uiTestUtils.getCurrentMedia(getActivity()) != null) {
return uiTestUtils.getCurrentMedia(getActivity()).getId()
== first.getMedia().getId();
} else {
return false;
}
});
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(() -> {
if (uiTestUtils.getCurrentMedia(getActivity()) != null) {
return uiTestUtils.getCurrentMedia(getActivity()).getId()
== second.getMedia().getId();
} else {
return false;
}
});
Awaitility.await().atMost(2, TimeUnit.SECONDS).until(
() -> first.getMedia().equals(uiTestUtils.getCurrentMedia()));
Awaitility.await().atMost(6, TimeUnit.SECONDS).until(
() -> second.getMedia().equals(uiTestUtils.getCurrentMedia()));
}
@ -213,33 +212,27 @@ public abstract class PlaybackTest {
}
private void skipEpisode() {
Intent skipIntent = new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE);
context.sendBroadcast(skipIntent);
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SKIP_CURRENT_EPISODE);
}
protected void pauseEpisode() {
Intent pauseIntent = new Intent(PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
context.sendBroadcast(pauseIntent);
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
}
protected void startLocalPlayback() {
openNavDrawer();
onDrawerItem(withText(R.string.episodes_label)).perform(click());
onView(isRoot()).perform(waitForView(withId(R.id.emptyViewTitle), 1000));
onView(isRoot()).perform(waitForView(withText(R.string.all_episodes_short_label), 1000));
onView(withText(R.string.all_episodes_short_label)).perform(click());
final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10);
onView(isRoot()).perform(waitForView(withId(R.id.butSecondaryAction), 1000));
Matcher<View> allEpisodesMatcher = allOf(withId(android.R.id.list), isDisplayed(), hasMinimumChildCount(2));
onView(isRoot()).perform(waitForView(allEpisodesMatcher, 1000));
onView(allEpisodesMatcher).perform(actionOnItemAtPosition(0, clickChildViewWithId(R.id.butSecondaryAction)));
onView(first(withId(R.id.butSecondaryAction))).perform(click());
long mediaId = episodes.get(0).getMedia().getId();
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> {
if (uiTestUtils.getCurrentMedia(getActivity()) != null) {
return uiTestUtils.getCurrentMedia(getActivity()).getId() == mediaId;
} else {
return false;
}
});
FeedMedia media = episodes.get(0).getMedia();
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(
() -> media.equals(uiTestUtils.getCurrentMedia()));
}
/**
@ -249,16 +242,14 @@ public abstract class PlaybackTest {
protected void playFromQueue(int itemIdx) {
final List<FeedItem> queue = DBReader.getQueue();
onView(nth(withId(R.id.butSecondaryAction), itemIdx + 1)).perform(click());
onView(isRoot()).perform(waitForView(withId(R.id.butPlay), 1000));
long mediaId = queue.get(itemIdx).getMedia().getId();
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> {
if (uiTestUtils.getCurrentMedia(getActivity()) != null) {
return uiTestUtils.getCurrentMedia(getActivity()).getId() == mediaId;
} else {
return false;
}
});
Matcher<View> queueMatcher = allOf(withId(R.id.recyclerView), isDisplayed(), hasMinimumChildCount(2));
onView(isRoot()).perform(waitForView(queueMatcher, 1000));
onView(queueMatcher).perform(actionOnItemAtPosition(itemIdx, clickChildViewWithId(R.id.butSecondaryAction)));
FeedMedia media = queue.get(itemIdx).getMedia();
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(
() -> media.equals(uiTestUtils.getCurrentMedia()));
}
/**
@ -272,42 +263,36 @@ public abstract class PlaybackTest {
final List<FeedItem> episodes = DBReader.getRecentlyPublishedEpisodes(0, 10);
startLocalPlayback();
long mediaId = episodes.get(0).getMedia().getId();
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> {
if (uiTestUtils.getCurrentMedia(getActivity()) != null) {
return uiTestUtils.getCurrentMedia(getActivity()).getId() == mediaId;
} else {
return false;
}
});
FeedMedia media = episodes.get(0).getMedia();
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(
() -> media.equals(uiTestUtils.getCurrentMedia()));
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(() ->
uiTestUtils.getCurrentMedia(getActivity()) == null
|| uiTestUtils.getCurrentMedia(getActivity()).getId() != mediaId);
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(
() -> !media.equals(uiTestUtils.getCurrentMedia()));
startLocalPlayback();
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(() -> {
if (uiTestUtils.getCurrentMedia(getActivity()) != null) {
return uiTestUtils.getCurrentMedia(getActivity()).getId() == mediaId;
} else {
return false;
}
});
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(
() -> media.equals(uiTestUtils.getCurrentMedia()));
}
protected void doTestSmartMarkAsPlayed_Skip_ForEpisode(int itemIdxNegAllowed) throws Exception {
setSmartMarkAsPlayedPreference(60);
// ensure when an episode is skipped, it is removed due to smart as played
setSkipKeepsEpisodePreference(false);
uiTestUtils.setMediaFileName("30sec.mp3");
uiTestUtils.addLocalFeedData(true);
LongList queue = DBReader.getQueueIDList();
int fiIdx;
if (itemIdxNegAllowed >= 0) {
fiIdx = itemIdxNegAllowed;
} else { // negative index: count from the end, with -1 being the last one, etc.
fiIdx = DBReader.getQueue().size() + itemIdxNegAllowed;
fiIdx = queue.size() + itemIdxNegAllowed;
}
final FeedItem feedItem = DBReader.getQueue().get(fiIdx);
final long feedItemId = queue.get(fiIdx);
queue.removeIndex(fiIdx);
assertFalse(queue.contains(feedItemId)); // Verify that episode is in queue only once
activityTestRule.launchActivity(new Intent());
playFromQueue(fiIdx);
@ -316,8 +301,8 @@ public abstract class PlaybackTest {
// assert item no longer in queue (needs to wait till skip is asynchronously processed)
Awaitility.await()
.atMost(1000, MILLISECONDS)
.until(() -> !DBReader.getQueue().contains(feedItem));
assertTrue(DBReader.getFeedItem(feedItem.getId()).isPlayed());
.atMost(5000, MILLISECONDS)
.until(() -> !DBReader.getQueueIDList().contains(feedItemId));
assertTrue(DBReader.getFeedItem(feedItemId).isPlayed());
}
}

View File

@ -1,10 +1,13 @@
package de.test.antennapod.service.download;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import de.test.antennapod.EspressoTestUtils;
import org.awaitility.Awaitility;
import org.awaitility.core.ConditionTimeoutException;
import org.junit.After;
@ -53,6 +56,8 @@ public class DownloadServiceTest {
@Before
public void setUp() throws Exception {
EspressoTestUtils.clearDatabase();
EspressoTestUtils.clearPreferences();
origFactory = DownloadService.getDownloaderFactory();
testFeed = setUpTestFeeds();
testMedia11 = testFeed.getItemAtIndex(0).getMedia();
@ -77,6 +82,10 @@ public class DownloadServiceTest {
@After
public void tearDown() throws Exception {
DownloadService.setDownloaderFactory(origFactory);
Context context = InstrumentationRegistry.getTargetContext();
DownloadRequester.getInstance().cancelAllDownloads(context);
context.stopService(new Intent(context, DownloadService.class));
EspressoTestUtils.tryKillDownloadService();
}
@Test
@ -136,8 +145,9 @@ public class DownloadServiceTest {
}
private void doTestCancelDownload_UndoEnqueue(boolean itemAlreadyInQueue) throws Exception {
Context context = InstrumentationRegistry.getTargetContext();
// let download takes longer to ensure the test can cancel the download in time
DownloadService.setDownloaderFactory(new StubDownloaderFactory(150, downloadStatus -> {
DownloadService.setDownloaderFactory(new StubDownloaderFactory(10000, downloadStatus -> {
downloadStatus.setSuccessful();
}));
UserPreferences.setEnqueueDownloadedEpisodes(true);
@ -146,45 +156,38 @@ public class DownloadServiceTest {
final long item1Id = testMedia11.getItem().getId();
if (itemAlreadyInQueue) {
// simulate item already in queue condition
DBWriter.addQueueItem(InstrumentationRegistry.getTargetContext(), false, item1Id).get();
DBWriter.addQueueItem(context, false, item1Id).get();
assertTrue(DBReader.getQueueIDList().contains(item1Id));
} else {
assertFalse(DBReader.getQueueIDList().contains(item1Id));
}
withFeedItemEventListener(feedItemEventListener -> {
try {
DownloadRequester.getInstance().downloadMedia(false, InstrumentationRegistry.getTargetContext(),
testMedia11.getItem());
if (itemAlreadyInQueue) {
Awaitility.await("download service receives the request - "
+ "no event is expected before cancel is issued")
.atLeast(100, TimeUnit.MILLISECONDS)
.until(() -> true);
} else {
Awaitility.await("item enqueue event")
.atMost(1000, TimeUnit.MILLISECONDS)
.until(() -> feedItemEventListener.getEvents().size() >= 1);
}
DownloadRequester.getInstance().cancelDownload(InstrumentationRegistry.getTargetContext(),
testMedia11);
final int totalNumEventsExpected = itemAlreadyInQueue ? 1 : 3;
Awaitility.await("item dequeue event + download termination event")
.atMost(1000, TimeUnit.MILLISECONDS)
.until(() ->feedItemEventListener.getEvents().size() >= totalNumEventsExpected);
assertFalse("The download should have been canceled",
DBReader.getFeedMedia(testMedia11.getId()).isDownloaded());
if (itemAlreadyInQueue) {
assertTrue("The FeedItem should still be in the queue after the download is cancelled."
+ " It's there before download.",
DBReader.getQueueIDList().contains(item1Id));
} else {
assertFalse("The FeedItem should not be in the queue after the download is cancelled.",
DBReader.getQueueIDList().contains(item1Id));
}
} catch (ConditionTimeoutException cte) {
fail("The expected FeedItemEvent (for media download complete) has not been posted. "
+ cte.getMessage());
DownloadRequester.getInstance().downloadMedia(false, context, testMedia11.getItem());
if (itemAlreadyInQueue) {
Awaitility.await("download service receives the request - "
+ "no event is expected before cancel is issued")
.atLeast(100, TimeUnit.MILLISECONDS)
.until(() -> true);
} else {
Awaitility.await("item enqueue event")
.atMost(2000, TimeUnit.MILLISECONDS)
.until(() -> feedItemEventListener.getEvents().size() >= 1);
}
DownloadRequester.getInstance().cancelDownload(context, testMedia11);
final int totalNumEventsExpected = itemAlreadyInQueue ? 1 : 3;
Awaitility.await("item dequeue event + download termination event")
.atMost(1000, TimeUnit.MILLISECONDS)
.until(() -> feedItemEventListener.getEvents().size() >= totalNumEventsExpected);
assertFalse("The download should have been canceled",
DBReader.getFeedMedia(testMedia11.getId()).isDownloaded());
if (itemAlreadyInQueue) {
assertTrue("The FeedItem should still be in the queue after the download is cancelled."
+ " It's there before download.",
DBReader.getQueueIDList().contains(item1Id));
} else {
assertFalse("The FeedItem should not be in the queue after the download is cancelled.",
DBReader.getQueueIDList().contains(item1Id));
}
});
}

View File

@ -29,10 +29,9 @@ public class HttpDownloaderTest {
private static final String TAG = "HttpDownloaderTest";
private static final String DOWNLOAD_DIR = "testdownloads";
private static boolean successful = true;
private String url404;
private String urlAuth;
private File destDir;
private HTTPBin httpServer;
public HttpDownloaderTest() {
@ -57,6 +56,8 @@ public class HttpDownloaderTest {
assertTrue(destDir.exists());
httpServer = new HTTPBin();
httpServer.start();
url404 = httpServer.getBaseUrl() + "/status/404";
urlAuth = httpServer.getBaseUrl() + "/basic-auth/user/passwd";
}
private FeedFileImpl setupFeedFile(String downloadUrl, String title, boolean deleteExisting) {
@ -88,33 +89,29 @@ public class HttpDownloaderTest {
return downloader;
}
private static final String URL_404 = HTTPBin.BASE_URL + "/status/404";
private static final String URL_AUTH = HTTPBin.BASE_URL + "/basic-auth/user/passwd";
@Test
public void testPassingHttp() {
download(HTTPBin.BASE_URL + "/status/200", "test200", true);
download(httpServer.getBaseUrl() + "/status/200", "test200", true);
}
@Test
public void testRedirect() {
download(HTTPBin.BASE_URL + "/redirect/4", "testRedirect", true);
download(httpServer.getBaseUrl() + "/redirect/4", "testRedirect", true);
}
@Test
public void testGzip() {
download(HTTPBin.BASE_URL + "/gzip/100", "testGzip", true);
download(httpServer.getBaseUrl() + "/gzip/100", "testGzip", true);
}
@Test
public void test404() {
download(URL_404, "test404", false);
download(url404, "test404", false);
}
@Test
public void testCancel() {
final String url = HTTPBin.BASE_URL + "/delay/3";
final String url = httpServer.getBaseUrl() + "/delay/3";
FeedFileImpl feedFile = setupFeedFile(url, "delay", true);
final Downloader downloader = new HttpDownloader(new DownloadRequest(feedFile.getFile_url(), url, "delay", 0, feedFile.getTypeAsInt()));
Thread t = new Thread() {
@ -139,7 +136,7 @@ public class HttpDownloaderTest {
@Test
public void testDeleteOnFailShouldDelete() {
Downloader downloader = download(URL_404, "testDeleteOnFailShouldDelete", false, true, null, null, true);
Downloader downloader = download(url404, "testDeleteOnFailShouldDelete", false, true, null, null, true);
assertFalse(new File(downloader.getDownloadRequest().getDestination()).exists());
}
@ -149,18 +146,18 @@ public class HttpDownloaderTest {
File dest = new File(destDir, filename);
dest.delete();
assertTrue(dest.createNewFile());
Downloader downloader = download(URL_404, filename, false, false, null, null, false);
Downloader downloader = download(url404, filename, false, false, null, null, false);
assertTrue(new File(downloader.getDownloadRequest().getDestination()).exists());
}
@Test
public void testAuthenticationShouldSucceed() throws InterruptedException {
download(URL_AUTH, "testAuthSuccess", true, true, "user", "passwd", true);
download(urlAuth, "testAuthSuccess", true, true, "user", "passwd", true);
}
@Test
public void testAuthenticationShouldFail() {
Downloader downloader = download(URL_AUTH, "testAuthSuccess", false, true, "user", "Wrong passwd", true);
Downloader downloader = download(urlAuth, "testAuthSuccess", false, true, "user", "Wrong passwd", true);
assertEquals(DownloadError.ERROR_UNAUTHORIZED, downloader.getResult().getReason());
}

View File

@ -2,8 +2,8 @@ package de.test.antennapod.service.playback;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import de.test.antennapod.EspressoTestUtils;
import junit.framework.AssertionFailedError;
@ -32,7 +32,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@ -45,13 +45,12 @@ import static org.junit.Assert.fail;
*/
@MediumTest
public class PlaybackServiceMediaPlayerTest {
private static final String PLAYABLE_FILE_URL = "http://127.0.0.1:" + HTTPBin.PORT + "/files/0";
private static final String PLAYABLE_DEST_URL = "psmptestfile.mp3";
private String PLAYABLE_LOCAL_URL = null;
private static final int LATCH_TIMEOUT_SECONDS = 3;
private HTTPBin httpServer;
private String playableFileUrl;
private volatile AssertionFailedError assertionError;
@After
@ -67,10 +66,11 @@ public class PlaybackServiceMediaPlayerTest {
EspressoTestUtils.makeNotFirstRun();
EspressoTestUtils.clearDatabase();
final Context context = InstrumentationRegistry.getTargetContext();
final Context context = getInstrumentation().getTargetContext();
httpServer = new HTTPBin();
httpServer.start();
playableFileUrl = httpServer.getBaseUrl() + "/files/0";
File cacheDir = context.getExternalFilesDir("testFiles");
if (cacheDir == null)
@ -81,7 +81,7 @@ public class PlaybackServiceMediaPlayerTest {
assertTrue(cacheDir.canWrite());
assertTrue(cacheDir.canRead());
if (!dest.exists()) {
InputStream i = InstrumentationRegistry.getContext().getAssets().open("3sec.mp3");
InputStream i = getInstrumentation().getTargetContext().getAssets().open("3sec.mp3");
OutputStream o = new FileOutputStream(new File(cacheDir, PLAYABLE_DEST_URL));
IOUtils.copy(i, o);
o.flush();
@ -167,7 +167,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
Playable p = writeTestPlayable(playableFileUrl, null);
psmp.playMediaObject(p, true, false, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
if (assertionError != null)
@ -207,7 +207,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
Playable p = writeTestPlayable(playableFileUrl, null);
psmp.playMediaObject(p, true, true, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@ -251,7 +251,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
Playable p = writeTestPlayable(playableFileUrl, null);
psmp.playMediaObject(p, true, false, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
if (assertionError != null)
@ -296,7 +296,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
Playable p = writeTestPlayable(playableFileUrl, null);
psmp.playMediaObject(p, true, true, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
if (assertionError != null)
@ -334,7 +334,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, false, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
if (assertionError != null)
@ -373,7 +373,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, true, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
if (assertionError != null)
@ -415,7 +415,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, false, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
if (assertionError != null)
@ -460,7 +460,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, true, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
if (assertionError != null)
@ -523,7 +523,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL);
if (initialState == PlayerStatus.PLAYING) {
psmp.playMediaObject(p, stream, true, true);
}
@ -616,7 +616,7 @@ public class PlaybackServiceMediaPlayerTest {
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
if (initialState == PlayerStatus.PREPARED || initialState == PlayerStatus.PLAYING || initialState == PlayerStatus.PAUSED) {
boolean startWhenPrepared = (initialState != PlayerStatus.PREPARED);
psmp.playMediaObject(writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL), false, startWhenPrepared, true);
psmp.playMediaObject(writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL), false, startWhenPrepared, true);
}
if (initialState == PlayerStatus.PAUSED) {
psmp.pause(false, false);
@ -673,7 +673,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL);
if (initialState == PlayerStatus.INITIALIZED
|| initialState == PlayerStatus.PLAYING
|| initialState == PlayerStatus.PREPARED
@ -747,7 +747,7 @@ public class PlaybackServiceMediaPlayerTest {
}
});
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
Playable p = writeTestPlayable(playableFileUrl, PLAYABLE_LOCAL_URL);
boolean prepareImmediately = initialState != PlayerStatus.INITIALIZED;
boolean startImmediately = initialState != PlayerStatus.PREPARED;
psmp.playMediaObject(p, false, startImmediately, prepareImmediately);

View File

@ -7,6 +7,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
import de.test.antennapod.EspressoTestUtils;
import org.awaitility.Awaitility;
import org.awaitility.core.ConditionTimeoutException;
import org.junit.After;
@ -14,6 +16,7 @@ import org.junit.Before;
import org.junit.Test;
import java.util.List;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.DBTasksCallbacks;
@ -49,21 +52,16 @@ public class AutoDownloadTest {
dbTasksCallbacksOrig = ClientConfig.dbTasksCallbacks;
// create new database
PodDBAdapter.init(context);
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.close();
EspressoTestUtils.clearPreferences();
EspressoTestUtils.clearDatabase();
UserPreferences.setAllowMobileStreaming(true);
}
@After
public void tearDown() throws Exception {
stubFeedsServer.tearDown();
ClientConfig.dbTasksCallbacks = dbTasksCallbacksOrig;
context.sendBroadcast(new Intent(PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
Awaitility.await().until(() -> !PlaybackService.isRunning);
EspressoTestUtils.tryKillPlaybackService();
stubFeedsServer.tearDown();
}
/**
@ -117,7 +115,7 @@ public class AutoDownloadTest {
FeedMedia media = item.getMedia();
DBTasks.playMedia(context, media, false, true, true);
Awaitility.await("episode is playing")
.atMost(1000, MILLISECONDS)
.atMost(2000, MILLISECONDS)
.until(() -> item.equals(getCurrentlyPlaying()));
}
@ -126,7 +124,7 @@ public class AutoDownloadTest {
if (playable == null) {
return null;
}
return ((FeedMedia)playable).getItem();
return ((FeedMedia) playable).getItem();
}
private void useDownloadAlgorithm(final AutomaticDownloadAlgorithm downloadAlgorithm) {

View File

@ -29,10 +29,12 @@ import static androidx.test.espresso.contrib.ActivityResultMatchers.hasResultCod
import static androidx.test.espresso.intent.Intents.intended;
import static androidx.test.espresso.intent.Intents.times;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static de.test.antennapod.EspressoTestUtils.clickPreference;
import static de.test.antennapod.EspressoTestUtils.openNavDrawer;
import static de.test.antennapod.EspressoTestUtils.waitForView;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
@ -75,11 +77,11 @@ public class MainActivityTest {
final Feed feed = uiTestUtils.hostedFeeds.get(0);
openNavDrawer();
onView(withText(R.string.add_feed_label)).perform(click());
onView(withId(R.id.etxtFeedurl)).perform(typeText(feed.getDownload_url()));
onView(withText(R.string.confirm_label)).perform(scrollTo()).perform(click());
onView(withId(R.id.etxtFeedurl)).perform(scrollTo(), typeText(feed.getDownload_url()));
onView(withText(R.string.confirm_label)).perform(scrollTo(), click());
Espresso.closeSoftKeyboard();
onView(withText(R.string.subscribe_label)).perform(click());
intended(hasComponent(MainActivity.class.getName()), times(2));
onView(isRoot()).perform(waitForView(withId(R.id.butShowSettings), 5000));
}
private String getActionbarTitle() {

View File

@ -32,6 +32,7 @@ import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.action.ViewActions.swipeDown;
import static androidx.test.espresso.action.ViewActions.swipeUp;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
@ -246,10 +247,10 @@ public class PreferencesTest {
public void testPauseForInterruptions() {
onView(withText(R.string.playback_pref)).perform(click());
final boolean pauseForFocusLoss = UserPreferences.shouldPauseForFocusLoss();
onView(withText(R.string.pref_pausePlaybackForFocusLoss_title)).perform(click());
clickPreference(R.string.pref_pausePlaybackForFocusLoss_title);
Awaitility.await().atMost(1000, MILLISECONDS)
.until(() -> pauseForFocusLoss != UserPreferences.shouldPauseForFocusLoss());
onView(withText(R.string.pref_pausePlaybackForFocusLoss_title)).perform(click());
clickPreference(R.string.pref_pausePlaybackForFocusLoss_title);
Awaitility.await().atMost(1000, MILLISECONDS)
.until(() -> pauseForFocusLoss == UserPreferences.shouldPauseForFocusLoss());
}
@ -332,7 +333,8 @@ public class PreferencesTest {
clickPreference(R.string.network_pref);
clickPreference(R.string.pref_automatic_download_title);
clickPreference(R.string.pref_episode_cache_title);
onView(withText(minEntry)).perform(scrollTo()).perform(click());
onView(withId(R.id.select_dialog_listview)).perform(swipeDown());
onView(withText(minEntry)).perform(click());
Awaitility.await().atMost(1000, MILLISECONDS)
.until(() -> UserPreferences.getEpisodeCacheSize() == minValue);
}
@ -346,6 +348,7 @@ public class PreferencesTest {
onView(withText(R.string.network_pref)).perform(click());
onView(withText(R.string.pref_automatic_download_title)).perform(click());
onView(withText(R.string.pref_episode_cache_title)).perform(click());
onView(withId(R.id.select_dialog_listview)).perform(swipeUp());
onView(withText(maxEntry)).perform(click());
Awaitility.await().atMost(1000, MILLISECONDS)
.until(() -> UserPreferences.getEpisodeCacheSize() == maxValue);
@ -365,17 +368,17 @@ public class PreferencesTest {
Awaitility.await().atMost(1000, MILLISECONDS)
.until(UserPreferences::isEnableAutodownload);
final boolean enableAutodownloadOnBattery = UserPreferences.isEnableAutodownloadOnBattery();
onView(withText(R.string.pref_automatic_download_on_battery_title)).perform(click());
clickPreference(R.string.pref_automatic_download_on_battery_title);
Awaitility.await().atMost(1000, MILLISECONDS)
.until(() -> enableAutodownloadOnBattery != UserPreferences.isEnableAutodownloadOnBattery());
onView(withText(R.string.pref_automatic_download_on_battery_title)).perform(click());
clickPreference(R.string.pref_automatic_download_on_battery_title);
Awaitility.await().atMost(1000, MILLISECONDS)
.until(() -> enableAutodownloadOnBattery == UserPreferences.isEnableAutodownloadOnBattery());
final boolean enableWifiFilter = UserPreferences.isEnableAutodownloadWifiFilter();
onView(withText(R.string.pref_autodl_wifi_filter_title)).perform(click());
clickPreference(R.string.pref_autodl_wifi_filter_title);
Awaitility.await().atMost(1000, MILLISECONDS)
.until(() -> enableWifiFilter != UserPreferences.isEnableAutodownloadWifiFilter());
onView(withText(R.string.pref_autodl_wifi_filter_title)).perform(click());
clickPreference(R.string.pref_autodl_wifi_filter_title);
Awaitility.await().atMost(1000, MILLISECONDS)
.until(() -> enableWifiFilter == UserPreferences.isEnableAutodownloadWifiFilter());
}
@ -425,7 +428,7 @@ public class PreferencesTest {
clickPreference(R.string.network_pref);
clickPreference(R.string.pref_automatic_download_title);
clickPreference(R.string.pref_episode_cleanup_title);
String search = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, 5, 5);
String search = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, 3, 3);
onView(isRoot()).perform(waitForView(withText(search), 1000));
onView(withText(search)).perform(click());
Awaitility.await().atMost(1000, MILLISECONDS)
@ -433,7 +436,7 @@ public class PreferencesTest {
EpisodeCleanupAlgorithm alg = UserPreferences.getEpisodeCleanupAlgorithm();
if (alg instanceof APCleanupAlgorithm) {
APCleanupAlgorithm cleanupAlg = (APCleanupAlgorithm) alg;
return cleanupAlg.getNumberOfHoursAfterPlayback() == 120; // 5 days
return cleanupAlg.getNumberOfHoursAfterPlayback() == 72; // 5 days
}
return false;
});

View File

@ -11,11 +11,11 @@ import de.danoeh.antennapod.activity.AudioplayerActivity;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.fragment.QueueFragment;
import de.test.antennapod.EspressoTestUtils;
import de.test.antennapod.IgnoreOnCi;
import org.awaitility.Awaitility;
import org.junit.After;
import org.junit.Before;
@ -39,6 +39,7 @@ import static de.test.antennapod.EspressoTestUtils.waitForView;
* User interface tests for changing the playback speed.
*/
@RunWith(AndroidJUnit4.class)
@IgnoreOnCi
public class SpeedChangeTest {
@Rule
@ -68,9 +69,7 @@ public class SpeedChangeTest {
UserPreferences.setPlaybackSpeedArray(new String[] {"1.00", "2.00", "3.00"});
availableSpeeds = UserPreferences.getPlaybackSpeedArray();
context.sendBroadcast(new Intent(PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
Awaitility.await().until(() -> !PlaybackService.isRunning);
EspressoTestUtils.tryKillPlaybackService();
activityRule.launchActivity(new Intent());
}
@ -88,7 +87,7 @@ public class SpeedChangeTest {
public void testChangeSpeedPlaying() {
onView(isRoot()).perform(waitForView(withId(R.id.butPlay), 1000));
onView(withId(R.id.butPlay)).perform(click());
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(()
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(()
-> activityRule.getActivity().getPlaybackController().getStatus() == PlayerStatus.PLAYING);
clickThroughSpeeds();
}
@ -97,10 +96,10 @@ public class SpeedChangeTest {
public void testChangeSpeedPaused() {
onView(isRoot()).perform(waitForView(withId(R.id.butPlay), 1000));
onView(withId(R.id.butPlay)).perform(click());
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(()
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(()
-> activityRule.getActivity().getPlaybackController().getStatus() == PlayerStatus.PLAYING);
onView(withId(R.id.butPlay)).perform(click());
Awaitility.await().atMost(1, TimeUnit.SECONDS).until(()
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(()
-> activityRule.getActivity().getPlaybackController().getStatus() == PlayerStatus.PAUSED);
clickThroughSpeeds();
}

View File

@ -5,6 +5,7 @@ import android.graphics.Bitmap;
import android.util.Log;
import de.danoeh.antennapod.core.event.FeedListUpdateEvent;
import de.danoeh.antennapod.core.util.playback.Playable;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
@ -87,13 +88,13 @@ public class UITestUtils {
out.close();
int id = server.serveFile(feedFile);
Assert.assertTrue(id != -1);
return String.format("%s/files/%d", HTTPBin.BASE_URL, id);
return String.format("%s/files/%d", server.getBaseUrl(), id);
}
private String hostFile(File file) {
int id = server.serveFile(file);
Assert.assertTrue(id != -1);
return String.format("%s/files/%d", HTTPBin.BASE_URL, id);
return String.format("%s/files/%d", server.getBaseUrl(), id);
}
private File newBitmapFile(String name) throws IOException {
@ -204,12 +205,14 @@ public class UITestUtils {
}
public PlaybackController getPlaybackController(MainActivity mainActivity) {
ExternalPlayerFragment fragment = (ExternalPlayerFragment)mainActivity.getSupportFragmentManager().findFragmentByTag(ExternalPlayerFragment.TAG);
ExternalPlayerFragment fragment = (ExternalPlayerFragment) mainActivity.getSupportFragmentManager()
.findFragmentByTag(ExternalPlayerFragment.TAG);
return fragment.getPlaybackControllerTestingOnly();
}
public FeedMedia getCurrentMedia(MainActivity mainActivity) {
return (FeedMedia)getPlaybackController(mainActivity).getMedia();
public FeedMedia getCurrentMedia() {
Playable playable = Playable.PlayableUtils.createInstanceFromPreferences(context);
return (FeedMedia) playable;
}
public void setMediaFileName(String filename) {

View File

@ -39,9 +39,6 @@ import de.danoeh.antennapod.BuildConfig;
*/
public class HTTPBin extends NanoHTTPD {
private static final String TAG = "HTTPBin";
public static final int PORT = 8124;
public static final String BASE_URL = "http://127.0.0.1:" + HTTPBin.PORT;
private static final String MIME_HTML = "text/html";
private static final String MIME_PLAIN = "text/plain";
@ -49,10 +46,14 @@ public class HTTPBin extends NanoHTTPD {
private final List<File> servedFiles;
public HTTPBin() {
super(PORT);
super(0); // Let system pick a free port
this.servedFiles = new ArrayList<>();
}
public String getBaseUrl() {
return "http://127.0.0.1:" + getListeningPort();
}
/**
* Adds the given file to the server.
*

View File

@ -215,7 +215,7 @@ public class DownloadService extends Service {
downloadCompletionThread.interrupt();
try {
downloadCompletionThread.join();
downloadCompletionThread.join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

View File

@ -985,23 +985,15 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
if (item != null) {
if (ended || smartMarkAsPlayed ||
(skipped && !UserPreferences.shouldSkipKeepEpisode())) {
if (ended || smartMarkAsPlayed
|| (skipped && !UserPreferences.shouldSkipKeepEpisode())) {
// only mark the item as played if we're not keeping it anyways
DBWriter.markItemPlayed(item, FeedItem.PLAYED, ended);
try {
final List<FeedItem> queue = taskManager.getQueue();
if (QueueAccess.ItemListAccess(queue).contains(item.getId())) {
// don't know if it actually matters to not autodownload when smart mark as played is triggered
DBWriter.removeQueueItem(PlaybackService.this, ended, item);
}
} catch (InterruptedException e) {
e.printStackTrace();
// isInQueue remains false
}
// don't know if it actually matters to not autodownload when smart mark as played is triggered
DBWriter.removeQueueItem(PlaybackService.this, ended, item);
// Delete episode if enabled
if (item.getFeed().getPreferences().getCurrentAutoDelete() &&
(!item.isTagged(FeedItem.TAG_FAVORITE) || !UserPreferences.shouldFavoriteKeepEpisode())) {
if (item.getFeed().getPreferences().getCurrentAutoDelete()
&& (!item.isTagged(FeedItem.TAG_FAVORITE) || !UserPreferences.shouldFavoriteKeepEpisode())) {
DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId());
Log.d(TAG, "Episode Deleted");
}