Merge pull request #1092 from Stypox/channel-tabs-improvements

Channel tabs code improvements
This commit is contained in:
Stypox 2023-08-06 21:44:10 +02:00 committed by GitHub
commit 7936987955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 2573 additions and 2574 deletions

View File

@ -43,9 +43,9 @@ public final class YoutubeChannelHelper {
} }
// If the URL is not a /channel URL, we need to use the navigation/resolve_url endpoint of // If the URL is not a /channel URL, we need to use the navigation/resolve_url endpoint of
// the InnerTube API to get the channel id. // the InnerTube API to get the channel id. If this fails or if the URL is not a /channel
// Otherwise, we couldn't get information about the channel associated with this URL, if // URL, then no information about the channel associated with this URL was found,
// there is one. // so the unresolved url will be returned.
if (!channelId[0].equals("channel")) { if (!channelId[0].equals("channel")) {
final byte[] body = JsonWriter.string( final byte[] body = JsonWriter.string(
prepareDesktopJsonBuilder(Localization.DEFAULT, ContentCountry.DEFAULT) prepareDesktopJsonBuilder(Localization.DEFAULT, ContentCountry.DEFAULT)
@ -78,6 +78,7 @@ public final class YoutubeChannelHelper {
} }
} }
// return the unresolved URL
return channelId[1]; return channelId[1];
} }
@ -110,11 +111,11 @@ public final class YoutubeChannelHelper {
* Fetch a YouTube channel tab response, using the given channel ID and tab parameters. * Fetch a YouTube channel tab response, using the given channel ID and tab parameters.
* *
* <p> * <p>
* Redirections to other channels such as are supported to up to 3 redirects, which could * Redirections to other channels are supported to up to 3 redirects, which could happen for
* happen for instance for localized channels or auto-generated ones such as the {@code Movies * instance for localized channels or for auto-generated ones. For instance, there are three IDs
* and Shows} (channel IDs {@code UCuJcl0Ju-gPDoksRjK1ya-w}, {@code UChBfWrfBXL9wS6tQtgjt_OQ} * of the auto-generated "Movies and Shows" channel, i.e. {@code UCuJcl0Ju-gPDoksRjK1ya-w},
* and {@code UCok7UTQQEP1Rsctxiv3gwSQ} of this channel redirect to the * {@code UChBfWrfBXL9wS6tQtgjt_OQ} and {@code UCok7UTQQEP1Rsctxiv3gwSQ}, and they all redirect
* {@code UClgRkhTL3_hImCAmdLfDE4g} one). * to the {@code UClgRkhTL3_hImCAmdLfDE4g} one.
* </p> * </p>
* *
* @param channelId a valid YouTube channel ID * @param channelId a valid YouTube channel ID
@ -177,7 +178,7 @@ public final class YoutubeChannelHelper {
} }
if (ajaxJson == null) { if (ajaxJson == null) {
throw new ExtractionException("Got no channel response"); throw new ExtractionException("Got no channel response after 3 redirects");
} }
defaultAlertsCheck(ajaxJson); defaultAlertsCheck(ajaxJson);

View File

