[YouTube] Implement age-restricted channels support, link handlers and channels tabs and tags changes on tests

Co-authored-by: ThetaDev <t.testboy@gmail.com>
This commit is contained in:
AudricV 2023-07-17 22:20:53 +02:00 committed by Stypox
parent eaf2600ce0
commit 684101c47d
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
3 changed files with 661 additions and 125 deletions

View File

@ -5,13 +5,12 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertContains;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContained;
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.defaultTestMoreItems;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestRelatedItems;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -20,14 +19,18 @@ import org.schabi.newpipe.downloader.DownloaderTestImpl;
import org.schabi.newpipe.extractor.ExtractorAsserts;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs;
import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException;
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.ReadyChannelTabListLinkHandler;
import org.schabi.newpipe.extractor.services.BaseChannelExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelExtractor;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelTabPlaylistExtractor;
import java.io.IOException;
import java.util.List;
/**
* Test for {@link ChannelExtractor}
@ -132,19 +135,19 @@ public class YoutubeChannelExtractorTest {
}
public static class NotSupported {
static class SystemTopic {
@BeforeAll
public static void setUp() throws IOException {
static void setUp() throws IOException {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "notSupported"));
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "systemTopic"));
}
@Test
void noVideoTab() throws Exception {
void noSupportedTab() throws Exception {
final ChannelExtractor extractor = YouTube.getChannelExtractor("https://invidio.us/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ");
extractor.fetchPage();
assertThrows(ContentNotSupportedException.class, extractor::getInitialPage);
assertTrue(extractor.getTabs().isEmpty());
}
}
@ -189,20 +192,6 @@ public class YoutubeChannelExtractorTest {
assertEquals("http://www.youtube.com/@Gronkh", extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
/*//////////////////////////////////////////////////////////////////////////
// ChannelExtractor
//////////////////////////////////////////////////////////////////////////*/
@ -216,14 +205,14 @@ public class YoutubeChannelExtractorTest {
public void testAvatarUrl() throws Exception {
String avatarUrl = extractor.getAvatarUrl();
assertIsSecureUrl(avatarUrl);
ExtractorAsserts.assertContains("yt3", avatarUrl);
assertContains("yt3", avatarUrl);
}
@Test
public void testBannerUrl() throws Exception {
String bannerUrl = extractor.getBannerUrl();
assertIsSecureUrl(bannerUrl);
ExtractorAsserts.assertContains("yt3", bannerUrl);
assertContains("yt3", bannerUrl);
}
@Test
@ -241,6 +230,18 @@ public class YoutubeChannelExtractorTest {
assertTrue(extractor.isVerified());
}
@Test
@Override
public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS,
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
}
@Test
@Override
public void testTags() throws Exception {
assertTrue(extractor.getTags().contains("gronkh"));
}
}
// Youtube RED/Premium ad blocking test
@ -285,20 +286,6 @@ public class YoutubeChannelExtractorTest {
assertEquals("https://www.youtube.com/user/Vsauce", extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
/*//////////////////////////////////////////////////////////////////////////
// ChannelExtractor
//////////////////////////////////////////////////////////////////////////*/
@ -312,14 +299,14 @@ public class YoutubeChannelExtractorTest {
public void testAvatarUrl() throws Exception {
String avatarUrl = extractor.getAvatarUrl();
assertIsSecureUrl(avatarUrl);
ExtractorAsserts.assertContains("yt3", avatarUrl);
assertContains("yt3", avatarUrl);
}
@Test
public void testBannerUrl() throws Exception {
String bannerUrl = extractor.getBannerUrl();
assertIsSecureUrl(bannerUrl);
ExtractorAsserts.assertContains("yt3", bannerUrl);
assertContains("yt3", bannerUrl);
}
@Test
@ -337,6 +324,19 @@ public class YoutubeChannelExtractorTest {
assertTrue(extractor.isVerified());
}
@Test
@Override
public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.LIVESTREAMS,
ChannelTabs.SHORTS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
}
@Test
@Override
public void testTags() throws Exception {
assertTrue(extractor.getTags().containsAll(List.of("questions", "education",
"learning", "schools", "Science")));
}
}
public static class Kurzgesagt implements BaseChannelExtractorTest {
@ -380,20 +380,6 @@ public class YoutubeChannelExtractorTest {
assertEquals("https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q", extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
/*//////////////////////////////////////////////////////////////////////////
// ChannelExtractor
//////////////////////////////////////////////////////////////////////////*/
@ -410,14 +396,14 @@ public class YoutubeChannelExtractorTest {
public void testAvatarUrl() throws Exception {
String avatarUrl = extractor.getAvatarUrl();
assertIsSecureUrl(avatarUrl);
ExtractorAsserts.assertContains("yt3", avatarUrl);
assertContains("yt3", avatarUrl);
}
@Test
public void testBannerUrl() throws Exception {
String bannerUrl = extractor.getBannerUrl();
assertIsSecureUrl(bannerUrl);
ExtractorAsserts.assertContains("yt3", bannerUrl);
assertContains("yt3", bannerUrl);
}
@Test
@ -434,25 +420,46 @@ public class YoutubeChannelExtractorTest {
public void testVerified() throws Exception {
assertTrue(extractor.isVerified());
}
@Test
@Override
public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS,
ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
}
@Test
@Override
public void testTags() throws Exception {
assertTrue(extractor.getTags().containsAll(List.of("universe", "Science",
"black hole", "humanism", "evolution")));
}
}
public static class KurzgesagtAdditional {
private static YoutubeChannelExtractor extractor;
private static ChannelTabExtractor tabExtractor;
@BeforeAll
public static void setUp() throws Exception {
// Test is not deterministic, mocks can't be used
NewPipe.init(DownloaderTestImpl.getInstance());
extractor = (YoutubeChannelExtractor) YouTube
.getChannelExtractor("https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q");
extractor = (YoutubeChannelExtractor) YouTube.getChannelExtractor(
"https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q");
extractor.fetchPage();
tabExtractor = YouTube.getChannelTabExtractor(extractor.getTabs().get(0));
tabExtractor.fetchPage();
}
@Test
public void testGetPageInNewExtractor() throws Exception {
final ChannelExtractor newExtractor = YouTube.getChannelExtractor(extractor.getUrl());
defaultTestGetPageInNewExtractor(extractor, newExtractor);
newExtractor.fetchPage();
final ChannelTabExtractor newTabExtractor = YouTube.getChannelTabExtractor(
newExtractor.getTabs().get(0));
defaultTestGetPageInNewExtractor(tabExtractor, newTabExtractor);
}
}
@ -497,41 +504,27 @@ public class YoutubeChannelExtractorTest {
assertEquals("https://www.youtube.com/user/CaptainDisillusion/videos", extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
/*//////////////////////////////////////////////////////////////////////////
// ChannelExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testDescription() throws Exception {
ExtractorAsserts.assertContains("In a world where", extractor.getDescription());
assertContains("In a world where", extractor.getDescription());
}
@Test
public void testAvatarUrl() throws Exception {
String avatarUrl = extractor.getAvatarUrl();
assertIsSecureUrl(avatarUrl);
ExtractorAsserts.assertContains("yt3", avatarUrl);
assertContains("yt3", avatarUrl);
}
@Test
public void testBannerUrl() throws Exception {
String bannerUrl = extractor.getBannerUrl();
assertIsSecureUrl(bannerUrl);
ExtractorAsserts.assertContains("yt3", bannerUrl);
assertContains("yt3", bannerUrl);
}
@Test
@ -548,6 +541,20 @@ public class YoutubeChannelExtractorTest {
public void testVerified() throws Exception {
assertTrue(extractor.isVerified());
}
@Test
@Override
public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS,
ChannelTabs.CHANNELS);
}
@Test
@Override
public void testTags() throws Exception {
assertTrue(extractor.getTags().containsAll(List.of("critical thinking",
"visual effects", "VFX", "sci-fi", "humor")));
}
}
public static class RandomChannel implements BaseChannelExtractorTest {
@ -591,47 +598,27 @@ public class YoutubeChannelExtractorTest {
assertEquals("https://www.youtube.com/channel/UCUaQMQS9lY5lit3vurpXQ6w", extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
public void testMoreRelatedItems() {
try {
defaultTestMoreItems(extractor);
} catch (final Throwable ignored) {
return;
}
fail("This channel doesn't have more items, it should throw an error");
}
/*//////////////////////////////////////////////////////////////////////////
// ChannelExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testDescription() throws Exception {
ExtractorAsserts.assertContains("Hey there iu will upoload a load of pranks onto this channel", extractor.getDescription());
assertContains("Hey there iu will upoload a load of pranks onto this channel", extractor.getDescription());
}
@Test
public void testAvatarUrl() throws Exception {
String avatarUrl = extractor.getAvatarUrl();
assertIsSecureUrl(avatarUrl);
ExtractorAsserts.assertContains("yt3", avatarUrl);
assertContains("yt3", avatarUrl);
}
@Test
public void testBannerUrl() throws Exception {
String bannerUrl = extractor.getBannerUrl();
assertIsSecureUrl(bannerUrl);
ExtractorAsserts.assertContains("yt3", bannerUrl);
assertContains("yt3", bannerUrl);
}
@Test
@ -648,6 +635,19 @@ public class YoutubeChannelExtractorTest {
public void testVerified() throws Exception {
assertFalse(extractor.isVerified());
}
@Test
@Override
public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS,
ChannelTabs.CHANNELS);
}
@Test
@Override
public void testTags() throws Exception {
assertTrue(extractor.getTags().isEmpty());
}
}
public static class CarouselHeader implements BaseChannelExtractorTest {
@ -691,32 +691,19 @@ public class YoutubeChannelExtractorTest {
assertEquals("https://www.youtube.com/channel/UCHF66aWLOxBW4l6VkSrS3cQ", extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor);
}
@Test
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor);
}
/*//////////////////////////////////////////////////////////////////////////
// ChannelExtractor
//////////////////////////////////////////////////////////////////////////*/
@Override
public void testDescription() {
public void testDescription() throws ParsingException {
}
@Test
public void testAvatarUrl() throws Exception {
String avatarUrl = extractor.getAvatarUrl();
assertIsSecureUrl(avatarUrl);
ExtractorAsserts.assertContains("yt3", avatarUrl);
assertContains("yt3", avatarUrl);
}
@Test
@ -739,5 +726,145 @@ public class YoutubeChannelExtractorTest {
public void testVerified() throws Exception {
assertTrue(extractor.isVerified());
}
@Test
@Override
public void testTabs() throws Exception {
assertTabsContained(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS,
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
}
@Test
@Override
public void testTags() throws Exception {
assertTrue(extractor.getTags().containsAll(List.of("coachella", "music", "california",
"festival", "arts")));
}
}
/**
* A YouTube channel which is age-restricted and requires login to view its contents on a
* channel page.
*
* <p>
* Note that age-restrictions on channels may not apply for countries, so check that the
* channel is age-restricted in the network you use to update the test's mocks before updating
* them.
* </p>
*/
static class AgeRestrictedChannel implements BaseChannelExtractorTest {
private static ChannelExtractor extractor;
@BeforeAll
static void setUp() throws Exception {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "ageRestricted"));
extractor = YouTube.getChannelExtractor(
"https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig");
extractor.fetchPage();
}
@Test
@Override
public void testDescription() throws Exception {
// Description cannot be extracted from age-restricted channels
assertTrue(isNullOrEmpty(extractor.getDescription()));
}
@Test
@Override
public void testAvatarUrl() throws Exception {
final String avatarUrl = extractor.getAvatarUrl();
assertIsSecureUrl(avatarUrl);
assertContains("yt3", avatarUrl);
}
@Test
@Override
public void testBannerUrl() throws Exception {
// Banners cannot be extracted from age-restricted channels
assertTrue(isNullOrEmpty(extractor.getBannerUrl()));
}
@Test
@Override
public void testFeedUrl() throws Exception {
assertEquals(
"https://www.youtube.com/feeds/videos.xml?channel_id=UCbfnHqxXs_K3kvaH-WlNlig",
extractor.getFeedUrl());
}
@Test
@Override
public void testSubscriberCount() throws Exception {
// Subscriber count cannot be extracted from age-restricted channels
assertEquals(ChannelExtractor.UNKNOWN_SUBSCRIBER_COUNT, extractor.getSubscriberCount());
}
@Test
@Override
public void testServiceId() throws Exception {
assertEquals(YouTube.getServiceId(), extractor.getServiceId());
}
@Test
@Override
public void testName() throws Exception {
assertEquals("Laphroaig Whisky", extractor.getName());
}
@Test
@Override
public void testId() throws Exception {
assertEquals("UCbfnHqxXs_K3kvaH-WlNlig", extractor.getId());
}
@Test
@Override
public void testUrl() throws Exception {
assertEquals("https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig",
extractor.getUrl());
}
@Test
@Override
public void testOriginalUrl() throws Exception {
assertEquals("https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig",
extractor.getOriginalUrl());
}
@Test
@Override
public void testVerified() throws Exception {
// Verification status cannot be extracted from age-restricted channels
assertFalse(extractor.isVerified());
}
@Test
@Override
public void testTabs() throws Exception {
// Channel tabs which may be available and which will be extracted from channel system
// uploads playlists
assertTabsContained(extractor.getTabs(),
ChannelTabs.VIDEOS, ChannelTabs.SHORTS, ChannelTabs.LIVESTREAMS);
// Check if all tabs are not classic tabs, so that link handlers are of the appropriate
// type and build YoutubeChannelTabPlaylistExtractor instances
assertTrue(extractor.getTabs()
.stream()
.allMatch(linkHandler ->
linkHandler.getClass() == ReadyChannelTabListLinkHandler.class
&& ((ReadyChannelTabListLinkHandler) linkHandler)
.getChannelTabExtractor(extractor.getService())
.getClass() == YoutubeChannelTabPlaylistExtractor.class));
}
@Test
@Override
public void testTags() throws Exception {
// Tags cannot be extracted from age-restricted channels
assertTrue(extractor.getTags().isEmpty());
}
}
}

View File

@ -6,9 +6,11 @@ import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestRela
import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderFactory;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor;
import org.schabi.newpipe.extractor.localization.DateWrapper;
import org.schabi.newpipe.extractor.localization.Localization;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
@ -18,6 +20,7 @@ import java.time.temporal.ChronoUnit;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* A class that tests multiple channels and ranges of "time ago".
@ -47,18 +50,27 @@ public class YoutubeChannelLocalizationTest {
for (Localization currentLocalization : supportedLocalizations) {
if (DEBUG) System.out.println("Testing localization = " + currentLocalization);
ListExtractor.InfoItemsPage<StreamInfoItem> itemsPage;
ListExtractor.InfoItemsPage<InfoItem> itemsPage;
try {
final ChannelExtractor extractor = YouTube.getChannelExtractor(channelUrl);
extractor.forceLocalization(currentLocalization);
extractor.fetchPage();
itemsPage = defaultTestRelatedItems(extractor);
// Use Videos tab only
final ChannelTabExtractor tabExtractor = YouTube.getChannelTabExtractor(
extractor.getTabs().get(0));
tabExtractor.fetchPage();
itemsPage = defaultTestRelatedItems(tabExtractor);
} catch (final Throwable e) {
System.out.println("[!] " + currentLocalization + " → failed");
throw e;
}
final List<StreamInfoItem> items = itemsPage.getItems();
final List<StreamInfoItem> items = itemsPage.getItems()
.stream()
.filter(StreamInfoItem.class::isInstance)
.map(StreamInfoItem.class::cast)
.collect(Collectors.toUnmodifiableList());
for (int i = 0; i < items.size(); i++) {
final StreamInfoItem item = items.get(i);
@ -73,7 +85,7 @@ public class YoutubeChannelLocalizationTest {
}
if (DEBUG) System.out.println(debugMessage + "\n");
}
results.put(currentLocalization, itemsPage.getItems());
results.put(currentLocalization, items);
if (DEBUG) System.out.println("\n===============================\n");
}

View File

@ -0,0 +1,397 @@
package org.schabi.newpipe.extractor.services.youtube;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderFactory;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabExtractor;
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.services.BaseListExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelTabExtractor;
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 {
private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH
+ "services/youtube/extractor/channelTabs/";
static class Videos implements BaseListExtractorTest {
private static YoutubeChannelTabExtractor extractor;
@BeforeAll
static void setUp() throws IOException, ExtractionException {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "videos"));
extractor = (YoutubeChannelTabExtractor) YouTube.getChannelTabExtractorFromId(
"user/creativecommons", ChannelTabs.VIDEOS);
extractor.fetchPage();
}
@Test
@Override
public void testServiceId() {
assertEquals(YouTube.getServiceId(), extractor.getServiceId());
}
@Test
@Override
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 {
private static YoutubeChannelTabExtractor extractor;
@BeforeAll
static void setUp() throws IOException, ExtractionException {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "playlists"));
extractor = (YoutubeChannelTabExtractor) YouTube.getChannelTabExtractorFromId(
"@EEVblog", ChannelTabs.PLAYLISTS);
extractor.fetchPage();
}
@Test
@Override
public void testServiceId() {
assertEquals(YouTube.getServiceId(), extractor.getServiceId());
}
@Test
@Override
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 {
private static YoutubeChannelTabExtractor extractor;
@BeforeAll
static void setUp() throws IOException, ExtractionException {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "channels"));
extractor = (YoutubeChannelTabExtractor) YouTube.getChannelTabExtractorFromId(
"channel/UC2DjFE7Xf11URZqWBigcVOQ", ChannelTabs.CHANNELS);
extractor.fetchPage();
}
@Test
@Override
public void testServiceId() {
assertEquals(YouTube.getServiceId(), extractor.getServiceId());
}
@Test
@Override
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 {
private static YoutubeChannelTabExtractor extractor;
@BeforeAll
static void setUp() throws IOException, ExtractionException {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "livestreams"));
extractor = (YoutubeChannelTabExtractor) YouTube.getChannelTabExtractorFromId(
"c/JeffGeerling", ChannelTabs.LIVESTREAMS);
extractor.fetchPage();
}
@Test
@Override
public void testServiceId() {
assertEquals(YouTube.getServiceId(), extractor.getServiceId());
}
@Test
@Override
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 {
private static YoutubeChannelTabExtractor extractor;
@BeforeAll
static void setUp() throws IOException, ExtractionException {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "shorts"));
extractor = (YoutubeChannelTabExtractor) YouTube.getChannelTabExtractorFromId(
"channel/UCh8gHdtzO2tXd593_bjErWg", ChannelTabs.SHORTS);
extractor.fetchPage();
}
@Test
@Override
public void testServiceId() {
assertEquals(YouTube.getServiceId(), extractor.getServiceId());
}
@Test
@Override
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;
private static ChannelTabExtractor shortsTabExtractor;
@BeforeAll
static void setUp() throws IOException, ExtractionException {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "ageRestricted"));
final ChannelExtractor extractor = YouTube.getChannelExtractor(
"https://www.youtube.com/channel/UCbfnHqxXs_K3kvaH-WlNlig");
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 void testServiceId() {
assertEquals(YouTube.getServiceId(), videosTabExtractor.getServiceId());
assertEquals(YouTube.getServiceId(), shortsTabExtractor.getServiceId());
}
@Test
@Override
public void testName() throws Exception {
assertEquals(ChannelTabs.VIDEOS, videosTabExtractor.getName());
assertEquals(ChannelTabs.SHORTS, shortsTabExtractor.getName());
}
@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
@Override
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(videosTabExtractor);
// No shorts on this channel, the channel tab playlist extractor should return no
// streams
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());
}
}
}