package org.schabi.newpipe.extractor.services.youtube; import static org.junit.jupiter.api.Assertions.assertEquals; 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.schabi.newpipe.extractor.ExtractorAsserts.assertContains; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmpty; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertNotEmpty; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContain; import static org.schabi.newpipe.extractor.ServiceList.YouTube; import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestGetPageInNewExtractor; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.schabi.newpipe.downloader.DownloaderFactory; 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.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; 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} */ public class YoutubeChannelExtractorTest { private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH + "services/youtube/extractor/channel/"; public static class NotAvailable { @BeforeAll public static void setUp() throws IOException { YoutubeTestsUtils.ensureStateless(); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "notAvailable")); } @Test public void deletedFetch() throws Exception { final ChannelExtractor extractor = YouTube.getChannelExtractor("https://www.youtube.com/channel/UCAUc4iz6edWerIjlnL8OSSw"); assertThrows(ContentNotAvailableException.class, extractor::fetchPage); } @Test public void nonExistentFetch() throws Exception { final ChannelExtractor extractor = YouTube.getChannelExtractor("https://www.youtube.com/channel/DOESNT-EXIST"); assertThrows(ContentNotAvailableException.class, extractor::fetchPage); } @Test public void accountTerminatedTOSFetch() throws Exception { // "This account has been terminated for a violation of YouTube's Terms of Service." final ChannelExtractor extractor = YouTube.getChannelExtractor("https://www.youtube.com/channel/UCTGjY2I-ZUGnwVoWAGRd7XQ"); AccountTerminatedException ex = assertThrows(AccountTerminatedException.class, extractor::fetchPage); assertEquals(AccountTerminatedException.Reason.VIOLATION, ex.getReason()); } @Test public void accountTerminatedCommunityFetch() throws Exception { // "This account has been terminated for violating YouTube's Community Guidelines." final ChannelExtractor extractor = YouTube.getChannelExtractor("https://www.youtube.com/channel/UC0AuOxCr9TZ0TtEgL1zpIgA"); AccountTerminatedException ex = assertThrows(AccountTerminatedException.class, extractor::fetchPage); assertEquals(AccountTerminatedException.Reason.VIOLATION, ex.getReason()); } @Test public void accountTerminatedHateFetch() throws Exception { // "This account has been terminated due to multiple or severe violations // of YouTube's policy prohibiting hate speech." final ChannelExtractor extractor = YouTube.getChannelExtractor("https://www.youtube.com/channel/UCPWXIOPK-9myzek6jHR5yrg"); AccountTerminatedException ex = assertThrows(AccountTerminatedException.class, extractor::fetchPage); assertEquals(AccountTerminatedException.Reason.VIOLATION, ex.getReason()); } @Test public void accountTerminatedBullyFetch() throws Exception { // "This account has been terminated due to multiple or severe violations // of YouTube's policy prohibiting content designed to harass, bully or threaten." final ChannelExtractor extractor = YouTube.getChannelExtractor("https://youtube.com/channel/UCB1o7_gbFp2PLsamWxFenBg"); AccountTerminatedException ex = assertThrows(AccountTerminatedException.class, extractor::fetchPage); assertEquals(AccountTerminatedException.Reason.VIOLATION, ex.getReason()); } @Test public void accountTerminatedSpamFetch() throws Exception { // "This account has been terminated due to multiple or severe violations // of YouTube's policy against spam, deceptive practices and misleading content // or other Terms of Service violations." final ChannelExtractor extractor = YouTube.getChannelExtractor("https://www.youtube.com/channel/UCoaO4U_p7G7AwalqSbGCZOA"); AccountTerminatedException ex = assertThrows(AccountTerminatedException.class, extractor::fetchPage); assertEquals(AccountTerminatedException.Reason.VIOLATION, ex.getReason()); } @Test public void accountTerminatedCopyrightFetch() throws Exception { // "This account has been terminated because we received multiple third-party claims // of copyright infringement regarding material that the user posted." final ChannelExtractor extractor = YouTube.getChannelExtractor("https://www.youtube.com/channel/UCI4i4RgFT5ilfMpna4Z_Y8w"); AccountTerminatedException ex = assertThrows(AccountTerminatedException.class, extractor::fetchPage); assertEquals(AccountTerminatedException.Reason.VIOLATION, ex.getReason()); } } static class SystemTopic { @BeforeAll static void setUp() throws IOException { YoutubeTestsUtils.ensureStateless(); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "systemTopic")); } @Test void noSupportedTab() throws Exception { final ChannelExtractor extractor = YouTube.getChannelExtractor("https://invidio.us/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ"); extractor.fetchPage(); assertTrue(extractor.getTabs().isEmpty()); } } public static class Gronkh implements BaseChannelExtractorTest { private static YoutubeChannelExtractor extractor; @BeforeAll public static void setUp() throws Exception { YoutubeTestsUtils.ensureStateless(); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "gronkh")); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("http://www.youtube.com/@Gronkh"); extractor.fetchPage(); } /*////////////////////////////////////////////////////////////////////////// // Extractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testServiceId() { assertEquals(YouTube.getServiceId(), extractor.getServiceId()); } @Test public void testName() throws Exception { assertEquals("Gronkh", extractor.getName()); } @Test public void testId() throws Exception { assertEquals("UCYJ61XIK64sp6ZFFS8sctxw", extractor.getId()); } @Test public void testUrl() throws ParsingException { assertEquals("https://www.youtube.com/channel/UCYJ61XIK64sp6ZFFS8sctxw", extractor.getUrl()); } @Test public void testOriginalUrl() throws ParsingException { assertEquals("http://www.youtube.com/@Gronkh", extractor.getOriginalUrl()); } /*////////////////////////////////////////////////////////////////////////// // ChannelExtractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testDescription() throws Exception { assertContains("Ungebremster Spieltrieb seit 1896.", extractor.getDescription()); } @Test public void testAvatars() throws Exception { YoutubeTestsUtils.testImages(extractor.getAvatars()); } @Test public void testBanners() throws Exception { YoutubeTestsUtils.testImages(extractor.getBanners()); } @Test public void testFeedUrl() throws Exception { assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UCYJ61XIK64sp6ZFFS8sctxw", extractor.getFeedUrl()); } @Test public void testSubscriberCount() throws Exception { ExtractorAsserts.assertGreaterOrEqual(4_900_000, extractor.getSubscriberCount()); } @Test @Override public void testVerified() throws Exception { assertTrue(extractor.isVerified()); } @Test @Override public void testTabs() throws Exception { assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS); assertTrue(extractor.getTabs().stream() .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); } @Test @Override public void testTags() throws Exception { assertTrue(extractor.getTags().contains("gronkh")); } } // YouTube RED/Premium ad blocking test public static class VSauce implements BaseChannelExtractorTest { private static YoutubeChannelExtractor extractor; @BeforeAll public static void setUp() throws Exception { YoutubeTestsUtils.ensureStateless(); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "VSauce")); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/user/Vsauce"); extractor.fetchPage(); } /*////////////////////////////////////////////////////////////////////////// // Extractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testServiceId() { assertEquals(YouTube.getServiceId(), extractor.getServiceId()); } @Test public void testName() throws Exception { assertEquals("Vsauce", extractor.getName()); } @Test public void testId() throws Exception { assertEquals("UC6nSFpj9HTCZ5t-N3Rm3-HA", extractor.getId()); } @Test public void testUrl() throws ParsingException { assertEquals("https://www.youtube.com/channel/UC6nSFpj9HTCZ5t-N3Rm3-HA", extractor.getUrl()); } @Test public void testOriginalUrl() throws ParsingException { assertEquals("https://www.youtube.com/user/Vsauce", extractor.getOriginalUrl()); } /*////////////////////////////////////////////////////////////////////////// // ChannelExtractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testDescription() throws Exception { assertContains("Our World is Amazing. \n\nQuestions? Ideas? Tweet me:", extractor.getDescription()); } @Test public void testAvatars() throws Exception { YoutubeTestsUtils.testImages(extractor.getAvatars()); } @Test public void testBanners() throws Exception { YoutubeTestsUtils.testImages(extractor.getBanners()); } @Test public void testFeedUrl() throws Exception { assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UC6nSFpj9HTCZ5t-N3Rm3-HA", extractor.getFeedUrl()); } @Test public void testSubscriberCount() throws Exception { ExtractorAsserts.assertGreaterOrEqual(17_000_000, extractor.getSubscriberCount()); } @Test public void testVerified() throws Exception { assertTrue(extractor.isVerified()); } @Test @Override public void testTabs() throws Exception { assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.LIVESTREAMS, ChannelTabs.SHORTS, ChannelTabs.PLAYLISTS); assertTrue(extractor.getTabs().stream() .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); } @Test @Override public void testTags() throws Exception { assertTrue(extractor.getTags().containsAll(List.of("questions", "education", "learning", "schools", "Science"))); } } public static class Kurzgesagt implements BaseChannelExtractorTest { private static YoutubeChannelExtractor extractor; @BeforeAll public static void setUp() throws Exception { YoutubeTestsUtils.ensureStateless(); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "kurzgesagt")); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q"); extractor.fetchPage(); } /*////////////////////////////////////////////////////////////////////////// // Extractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testServiceId() { assertEquals(YouTube.getServiceId(), extractor.getServiceId()); } @Test public void testName() throws Exception { assertTrue(extractor.getName().startsWith("Kurzgesagt")); } @Test public void testId() throws Exception { assertEquals("UCsXVk37bltHxD1rDPwtNM8Q", extractor.getId()); } @Test public void testUrl() throws ParsingException { assertEquals("https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q", extractor.getUrl()); } @Test public void testOriginalUrl() throws ParsingException { assertEquals("https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q", extractor.getOriginalUrl()); } /*////////////////////////////////////////////////////////////////////////// // ChannelExtractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testDescription() throws Exception { ExtractorAsserts.assertContains("science", extractor.getDescription()); ExtractorAsserts.assertContains("animators", extractor.getDescription()); //TODO: Description get cuts out, because the og:description is optimized and don't have all the content //assertTrue(description, description.contains("Currently we make one animation video per month")); } @Test public void testAvatars() throws Exception { YoutubeTestsUtils.testImages(extractor.getAvatars()); } @Test public void testBanners() throws Exception { YoutubeTestsUtils.testImages(extractor.getBanners()); } @Test public void testFeedUrl() throws Exception { assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UCsXVk37bltHxD1rDPwtNM8Q", extractor.getFeedUrl()); } @Test public void testSubscriberCount() throws Exception { ExtractorAsserts.assertGreaterOrEqual(17_000_000, extractor.getSubscriberCount()); } @Test public void testVerified() throws Exception { assertTrue(extractor.isVerified()); } @Test @Override public void testTabs() throws Exception { assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS, ChannelTabs.PLAYLISTS); assertTrue(extractor.getTabs().stream() .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); } @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.fetchPage(); tabExtractor = YouTube.getChannelTabExtractor(extractor.getTabs().get(0)); tabExtractor.fetchPage(); } @Test public void testGetPageInNewExtractor() throws Exception { final ChannelExtractor newExtractor = YouTube.getChannelExtractor(extractor.getUrl()); newExtractor.fetchPage(); final ChannelTabExtractor newTabExtractor = YouTube.getChannelTabExtractor( newExtractor.getTabs().get(0)); defaultTestGetPageInNewExtractor(tabExtractor, newTabExtractor); } } public static class CaptainDisillusion implements BaseChannelExtractorTest { private static YoutubeChannelExtractor extractor; @BeforeAll public static void setUp() throws Exception { YoutubeTestsUtils.ensureStateless(); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "captainDisillusion")); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/user/CaptainDisillusion/videos"); extractor.fetchPage(); } /*////////////////////////////////////////////////////////////////////////// // Extractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testServiceId() { assertEquals(YouTube.getServiceId(), extractor.getServiceId()); } @Test public void testName() throws Exception { assertEquals("Captain Disillusion", extractor.getName()); } @Test public void testId() throws Exception { assertEquals("UCEOXxzW2vU0P-0THehuIIeg", extractor.getId()); } @Test public void testUrl() throws ParsingException { assertEquals("https://www.youtube.com/channel/UCEOXxzW2vU0P-0THehuIIeg", extractor.getUrl()); } @Test public void testOriginalUrl() throws ParsingException { assertEquals("https://www.youtube.com/user/CaptainDisillusion/videos", extractor.getOriginalUrl()); } /*////////////////////////////////////////////////////////////////////////// // ChannelExtractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testDescription() throws Exception { assertContains("In a world where", extractor.getDescription()); } @Test public void testAvatars() throws Exception { YoutubeTestsUtils.testImages(extractor.getAvatars()); } @Test public void testBanners() throws Exception { YoutubeTestsUtils.testImages(extractor.getBanners()); } @Test public void testFeedUrl() throws Exception { assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UCEOXxzW2vU0P-0THehuIIeg", extractor.getFeedUrl()); } @Test public void testSubscriberCount() throws Exception { ExtractorAsserts.assertGreaterOrEqual(2_000_000, extractor.getSubscriberCount()); } @Test public void testVerified() throws Exception { assertTrue(extractor.isVerified()); } @Test @Override public void testTabs() throws Exception { assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS, ChannelTabs.SHORTS); assertTrue(extractor.getTabs().stream() .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); } @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 { private static YoutubeChannelExtractor extractor; @BeforeAll public static void setUp() throws Exception { YoutubeTestsUtils.ensureStateless(); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "random")); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/channel/UCUaQMQS9lY5lit3vurpXQ6w"); extractor.fetchPage(); } /*////////////////////////////////////////////////////////////////////////// // Extractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testServiceId() { assertEquals(YouTube.getServiceId(), extractor.getServiceId()); } @Test public void testName() throws Exception { assertEquals("random channel", extractor.getName()); } @Test public void testId() throws Exception { assertEquals("UCUaQMQS9lY5lit3vurpXQ6w", extractor.getId()); } @Test public void testUrl() throws ParsingException { assertEquals("https://www.youtube.com/channel/UCUaQMQS9lY5lit3vurpXQ6w", extractor.getUrl()); } @Test public void testOriginalUrl() throws ParsingException { assertEquals("https://www.youtube.com/channel/UCUaQMQS9lY5lit3vurpXQ6w", extractor.getOriginalUrl()); } /*////////////////////////////////////////////////////////////////////////// // ChannelExtractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testDescription() throws Exception { assertContains("Hey there iu will upoload a load of pranks onto this channel", extractor.getDescription()); } @Test public void testAvatars() throws Exception { YoutubeTestsUtils.testImages(extractor.getAvatars()); } @Test public void testBanners() throws Exception { YoutubeTestsUtils.testImages(extractor.getBanners()); } @Test public void testFeedUrl() throws Exception { assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UCUaQMQS9lY5lit3vurpXQ6w", extractor.getFeedUrl()); } @Test public void testSubscriberCount() throws Exception { ExtractorAsserts.assertGreaterOrEqual(50, extractor.getSubscriberCount()); } @Test public void testVerified() throws Exception { assertFalse(extractor.isVerified()); } @Test @Override public void testTabs() throws Exception { assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS); assertTrue(extractor.getTabs().stream() .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); } @Test @Override public void testTags() throws Exception { assertTrue(extractor.getTags().isEmpty()); } } public static class CarouselHeader implements BaseChannelExtractorTest { private static YoutubeChannelExtractor extractor; @BeforeAll public static void setUp() throws Exception { YoutubeTestsUtils.ensureStateless(); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "carouselHeader")); extractor = (YoutubeChannelExtractor) YouTube .getChannelExtractor("https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw"); extractor.fetchPage(); } /*////////////////////////////////////////////////////////////////////////// // Extractor //////////////////////////////////////////////////////////////////////////*/ @Test public void testServiceId() { assertEquals(YouTube.getServiceId(), extractor.getServiceId()); } @Test public void testName() throws Exception { assertEquals("Sports", extractor.getName()); } @Test public void testId() throws Exception { assertEquals("UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getId()); } @Test public void testUrl() throws ParsingException { assertEquals("https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getUrl()); } @Test public void testOriginalUrl() throws ParsingException { assertEquals("https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getOriginalUrl()); } /*////////////////////////////////////////////////////////////////////////// // ChannelExtractor //////////////////////////////////////////////////////////////////////////*/ @Test @Override public void testDescription() throws ParsingException { assertNull(extractor.getDescription()); } @Test public void testAvatars() throws Exception { YoutubeTestsUtils.testImages(extractor.getAvatars()); } @Test public void testBanners() { // A CarouselHeaderRenderer doesn't contain a banner assertEmpty(extractor.getBanners()); } @Test public void testFeedUrl() throws Exception { assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getFeedUrl()); } @Test public void testSubscriberCount() throws Exception { ExtractorAsserts.assertGreaterOrEqual(70_000_000, extractor.getSubscriberCount()); } @Test public void testVerified() throws Exception { assertTrue(extractor.isVerified()); } @Test @Override public void testTabs() throws Exception { assertEmpty(extractor.getTabs()); } @Test @Override public void testTags() throws Exception { assertEmpty(extractor.getTags()); } } /** * A YouTube channel which is age-restricted and requires login to view its contents on a * channel page. * *

* 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. *

*/ 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 testAvatars() throws Exception { YoutubeTestsUtils.testImages(extractor.getAvatars()); } @Test @Override public void testBanners() throws Exception { // Banners cannot be extracted from age-restricted channels assertEmpty(extractor.getBanners()); } @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 assertTabsContain(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()); } } static class InteractiveTabbedHeader implements BaseChannelExtractorTest { private static ChannelExtractor extractor; @BeforeAll static void setUp() throws Exception { YoutubeTestsUtils.ensureStateless(); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "interactiveTabbedHeader")); extractor = YouTube.getChannelExtractor( "https://www.youtube.com/channel/UCQvWX73GQygcwXOTSf_VDVg"); extractor.fetchPage(); } @Test @Override public void testDescription() throws Exception { // The description changes frequently and there is no significant common word, so only // check if it is not empty assertNotEmpty(extractor.getDescription()); } @Test @Override public void testAvatars() throws Exception { YoutubeTestsUtils.testImages(extractor.getAvatars()); } @Test @Override public void testBanners() throws Exception { YoutubeTestsUtils.testImages(extractor.getBanners()); } @Test @Override public void testFeedUrl() throws Exception { assertEquals( "https://www.youtube.com/feeds/videos.xml?channel_id=UCQvWX73GQygcwXOTSf_VDVg", extractor.getFeedUrl()); } @Test @Override public void testSubscriberCount() throws Exception { // Subscriber count is not available on channels with an interactiveTabbedHeaderRenderer assertEquals(ChannelExtractor.UNKNOWN_SUBSCRIBER_COUNT, extractor.getSubscriberCount()); } @Test @Override public void testVerified() throws Exception { assertTrue(extractor.isVerified()); } @Test @Override public void testTabs() throws Exception { // Gaming topic channels tabs are not yet supported // However, a Shorts tab like on other channel types is returned, so it is supported // Check that it is returned assertTabsContain(extractor.getTabs(), ChannelTabs.SHORTS); } @Test @Override public void testTags() throws Exception { assertTrue(extractor.getTags().isEmpty()); } @Test @Override public void testServiceId() throws Exception { assertEquals(YouTube.getServiceId(), extractor.getServiceId()); } @Test @Override public void testName() throws Exception { assertContains("Minecraft", extractor.getName()); } @Test @Override public void testId() throws Exception { assertEquals("UCQvWX73GQygcwXOTSf_VDVg", extractor.getId()); } @Test @Override public void testUrl() throws Exception { assertEquals("https://www.youtube.com/channel/UCQvWX73GQygcwXOTSf_VDVg", extractor.getUrl()); } @Test @Override public void testOriginalUrl() throws Exception { assertEquals("https://www.youtube.com/channel/UCQvWX73GQygcwXOTSf_VDVg", extractor.getOriginalUrl()); } } }