@ -57,6 +57,7 @@ import javax.annotation.Nullable;
public class YoutubeChannelExtractor extends ChannelExtractor { public class YoutubeChannelExtractor extends ChannelExtractor {
private JsonObject jsonResponse; private JsonObject jsonResponse;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType") @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private Optional<YoutubeChannelHelper.ChannelHeader> channelHeader; private Optional<YoutubeChannelHelper.ChannelHeader> channelHeader;
@ -89,6 +90,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
"EgZ2aWRlb3PyBgQKAjoA", getExtractorLocalization(), getExtractorContentCountry()); "EgZ2aWRlb3PyBgQKAjoA", getExtractorLocalization(), getExtractorContentCountry());
jsonResponse = data.jsonResponse; jsonResponse = data.jsonResponse;
channelHeader = YoutubeChannelHelper.getChannelHeader(jsonResponse);
channelId = data.channelId; channelId = data.channelId;
channelAgeGateRenderer = getChannelAgeGateRenderer(); channelAgeGateRenderer = getChannelAgeGateRenderer();
} }
@ -115,12 +117,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
} }
@Nonnull @Nonnull
private Optional<YoutubeChannelHelper.ChannelHeader> getChannelHeader() { private Optional<JsonObject> getChannelHeaderJson() {
//noinspection OptionalAssignedToNull return channelHeader.map(it -> it.json);
if (channelHeader == null) {
channelHeader = YoutubeChannelHelper.getChannelHeader(jsonResponse);
}
return channelHeader;
} }
@Nonnull @Nonnull
@ -136,9 +134,9 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
@Nonnull @Nonnull
@Override @Override
public String getId() throws ParsingException { public String getId() throws ParsingException {
return getChannelHeader() return getChannelHeaderJson()
.flatMap(header -> Optional.ofNullable(header.json.getString("channelId")) .flatMap(header -> Optional.ofNullable(header.getString("channelId"))
.or(() -> Optional.ofNullable(header.json.getObject("navigationEndpoint") .or(() -> Optional.ofNullable(header.getObject("navigationEndpoint")
.getObject("browseEndpoint") .getObject("browseEndpoint")
.getString("browseId")) .getString("browseId"))
)) ))
@ -160,8 +158,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
return metadataRendererTitle; return metadataRendererTitle;
} }
return getChannelHeader().flatMap(header -> { return getChannelHeaderJson().flatMap(header -> {
final Object title = header.json.get("title"); final Object title = header.get("title");
if (title instanceof String) { if (title instanceof String) {
return Optional.of((String) title); return Optional.of((String) title);
} else if (title instanceof JsonObject) { } else if (title instanceof JsonObject) {
@ -180,7 +178,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
if (channelAgeGateRenderer != null) { if (channelAgeGateRenderer != null) {
avatarJsonObjectContainer = channelAgeGateRenderer; avatarJsonObjectContainer = channelAgeGateRenderer;
} else { } else {
avatarJsonObjectContainer = getChannelHeader().map(header -> header.json) avatarJsonObjectContainer = getChannelHeaderJson()
.orElseThrow(() -> new ParsingException("Could not get avatar URL")); .orElseThrow(() -> new ParsingException("Could not get avatar URL"));
} }
@ -196,8 +194,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
return ""; return "";
} }
return getChannelHeader().flatMap(header -> Optional.ofNullable( return getChannelHeaderJson().flatMap(header -> Optional.ofNullable(
header.json.getObject("banner") header.getObject("banner")
.getArray("thumbnails") .getArray("thumbnails")
.getObject(0) .getObject(0)
.getString("url"))) .getString("url")))
@ -226,9 +224,9 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
return UNKNOWN_SUBSCRIBER_COUNT; return UNKNOWN_SUBSCRIBER_COUNT;
} }
final Optional<YoutubeChannelHelper.ChannelHeader> headerOpt = getChannelHeader(); final Optional<JsonObject> headerOpt = getChannelHeaderJson();
if (headerOpt.isPresent()) { if (headerOpt.isPresent()) {
final JsonObject header = headerOpt.get().json; final JsonObject header = headerOpt.get();
JsonObject textObject = null; JsonObject textObject = null;
if (header.has("subscriberCountText")) { if (header.has("subscriberCountText")) {
@ -285,9 +283,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
return false; return false;
} }
final Optional<YoutubeChannelHelper.ChannelHeader> headerOpt = getChannelHeader(); if (channelHeader.isPresent()) {
if (headerOpt.isPresent()) { final YoutubeChannelHelper.ChannelHeader header = channelHeader.get();
final YoutubeChannelHelper.ChannelHeader header = headerOpt.get();
// The CarouselHeaderRenderer does not contain any verification badges. // The CarouselHeaderRenderer does not contain any verification badges.
// Since it is only shown on YT-internal channels or on channels of large organizations // Since it is only shown on YT-internal channels or on channels of large organizations

View File

@ -23,7 +23,6 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeChannelHelper.getChannelResponse; import static org.schabi.newpipe.extractor.services.youtube.YoutubeChannelHelper.getChannelResponse;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeChannelHelper.resolveChannelId; import static org.schabi.newpipe.extractor.services.youtube.YoutubeChannelHelper.resolveChannelId;
@ -299,20 +298,20 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
.getObject("content"); .getObject("content");
if (richItem.has("videoRenderer")) { if (richItem.has("videoRenderer")) {
getCommitVideoConsumer(collector, timeAgoParser, channelIds).accept( getCommitVideoConsumer(collector, timeAgoParser, channelIds,
richItem.getObject("videoRenderer")); richItem.getObject("videoRenderer"));
} else if (richItem.has("reelItemRenderer")) { } else if (richItem.has("reelItemRenderer")) {
getCommitReelItemConsumer(collector, timeAgoParser, channelIds).accept( getCommitReelItemConsumer(collector, timeAgoParser, channelIds,
richItem.getObject("reelItemRenderer")); richItem.getObject("reelItemRenderer"));
} else if (richItem.has("playlistRenderer")) { } else if (richItem.has("playlistRenderer")) {
getCommitPlaylistConsumer(collector, channelIds).accept( getCommitPlaylistConsumer(collector, channelIds,
item.getObject("playlistRenderer")); item.getObject("playlistRenderer"));
} }
} else if (item.has("gridVideoRenderer")) { } else if (item.has("gridVideoRenderer")) {
getCommitVideoConsumer(collector, timeAgoParser, channelIds).accept( getCommitVideoConsumer(collector, timeAgoParser, channelIds,
item.getObject("gridVideoRenderer")); item.getObject("gridVideoRenderer"));
} else if (item.has("gridPlaylistRenderer")) { } else if (item.has("gridPlaylistRenderer")) {
getCommitPlaylistConsumer(collector, channelIds).accept( getCommitPlaylistConsumer(collector, channelIds,
item.getObject("gridPlaylistRenderer")); item.getObject("gridPlaylistRenderer"));
} else if (item.has("gridChannelRenderer")) { } else if (item.has("gridChannelRenderer")) {
collector.commit(new YoutubeChannelInfoItemExtractor( collector.commit(new YoutubeChannelInfoItemExtractor(
@ -336,13 +335,12 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
return Optional.empty(); return Optional.empty();
} }
@Nonnull private void getCommitVideoConsumer(@Nonnull final MultiInfoItemsCollector collector,
private Consumer<JsonObject> getCommitVideoConsumer( @Nonnull final TimeAgoParser timeAgoParser,
@Nonnull final MultiInfoItemsCollector collector, @Nonnull final List<String> channelIds,
@Nonnull final TimeAgoParser timeAgoParser, @Nonnull final JsonObject jsonObject) {
@Nonnull final List<String> channelIds) { collector.commit(
return videoRenderer -> collector.commit( new YoutubeStreamInfoItemExtractor(jsonObject, timeAgoParser) {
new YoutubeStreamInfoItemExtractor(videoRenderer, timeAgoParser) {
@Override @Override
public String getUploaderName() throws ParsingException { public String getUploaderName() throws ParsingException {
if (channelIds.size() >= 2) { if (channelIds.size() >= 2) {
@ -361,13 +359,12 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
}); });
} }
@Nonnull private void getCommitReelItemConsumer(@Nonnull final MultiInfoItemsCollector collector,
private Consumer<JsonObject> getCommitReelItemConsumer( @Nonnull final TimeAgoParser timeAgoParser,
@Nonnull final MultiInfoItemsCollector collector, @Nonnull final List<String> channelIds,
@Nonnull final TimeAgoParser timeAgoParser, @Nonnull final JsonObject jsonObject) {
@Nonnull final List<String> channelIds) { collector.commit(
return reelItemRenderer -> collector.commit( new YoutubeReelInfoItemExtractor(jsonObject, timeAgoParser) {
new YoutubeReelInfoItemExtractor(reelItemRenderer, timeAgoParser) {
@Override @Override
public String getUploaderName() throws ParsingException { public String getUploaderName() throws ParsingException {
if (channelIds.size() >= 2) { if (channelIds.size() >= 2) {
@ -386,12 +383,11 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
}); });
} }
@Nonnull private void getCommitPlaylistConsumer(@Nonnull final MultiInfoItemsCollector collector,
private Consumer<JsonObject> getCommitPlaylistConsumer( @Nonnull final List<String> channelIds,
@Nonnull final MultiInfoItemsCollector collector, @Nonnull final JsonObject jsonObject) {
@Nonnull final List<String> channelIds) { collector.commit(
return playlistRenderer -> collector.commit( new YoutubePlaylistInfoItemExtractor(jsonObject) {
new YoutubePlaylistInfoItemExtractor(playlistRenderer) {
@Override @Override
public String getUploaderName() throws ParsingException { public String getUploaderName() throws ParsingException {
if (channelIds.size() >= 2) { if (channelIds.size() >= 2) {

View File

@ -1,6 +1,7 @@
package org.schabi.newpipe.extractor.services.youtube.extractors; package org.schabi.newpipe.extractor.services.youtube.extractors;
import org.schabi.newpipe.extractor.InfoItem; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.Page;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor;
@ -12,14 +13,11 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubePlaylistLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubePlaylistLinkHandlerFactory;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import javax.annotation.Nonnull;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import javax.annotation.Nonnull;
/** /**
* A {@link ChannelTabExtractor} for YouTube system playlists using a * A {@link ChannelTabExtractor} for YouTube system playlists using a
@ -74,35 +72,19 @@ public class YoutubeChannelTabPlaylistExtractor extends ChannelTabExtractor {
@Nonnull @Nonnull
@Override @Override
public InfoItemsPage<InfoItem> getInitialPage() throws IOException, ExtractionException { public InfoItemsPage getInitialPage() throws IOException, ExtractionException {
if (!playlistExisting) { if (!playlistExisting) {
return InfoItemsPage.emptyPage(); return InfoItemsPage.emptyPage();
} }
return playlistExtractorInstance.getInitialPage();
final InfoItemsPage<StreamInfoItem> playlistInitialPage =
playlistExtractorInstance.getInitialPage();
// We can't provide the playlist page as it is due to a type conflict, we need to wrap the
// page items and provide a new InfoItemsPage
final List<InfoItem> infoItems = new ArrayList<>(playlistInitialPage.getItems());
return new InfoItemsPage<>(infoItems, playlistInitialPage.getNextPage(),
playlistInitialPage.getErrors());
} }
@Override @Override
public InfoItemsPage<InfoItem> getPage(final Page page) public InfoItemsPage getPage(final Page page) throws IOException, ExtractionException {
throws IOException, ExtractionException {
if (!playlistExisting) { if (!playlistExisting) {
return InfoItemsPage.emptyPage(); return InfoItemsPage.emptyPage();
} }
return playlistExtractorInstance.getPage(page);
final InfoItemsPage<StreamInfoItem> playlistPage = playlistExtractorInstance.getPage(page);
// We can't provide the playlist page as it is due to a type conflict, we need to wrap the
// page items and provide a new InfoItemsPage
final List<InfoItem> infoItems = new ArrayList<>(playlistPage.getItems());
return new InfoItemsPage<>(infoItems, playlistPage.getNextPage(),
playlistPage.getErrors());
} }
/** /**

View File

@ -151,8 +151,8 @@ public class ExtractorAsserts {
"'" + shouldBeContained + "' should be contained inside '" + container + "'"); "'" + shouldBeContained + "' should be contained inside '" + container + "'");
} }
public static void assertTabsContained(@Nonnull final List<ListLinkHandler> tabs, public static void assertTabsContain(@Nonnull final List<ListLinkHandler> tabs,
@Nonnull final String... expectedTabs) { @Nonnull final String... expectedTabs) {
final Set<String> tabSet = tabs.stream() final Set<String> tabSet = tabs.stream()
.map(linkHandler -> linkHandler.getContentFilters().get(0)) .map(linkHandler -> linkHandler.getContentFilters().get(0))
.collect(Collectors.toUnmodifiableSet()); .collect(Collectors.toUnmodifiableSet());

View File

@ -11,7 +11,7 @@ import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs;
import org.schabi.newpipe.extractor.services.BaseChannelExtractorTest; import org.schabi.newpipe.extractor.services.BaseChannelExtractorTest;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContained; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContain;
import static org.schabi.newpipe.extractor.ServiceList.Bandcamp; import static org.schabi.newpipe.extractor.ServiceList.Bandcamp;
public class BandcampChannelExtractorTest implements BaseChannelExtractorTest { public class BandcampChannelExtractorTest implements BaseChannelExtractorTest {
@ -84,7 +84,7 @@ public class BandcampChannelExtractorTest implements BaseChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.ALBUMS); assertTabsContain(extractor.getTabs(), ChannelTabs.ALBUMS);
} }
@Test @Test

View File

@ -3,22 +3,27 @@ package org.schabi.newpipe.extractor.services.bandcamp;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderTestImpl; import org.schabi.newpipe.downloader.DownloaderTestImpl;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.BaseListExtractorTest; import org.schabi.newpipe.extractor.services.BaseListExtractorTest;
import org.schabi.newpipe.extractor.services.DefaultListExtractorTest;
import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampChannelTabExtractor; import org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampChannelTabExtractor;
import java.io.IOException; import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.schabi.newpipe.extractor.ServiceList.Bandcamp; import static org.schabi.newpipe.extractor.ServiceList.Bandcamp;
import static org.schabi.newpipe.extractor.ServiceList.PeerTube;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestRelatedItems; import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestRelatedItems;
class BandcampChannelTabExtractorTest { class BandcampChannelTabExtractorTest {
static class Tracks implements BaseListExtractorTest { static class Tracks extends DefaultListExtractorTest<ChannelTabExtractor> {
private static BandcampChannelTabExtractor extractor; private static BandcampChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -29,50 +34,17 @@ class BandcampChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return Bandcamp; }
public void testServiceId() throws Exception { @Override public String expectedName() throws Exception { return ChannelTabs.TRACKS; }
assertEquals(Bandcamp.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "2464198920"; }
} @Override public String expectedUrlContains() throws Exception { return "https://wintergatan.bandcamp.com/track"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://wintergatan.bandcamp.com/track"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
@Override @Override public boolean expectedHasMoreItems() { return false; }
public void testName() throws Exception {
assertEquals(ChannelTabs.TRACKS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("2464198920", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://wintergatan.bandcamp.com/track", extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://wintergatan.bandcamp.com/track", extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
// Bandcamp only return a single page
}
} }
static class Albums implements BaseListExtractorTest { static class Albums extends DefaultListExtractorTest<ChannelTabExtractor> {
private static BandcampChannelTabExtractor extractor; private static BandcampChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -83,46 +55,13 @@ class BandcampChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return Bandcamp; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.ALBUMS; }
assertEquals(Bandcamp.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "2450875064"; }
} @Override public String expectedUrlContains() throws Exception { return "https://toupie.bandcamp.com/album"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://toupie.bandcamp.com/album"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.PLAYLIST; }
@Override @Override public boolean expectedHasMoreItems() { return false; }
public void testName() throws Exception {
assertEquals(ChannelTabs.ALBUMS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("2450875064", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://toupie.bandcamp.com/album", extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://toupie.bandcamp.com/album", extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
// Bandcamp only return a single page
}
} }
} }

View File

@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContained; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContain;
import static org.schabi.newpipe.extractor.ServiceList.PeerTube; import static org.schabi.newpipe.extractor.ServiceList.PeerTube;
/** /**
@ -103,7 +103,7 @@ public class PeertubeAccountExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.CHANNELS); assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.CHANNELS);
} }
@Test @Test
@ -192,7 +192,7 @@ public class PeertubeAccountExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.CHANNELS); assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.CHANNELS);
} }
@Test @Test

View File

@ -3,10 +3,14 @@ package org.schabi.newpipe.extractor.services.peertube;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderTestImpl; import org.schabi.newpipe.downloader.DownloaderTestImpl;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.BaseListExtractorTest; import org.schabi.newpipe.extractor.services.BaseListExtractorTest;
import org.schabi.newpipe.extractor.services.DefaultListExtractorTest;
import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeChannelTabExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeChannelTabExtractor;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -16,7 +20,7 @@ import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestRela
class PeertubeAccountTabExtractorTest { class PeertubeAccountTabExtractorTest {
static class Videos implements BaseListExtractorTest { static class Videos extends DefaultListExtractorTest<ChannelTabExtractor> {
private static PeertubeChannelTabExtractor extractor; private static PeertubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -29,60 +33,17 @@ class PeertubeAccountTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
/*////////////////////////////////////////////////////////////////////////// @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
// Extractor @Override public StreamingService expectedService() throws Exception { return PeerTube; }
//////////////////////////////////////////////////////////////////////////*/ @Override public String expectedName() throws Exception { return ChannelTabs.VIDEOS; }
@Override public String expectedId() throws Exception { return "accounts/framasoft"; }
@Test @Override public String expectedUrlContains() throws Exception { return "https://framatube.org/accounts/framasoft/videos"; }
@Override @Override public String expectedOriginalUrlContains() throws Exception { return "https://framatube.org/accounts/framasoft/videos"; }
public void testServiceId() { @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
assertEquals(PeerTube.getServiceId(), extractor.getServiceId()); @Override public boolean expectedHasMoreItems() { return true; }
}
@Test
@Override
public void testName() throws ParsingException {
assertEquals(ChannelTabs.VIDEOS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("accounts/framasoft", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://framatube.org/accounts/framasoft/videos",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws ParsingException {
assertEquals("https://framatube.org/accounts/framasoft/videos",
extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
static class Channels implements BaseListExtractorTest { static class Channels extends DefaultListExtractorTest<ChannelTabExtractor> {
private static PeertubeChannelTabExtractor extractor; private static PeertubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -95,56 +56,13 @@ class PeertubeAccountTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
/*////////////////////////////////////////////////////////////////////////// @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
// Extractor @Override public StreamingService expectedService() throws Exception { return PeerTube; }
//////////////////////////////////////////////////////////////////////////*/ @Override public String expectedName() throws Exception { return ChannelTabs.CHANNELS; }
@Override public String expectedId() throws Exception { return "accounts/framasoft"; }
@Test @Override public String expectedUrlContains() throws Exception { return "https://framatube.org/accounts/framasoft/video-channels"; }
@Override @Override public String expectedOriginalUrlContains() throws Exception { return "https://framatube.org/accounts/framasoft/video-channels"; }
public void testServiceId() { @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.CHANNEL; }
assertEquals(PeerTube.getServiceId(), extractor.getServiceId()); @Override public boolean expectedHasMoreItems() { return true; }
}
@Test
@Override
public void testName() throws ParsingException {
assertEquals(ChannelTabs.CHANNELS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("accounts/framasoft", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://framatube.org/accounts/framasoft/video-channels",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws ParsingException {
assertEquals("https://framatube.org/accounts/framasoft/video-channels",
extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
} }

View File

@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContained; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContain;
import static org.schabi.newpipe.extractor.ServiceList.PeerTube; import static org.schabi.newpipe.extractor.ServiceList.PeerTube;
/** /**
@ -118,7 +118,7 @@ public class PeertubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS); assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS);
} }
@Test @Test
@ -223,7 +223,7 @@ public class PeertubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS); assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS);
} }
@Test @Test

View File

@ -1,25 +1,25 @@
package org.schabi.newpipe.extractor.services.peertube; package org.schabi.newpipe.extractor.services.peertube;
import static org.schabi.newpipe.extractor.ServiceList.PeerTube;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestGetPageInNewExtractor;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderTestImpl; import org.schabi.newpipe.downloader.DownloaderTestImpl;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.DefaultListExtractorTest;
import org.schabi.newpipe.extractor.services.BaseListExtractorTest;
import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeChannelTabExtractor; import org.schabi.newpipe.extractor.services.peertube.extractors.PeertubeChannelTabExtractor;
import java.io.IOException; import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.schabi.newpipe.extractor.ServiceList.PeerTube;
import static org.schabi.newpipe.extractor.services.DefaultTests.*;
class PeertubeChannelTabExtractorTest { class PeertubeChannelTabExtractorTest {
static class Videos implements BaseListExtractorTest { static class Videos extends DefaultListExtractorTest<ChannelTabExtractor> {
private static PeertubeChannelTabExtractor extractor; private static PeertubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -32,61 +32,14 @@ class PeertubeChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
/*////////////////////////////////////////////////////////////////////////// @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
// Extractor @Override public StreamingService expectedService() throws Exception { return PeerTube; }
//////////////////////////////////////////////////////////////////////////*/ @Override public String expectedName() throws Exception { return ChannelTabs.VIDEOS; }
@Override public String expectedId() throws Exception { return "video-channels/lqdn_channel@video.lqdn.fr"; }
@Test @Override public String expectedUrlContains() throws Exception { return "https://framatube.org/video-channels/lqdn_channel@video.lqdn.fr/videos"; }
@Override @Override public String expectedOriginalUrlContains() throws Exception { return "https://framatube.org/video-channels/lqdn_channel@video.lqdn.fr/videos"; }
public void testServiceId() { @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
assertEquals(PeerTube.getServiceId(), extractor.getServiceId()); @Override public boolean expectedHasMoreItems() { return true; }
}
@Test
@Override
public void testName() throws ParsingException {
assertEquals(ChannelTabs.VIDEOS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("video-channels/lqdn_channel@video.lqdn.fr", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://framatube.org/video-channels/lqdn_channel@video.lqdn.fr/videos",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws ParsingException {
assertEquals("https://framatube.org/video-channels/lqdn_channel@video.lqdn.fr/videos",
extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
/*//////////////////////////////////////////////////////////////////////////
// Additional Testing
//////////////////////////////////////////////////////////////////////////*/
@Test @Test
void testGetPageInNewExtractor() throws Exception { void testGetPageInNewExtractor() throws Exception {
@ -96,7 +49,7 @@ class PeertubeChannelTabExtractorTest {
} }
} }
static class Playlists implements BaseListExtractorTest { static class Playlists extends DefaultListExtractorTest<ChannelTabExtractor> {
private static PeertubeChannelTabExtractor extractor; private static PeertubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -109,51 +62,17 @@ class PeertubeChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return PeerTube; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.PLAYLISTS; }
assertEquals(PeerTube.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "video-channels/lqdn_channel@video.lqdn.fr"; }
} @Override public String expectedUrlContains() throws Exception { return "https://framatube.org/video-channels/lqdn_channel@video.lqdn.fr/video-playlists"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://framatube.org/video-channels/lqdn_channel@video.lqdn.fr/video-playlists"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.PLAYLIST; }
@Override @Override public boolean expectedHasMoreItems() { return false; }
public void testName() throws Exception {
assertEquals(ChannelTabs.PLAYLISTS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("video-channels/lqdn_channel@video.lqdn.fr", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://framatube.org/video-channels/lqdn_channel@video.lqdn.fr/video-playlists",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://framatube.org/video-channels/lqdn_channel@video.lqdn.fr/video-playlists",
extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
static class Channels implements BaseListExtractorTest { static class Channels extends DefaultListExtractorTest<ChannelTabExtractor> {
private static PeertubeChannelTabExtractor extractor; private static PeertubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -165,48 +84,13 @@ class PeertubeChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return PeerTube; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.CHANNELS; }
assertEquals(PeerTube.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "accounts/framasoft"; }
} @Override public String expectedUrlContains() throws Exception { return "https://framatube.org/accounts/framasoft/video-channels"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://framatube.org/accounts/framasoft/video-channels"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.CHANNEL; }
@Override @Override public boolean expectedHasMoreItems() { return true; }
public void testName() throws Exception {
assertEquals(ChannelTabs.CHANNELS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("accounts/framasoft", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://framatube.org/accounts/framasoft/video-channels",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://framatube.org/accounts/framasoft/video-channels",
extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
} }

View File

@ -12,7 +12,7 @@ import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudCha
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmpty; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmpty;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContained; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContain;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
/** /**
@ -96,7 +96,7 @@ public class SoundcloudChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.TRACKS, ChannelTabs.PLAYLISTS, assertTabsContain(extractor.getTabs(), ChannelTabs.TRACKS, ChannelTabs.PLAYLISTS,
ChannelTabs.ALBUMS); ChannelTabs.ALBUMS);
} }
@ -184,7 +184,7 @@ public class SoundcloudChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.TRACKS, ChannelTabs.PLAYLISTS, assertTabsContain(extractor.getTabs(), ChannelTabs.TRACKS, ChannelTabs.PLAYLISTS,
ChannelTabs.ALBUMS); ChannelTabs.ALBUMS);
} }

View File

@ -3,17 +3,21 @@ package org.schabi.newpipe.extractor.services.soundcloud;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderTestImpl; import org.schabi.newpipe.downloader.DownloaderTestImpl;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.BaseListExtractorTest; import org.schabi.newpipe.extractor.services.BaseListExtractorTest;
import org.schabi.newpipe.extractor.services.DefaultListExtractorTest;
import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudChannelTabExtractor; import org.schabi.newpipe.extractor.services.soundcloud.extractors.SoundcloudChannelTabExtractor;
import java.io.IOException; import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.schabi.newpipe.extractor.ServiceList.PeerTube;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestGetPageInNewExtractor; import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestGetPageInNewExtractor;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestMoreItems; import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestMoreItems;
@ -21,7 +25,7 @@ import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestRela
class SoundcloudChannelTabExtractorTest { class SoundcloudChannelTabExtractorTest {
static class Tracks implements BaseListExtractorTest { static class Tracks extends DefaultListExtractorTest<ChannelTabExtractor> {
private static SoundcloudChannelTabExtractor extractor; private static SoundcloudChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -32,51 +36,14 @@ class SoundcloudChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return SoundCloud; }
public void testServiceId() throws Exception { @Override public String expectedName() throws Exception { return ChannelTabs.TRACKS; }
assertEquals(SoundCloud.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "10494998"; }
} @Override public String expectedUrlContains() throws Exception { return "https://soundcloud.com/liluzivert/tracks"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://soundcloud.com/liluzivert/tracks"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
@Override @Override public boolean expectedHasMoreItems() { return true; }
public void testName() throws Exception {
assertEquals(ChannelTabs.TRACKS, extractor.getName());
}
@Test
@Override
public void testId() throws Exception {
assertEquals("10494998", extractor.getId());
}
@Test
@Override
public void testUrl() throws Exception {
assertEquals("https://soundcloud.com/liluzivert/tracks", extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://soundcloud.com/liluzivert/tracks", extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
/*//////////////////////////////////////////////////////////////////////////
// Additional Testing
//////////////////////////////////////////////////////////////////////////*/
@Test @Test
void testGetPageInNewExtractor() throws Exception { void testGetPageInNewExtractor() throws Exception {
@ -86,7 +53,7 @@ class SoundcloudChannelTabExtractorTest {
} }
} }
static class Playlists implements BaseListExtractorTest { static class Playlists extends DefaultListExtractorTest<ChannelTabExtractor> {
private static SoundcloudChannelTabExtractor extractor; private static SoundcloudChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -97,50 +64,17 @@ class SoundcloudChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return SoundCloud; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.PLAYLISTS; }
assertEquals(SoundCloud.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "323371733"; }
} @Override public String expectedUrlContains() throws Exception { return "https://soundcloud.com/trackaholic/sets"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://soundcloud.com/trackaholic/sets"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.PLAYLIST; }
@Override @Override public boolean expectedHasMoreItems() { return true; }
public void testName() throws Exception {
assertEquals(ChannelTabs.PLAYLISTS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("323371733", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://soundcloud.com/trackaholic/sets", extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://soundcloud.com/trackaholic/sets", extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
static class Albums implements BaseListExtractorTest { static class Albums extends DefaultListExtractorTest<ChannelTabExtractor> {
private static SoundcloudChannelTabExtractor extractor; private static SoundcloudChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -151,46 +85,13 @@ class SoundcloudChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return SoundCloud; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.ALBUMS; }
assertEquals(SoundCloud.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "4803918"; }
} @Override public String expectedUrlContains() throws Exception { return "https://soundcloud.com/bigsean-1/albums"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://soundcloud.com/bigsean-1/albums"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.PLAYLIST; }
@Override @Override public boolean expectedHasMoreItems() { return true; }
public void testName() throws Exception {
assertEquals(ChannelTabs.ALBUMS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("4803918", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://soundcloud.com/bigsean-1/albums", extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://soundcloud.com/bigsean-1/albums", extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
} }

View File

@ -7,7 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertContains; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertContains;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContained; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContain;
import static org.schabi.newpipe.extractor.ServiceList.YouTube; import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestGetPageInNewExtractor; import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestGetPageInNewExtractor;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
@ -233,8 +233,11 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS,
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS); ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
} }
@Test @Test
@ -327,8 +330,11 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.LIVESTREAMS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.LIVESTREAMS,
ChannelTabs.SHORTS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS); ChannelTabs.SHORTS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
} }
@Test @Test
@ -424,8 +430,11 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS,
ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS); ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
} }
@Test @Test
@ -545,8 +554,11 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS,
ChannelTabs.CHANNELS); ChannelTabs.CHANNELS);
assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
} }
@Test @Test
@ -639,8 +651,11 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS,
ChannelTabs.CHANNELS); ChannelTabs.CHANNELS);
assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
} }
@Test @Test
@ -730,8 +745,11 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS,
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS); ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
} }
@Test @Test
@ -846,7 +864,7 @@ public class YoutubeChannelExtractorTest {
public void testTabs() throws Exception { public void testTabs() throws Exception {
// Channel tabs which may be available and which will be extracted from channel system // Channel tabs which may be available and which will be extracted from channel system
// uploads playlists // uploads playlists
assertTabsContained(extractor.getTabs(), assertTabsContain(extractor.getTabs(),
ChannelTabs.VIDEOS, ChannelTabs.SHORTS, ChannelTabs.LIVESTREAMS); ChannelTabs.VIDEOS, ChannelTabs.SHORTS, ChannelTabs.LIVESTREAMS);
// Check if all tabs are not classic tabs, so that link handlers are of the appropriate // Check if all tabs are not classic tabs, so that link handlers are of the appropriate

View File

@ -1,34 +1,30 @@
package org.schabi.newpipe.extractor.services.youtube; package org.schabi.newpipe.extractor.services.youtube;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderFactory; import org.schabi.newpipe.downloader.DownloaderFactory;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.channel.ChannelExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs; import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.DefaultListExtractorTest;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.services.BaseListExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelTabExtractor; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelTabExtractor;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestMoreItems;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestRelatedItems;
class YoutubeChannelTabExtractorTest { class YoutubeChannelTabExtractorTest {
private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH
+ "services/youtube/extractor/channelTabs/"; + "services/youtube/extractor/channelTabs/";
static class Videos implements BaseListExtractorTest { static class Videos extends DefaultListExtractorTest<ChannelTabExtractor> {
private static YoutubeChannelTabExtractor extractor; private static YoutubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -40,52 +36,17 @@ class YoutubeChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return YouTube; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.VIDEOS; }
assertEquals(YouTube.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "UCTwECeGqMZee77BjdoYtI2Q"; }
} @Override public String expectedUrlContains() throws Exception { return "https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q/videos"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://www.youtube.com/user/creativecommons/videos"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
@Override @Override public boolean expectedHasMoreItems() { return true; }
public void testName() throws Exception {
assertEquals(ChannelTabs.VIDEOS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("UCTwECeGqMZee77BjdoYtI2Q", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://www.youtube.com/channel/UCTwECeGqMZee77BjdoYtI2Q/videos",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://www.youtube.com/user/creativecommons/videos",
extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
static class Playlists implements BaseListExtractorTest { static class Playlists extends DefaultListExtractorTest<ChannelTabExtractor> {
private static YoutubeChannelTabExtractor extractor; private static YoutubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -97,52 +58,17 @@ class YoutubeChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return YouTube; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.PLAYLISTS; }
assertEquals(YouTube.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "UC2DjFE7Xf11URZqWBigcVOQ"; }
} @Override public String expectedUrlContains() throws Exception { return "https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/playlists"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://www.youtube.com/@EEVblog/playlists"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.PLAYLIST; }
@Override @Override public boolean expectedHasMoreItems() { return true; }
public void testName() throws Exception {
assertEquals(ChannelTabs.PLAYLISTS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("UC2DjFE7Xf11URZqWBigcVOQ", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/playlists",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://www.youtube.com/@EEVblog/playlists",
extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
static class Channels implements BaseListExtractorTest { static class Channels extends DefaultListExtractorTest<ChannelTabExtractor> {
private static YoutubeChannelTabExtractor extractor; private static YoutubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -154,52 +80,17 @@ class YoutubeChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return YouTube; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.CHANNELS; }
assertEquals(YouTube.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "UC2DjFE7Xf11URZqWBigcVOQ"; }
} @Override public String expectedUrlContains() throws Exception { return "https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/channels"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/channels"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.CHANNEL; }
@Override @Override public boolean expectedHasMoreItems() { return true; }
public void testName() throws Exception {
assertEquals(ChannelTabs.CHANNELS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("UC2DjFE7Xf11URZqWBigcVOQ", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/channels",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/channels",
extractor.getUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
static class Livestreams implements BaseListExtractorTest { static class Livestreams extends DefaultListExtractorTest<ChannelTabExtractor> {
private static YoutubeChannelTabExtractor extractor; private static YoutubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -211,52 +102,17 @@ class YoutubeChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return YouTube; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.LIVESTREAMS; }
assertEquals(YouTube.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "UCR-DXc1voovS8nhAvccRZhg"; }
} @Override public String expectedUrlContains() throws Exception { return "https://www.youtube.com/channel/UCR-DXc1voovS8nhAvccRZhg/streams"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://www.youtube.com/c/JeffGeerling/streams"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
@Override @Override public boolean expectedHasMoreItems() { return true; }
public void testName() throws Exception {
assertEquals(ChannelTabs.LIVESTREAMS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("UCR-DXc1voovS8nhAvccRZhg", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://www.youtube.com/channel/UCR-DXc1voovS8nhAvccRZhg/streams",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://www.youtube.com/c/JeffGeerling/streams",
extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
static class Shorts implements BaseListExtractorTest { static class Shorts extends DefaultListExtractorTest<ChannelTabExtractor> {
private static YoutubeChannelTabExtractor extractor; private static YoutubeChannelTabExtractor extractor;
@BeforeAll @BeforeAll
@ -268,130 +124,80 @@ class YoutubeChannelTabExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return YouTube; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.SHORTS; }
assertEquals(YouTube.getServiceId(), extractor.getServiceId()); @Override public String expectedId() throws Exception { return "UCh8gHdtzO2tXd593_bjErWg"; }
} @Override public String expectedUrlContains() throws Exception { return "https://www.youtube.com/channel/UCh8gHdtzO2tXd593_bjErWg/shorts"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://www.youtube.com/channel/UCh8gHdtzO2tXd593_bjErWg/shorts"; }
@Test @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
@Override @Override public boolean expectedHasMoreItems() { return true; }
public void testName() throws Exception {
assertEquals(ChannelTabs.SHORTS, extractor.getName());
}
@Test
@Override
public void testId() throws ParsingException {
assertEquals("UCh8gHdtzO2tXd593_bjErWg", extractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://www.youtube.com/channel/UCh8gHdtzO2tXd593_bjErWg/shorts",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://www.youtube.com/channel/UCh8gHdtzO2tXd593_bjErWg/shorts",
extractor.getOriginalUrl());
}
@Test
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
} }
static class AgeRestrictedTabs implements BaseListExtractorTest {
private static ChannelTabExtractor videosTabExtractor; // TESTS FOR TABS OF AGE RESTRICTED CHANNELS
private static ChannelTabExtractor shortsTabExtractor; // Fetching the tabs individually would use the standard tabs without fallback to
// system playlists for stream tabs, we need to fetch the channel extractor to get the
// channel playlist tabs
// TODO: implement system playlists fallback in YoutubeChannelTabExtractor for stream
// tabs
static class AgeRestrictedTabsVideos extends DefaultListExtractorTest<ChannelTabExtractor> {
private static ChannelTabExtractor extractor;
@BeforeAll @BeforeAll
static void setUp() throws IOException, ExtractionException { static void setUp() throws IOException, ExtractionException {
YoutubeTestsUtils.ensureStateless(); YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "ageRestricted")); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "ageRestrictedTabsVideos"));
final ChannelExtractor extractor = YouTube.getChannelExtractor( final ChannelExtractor channelExtractor = YouTube.getChannelExtractor(
"https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig"); "https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig");
channelExtractor.fetchPage();
// the videos tab is the first one
extractor = YouTube.getChannelTabExtractor(channelExtractor.getTabs().get(0));
extractor.fetchPage(); extractor.fetchPage();
// Fetching the tabs individually would use the standard tabs without fallback to
// system playlists for stream tabs, we need to fetch the channel extractor to get the
// channel playlist tabs
// TODO: implement system playlists fallback in YoutubeChannelTabExtractor for stream
// tabs
final List<ListLinkHandler> tabs = extractor.getTabs();
videosTabExtractor = YouTube.getChannelTabExtractor(tabs.get(0));
videosTabExtractor.fetchPage();
shortsTabExtractor = YouTube.getChannelTabExtractor(tabs.get(1));
shortsTabExtractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return YouTube; }
public void testServiceId() { @Override public String expectedName() throws Exception { return ChannelTabs.VIDEOS; }
assertEquals(YouTube.getServiceId(), videosTabExtractor.getServiceId()); @Override public String expectedId() throws Exception { return "UCbfnHqxXs_K3kvaH-WlNlig"; }
assertEquals(YouTube.getServiceId(), shortsTabExtractor.getServiceId()); @Override public String expectedUrlContains() throws Exception { return "https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig/videos"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig/videos"; }
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
@Override public boolean expectedHasMoreItems() { return true; }
}
static class AgeRestrictedTabsShorts extends DefaultListExtractorTest<ChannelTabExtractor> {
private static ChannelTabExtractor extractor;
@BeforeAll
static void setUp() throws IOException, ExtractionException {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "ageRestrictedTabsShorts"));
final ChannelExtractor channelExtractor = YouTube.getChannelExtractor(
"https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig");
channelExtractor.fetchPage();
// the shorts tab is the second one
extractor = YouTube.getChannelTabExtractor(channelExtractor.getTabs().get(1));
extractor.fetchPage();
} }
@Test @Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override @Override public StreamingService expectedService() throws Exception { return YouTube; }
public void testName() throws Exception { @Override public String expectedName() throws Exception { return ChannelTabs.SHORTS; }
assertEquals(ChannelTabs.VIDEOS, videosTabExtractor.getName()); @Override public String expectedId() throws Exception { return "UCbfnHqxXs_K3kvaH-WlNlig"; }
assertEquals(ChannelTabs.SHORTS, shortsTabExtractor.getName()); @Override public String expectedUrlContains() throws Exception { return "https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig/shorts"; }
} @Override public String expectedOriginalUrlContains() throws Exception { return "https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig/shorts"; }
@Override public boolean expectedHasMoreItems() { return false; }
@Test
@Override
public void testId() throws ParsingException {
assertEquals("UCbfnHqxXs_K3kvaH-WlNlig", videosTabExtractor.getId());
assertEquals("UCbfnHqxXs_K3kvaH-WlNlig", shortsTabExtractor.getId());
}
@Test
@Override
public void testUrl() throws ParsingException {
assertEquals("https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig/videos",
videosTabExtractor.getUrl());
assertEquals("https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig/shorts",
shortsTabExtractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig/videos",
videosTabExtractor.getOriginalUrl());
assertEquals("https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig/shorts",
shortsTabExtractor.getOriginalUrl());
}
@Test @Test
@Override @Override
public void testRelatedItems() throws Exception { public void testRelatedItems() throws Exception {
defaultTestRelatedItems(videosTabExtractor); // this channel has no shorts, so an empty page is returned by the playlist extractor
// No shorts on this channel, the channel tab playlist extractor should return no assertTrue(extractor.getInitialPage().getItems().isEmpty());
// streams assertTrue(extractor.getInitialPage().getErrors().isEmpty());
assertTrue(shortsTabExtractor.getInitialPage().getItems().isEmpty());
}
@Test
@Override
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(videosTabExtractor);
// No shorts on this channel, the channel tab playlist extractor should return no
// streams
assertFalse(shortsTabExtractor.getInitialPage().hasNextPage());
} }
} }
} }

View File

@ -0,0 +1,88 @@
{
"request": {
"httpMethod": "GET",
"url": "https://www.youtube.com/sw.js",
"headers": {
"Origin": [
"https://www.youtube.com"
],
"Referer": [
"https://www.youtube.com"
],
"Accept-Language": [
"en-GB, en;q\u003d0.9"
]
},
"localization": {
"languageCode": "en",
"countryCode": "GB"
}
},
"response": {
"responseCode": 200,
"responseMessage": "",
"responseHeaders": {
"access-control-allow-credentials": [
"true"
],
"access-control-allow-origin": [
"https://www.youtube.com"
],
"alt-svc": [
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000"
],
"cache-control": [
"private, max-age\u003d0"
],
"content-security-policy-report-only": [
"require-trusted-types-for \u0027script\u0027;report-uri /cspreport"
],
"content-type": [
"text/javascript; charset\u003dutf-8"
],
"cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\""
],
"date": [
"Sun, 06 Aug 2023 11:54:54 GMT"
],
"expires": [
"Sun, 06 Aug 2023 11:54:54 GMT"
],
"origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
],
"p3p": [
"CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\""
],
"permissions-policy": [
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-form-factor\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
],
"report-to": [
"{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}"
],
"server": [
"ESF"
],
"set-cookie": [
"YSC\u003dIXSPROQ-CH8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 09-Nov-2020 11:54:54 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"CONSENT\u003dPENDING+942; expires\u003dTue, 05-Aug-2025 11:54:54 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
],
"strict-transport-security": [
"max-age\u003d31536000"
],
"x-content-type-options": [
"nosniff"
],
"x-frame-options": [
"SAMEORIGIN"
],
"x-xss-protection": [
"0"
]
},
"responseBody": "\n self.addEventListener(\u0027install\u0027, event \u003d\u003e {\n event.waitUntil(self.skipWaiting());\n });\n self.addEventListener(\u0027activate\u0027, event \u003d\u003e {\n event.waitUntil(\n self.clients.claim().then(() \u003d\u003e self.registration.unregister()));\n });\n ",
"latestUrl": "https://www.youtube.com/sw.js"
}
}

View File

@ -41,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Mon, 17 Jul 2023 20:14:18 GMT" "Sun, 06 Aug 2023 11:55:07 GMT"
], ],
"expires": [ "expires": [
"Mon, 17 Jul 2023 20:14:18 GMT" "Sun, 06 Aug 2023 11:55:07 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dgtpu5gh6Su4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dqCdA3bmpLFQ; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dTue, 20-Oct-2020 20:14:18 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 09-Nov-2020 11:55:07 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"CONSENT\u003dPENDING+016; expires\u003dWed, 16-Jul-2025 20:14:18 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+717; expires\u003dTue, 05-Aug-2025 11:55:07 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"