Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.OffsetDateTime;
import java.util.List;

import static org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper.getThumbnailsFromLiveStreamItem;
Expand All @@ -19,17 +20,25 @@ public class MediaCCCLiveStreamKioskExtractor implements StreamInfoItemExtractor
private final String group;
private final JsonObject roomInfo;

@Nonnull
private final JsonObject currentTalk;

public MediaCCCLiveStreamKioskExtractor(final JsonObject conferenceInfo,
final String group,
final JsonObject roomInfo) {
this.conferenceInfo = conferenceInfo;
this.group = group;
this.roomInfo = roomInfo;
this.currentTalk = roomInfo.getObject("talks").getObject("current");
}

@Override
public String getName() throws ParsingException {
return roomInfo.getObject("talks").getObject("current").getString("title");
if (isBreak()) {
return roomInfo.getString("display") + " - Pause";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How MediaCCC's website displays paused rooms? I don't think hardcoding - Pause at the end of a room name is a good idea for localization purposes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what else do you suggest? just remove it? Or use "Break"?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know so let's use this for now :P

} else {
return currentTalk.getString("title");
}
}

@Override
Expand Down Expand Up @@ -95,6 +104,18 @@ public String getTextualUploadDate() throws ParsingException {
@Nullable
@Override
public DateWrapper getUploadDate() throws ParsingException {
return null;
if (isBreak()) {
return new DateWrapper(OffsetDateTime.parse(currentTalk.getString("fstart")));
} else {
return new DateWrapper(OffsetDateTime.parse(conferenceInfo.getString("startsAt")));
}
}

/**
* Whether the current "talk" is a talk or a pause.
*/
private boolean isBreak() {
return OffsetDateTime.parse(currentTalk.getString("fstart")).isBefore(OffsetDateTime.now())
|| "gap".equals(currentTalk.getString("special"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,18 @@ public static JsonArray getLiveStreams(final Downloader downloader,
return liveStreams;
}

/**
* Reset cached live stream data.
*
* <p>
* This is a temporary method which can be used to reset the cached live stream data until a
* caching policy for {@link #getLiveStreams(Downloader, Localization)} is implemented.
* </p>
*/
public static void resetCachedLiveStreamInfo() {
liveStreams = null;
}

/**
* Get an {@link Image} list from a given image logo URL.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class DownloaderFactory {

private static DownloaderType cachedDownloaderType;

private static DownloaderType getDownloaderType() {
static DownloaderType getDownloaderType() {
if (cachedDownloaderType == null) {
cachedDownloaderType = determineDownloaderType();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.schabi.newpipe.downloader;

import org.junit.jupiter.api.extension.ExtendWith;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* Use this to annotate tests methods/classes that should only be run when the downloader is of type
* {@link DownloaderType#MOCK} or {@link DownloaderType#RECORDING}. This should be used when e.g. an
* extractor returns different results each time because the underlying service web page does so. In
* that case it makes sense to only run the tests with the mock downloader, since the real web page
* is not reliable, but we still want to make sure that the code correctly interprets the stored and
* mocked web page data.
* @see MockOnlyCondition
*/
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(MockOnlyCondition.class)
public @interface MockOnly {

/**
* The reason why the test is mockonly.
*/
String value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.schabi.newpipe.downloader;

import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;

/**
* @see MockOnly
*/
public class MockOnlyCondition implements ExecutionCondition {
private static final String MOCK_ONLY_REASON = "Mock only";

@Override
public ConditionEvaluationResult evaluateExecutionCondition(final ExtensionContext context) {
if (DownloaderFactory.getDownloaderType() == DownloaderType.REAL) {
return ConditionEvaluationResult.disabled(MOCK_ONLY_REASON);
} else {
return ConditionEvaluationResult.enabled(MOCK_ONLY_REASON);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
package org.schabi.newpipe.extractor.services.media_ccc;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.MockOnly;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
import org.schabi.newpipe.extractor.services.DefaultSimpleExtractorTest;
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCLiveStreamKiosk;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestListOfItems;

public class MediaCCCLiveStreamListExtractorTest extends DefaultSimpleExtractorTest<KioskExtractor> {
private static final String LIVE_KIOSK_ID = MediaCCCLiveStreamKiosk.KIOSK_ID;

@Override
protected KioskExtractor createExtractor() throws Exception {
Expand All @@ -19,4 +28,95 @@ public void getConferencesListTest() {
assertDoesNotThrow(() -> extractor().getInitialPage().getItems());
}

/**
* Test against the media.ccc.de livestream API endpoint
* and ensure that no exceptions are thrown.
*/
public static class LiveDataTest extends DefaultSimpleExtractorTest<KioskExtractor> {

@BeforeAll
@Override
public void setUp() throws Exception {
MediaCCCTestUtils.ensureStateless();
super.setUp();
}

@Override
protected KioskExtractor createExtractor() throws Exception {
return MediaCCC.getKioskList().getExtractorById(LIVE_KIOSK_ID, null);
}

@Test
void getConferencesListTest() throws Exception {
final ListExtractor.InfoItemsPage liveStreamPage = extractor().getInitialPage();
final List<InfoItem> items = liveStreamPage.getItems();
if (items.isEmpty()) {
// defaultTestListOfItems() fails, if items is empty.
// This can happen if there are no current live streams.
// In this case, we just check if an exception was thrown
assertTrue(liveStreamPage.getErrors().isEmpty());
} else {
defaultTestListOfItems(MediaCCC, items, liveStreamPage.getErrors());
}
}

}

/**
* Test conferences which are available via the API for C3voc internal testing,
* but not intended to be shown to users.
*/
@MockOnly("The live stream API returns different data depending on if and what conferences"
+ " are running. The PreparationTest tests a conference which is used "
+ "for internal testing.")
public static class PreparationTest extends DefaultSimpleExtractorTest<KioskExtractor> {

@BeforeAll
@Override
public void setUp() throws Exception {
MediaCCCTestUtils.ensureStateless();
super.setUp();
}

@Override
protected KioskExtractor createExtractor() throws Exception {
return MediaCCC.getKioskList().getExtractorById(LIVE_KIOSK_ID, null);
}

@Test
void getConferencesListTest() throws Exception {
// Testing conferences and the corresponding talks should not be extracted.
assertTrue(extractor().getInitialPage().getItems().isEmpty());
}
}

/**
* Test a running conference.
*/
@MockOnly("The live stream API returns different data depending on if and what conferences"
+ " are running. Using mocks to ensure that there are conferences & talks to extract.")
public static class LiveConferenceTest extends DefaultSimpleExtractorTest<KioskExtractor> {

@BeforeAll
@Override
public void setUp() throws Exception {
MediaCCCTestUtils.ensureStateless();
super.setUp();
}

@Override
protected KioskExtractor createExtractor() throws Exception {
return MediaCCC.getKioskList().getExtractorById(LIVE_KIOSK_ID, null);
}

@Test
void getConferencesListTest() throws Exception {
final ListExtractor.InfoItemsPage liveStreamPage = extractor().getInitialPage();
final List<InfoItem> items = liveStreamPage.getItems();
assertEquals(6, items.size());
defaultTestListOfItems(MediaCCC, items, liveStreamPage.getErrors());

}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.schabi.newpipe.extractor.services.media_ccc;

import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper;

public final class MediaCCCTestUtils {

/**
* Clears static MediaCCC states.
*
* <p>
* This method needs to be called in every class before running and recording mock tests.
* </p>
*/
public static void ensureStateless() {
MediaCCCParsingHelper.resetCachedLiveStreamInfo();
}

}

Large diffs are not rendered by default.

Loading
Loading