77import org .schabi .newpipe .extractor .localization .TimeAgoPatternsManager ;
88import org .schabi .newpipe .extractor .services .youtube .extractors .YoutubeStreamInfoItemExtractor ;
99import org .schabi .newpipe .extractor .services .youtube .extractors .YoutubeStreamInfoItemLockupExtractor ;
10+ import org .schabi .newpipe .extractor .stream .ContentAvailability ;
1011import org .schabi .newpipe .extractor .stream .StreamType ;
1112
1213import java .io .FileInputStream ;
@@ -53,7 +54,8 @@ void videoRendererPremiere() throws FileNotFoundException, JsonParserException {
5354 () -> assertEquals (-1 , extractor .getViewCount ()),
5455 () -> assertFalse (extractor .getThumbnails ().isEmpty ()),
5556 () -> assertEquals ("Patience is key… MERCH SHOP : https://www.bluntbrosproductions.com Follow us on Instagram for early updates: ..." , extractor .getShortDescription ()),
56- () -> assertFalse (extractor .isShortFormContent ())
57+ () -> assertFalse (extractor .isShortFormContent ()),
58+ () -> assertEquals (ContentAvailability .UPCOMING , extractor .getContentAvailability ())
5759 );
5860 }
5961
@@ -82,7 +84,8 @@ void lockupViewModelPremiere()
8284 () -> assertEquals (-1 , extractor .getViewCount ()),
8385 () -> assertFalse (extractor .getThumbnails ().isEmpty ()),
8486 () -> assertNull (extractor .getShortDescription ()),
85- () -> assertFalse (extractor .isShortFormContent ())
87+ () -> assertFalse (extractor .isShortFormContent ()),
88+ () -> assertEquals (ContentAvailability .UPCOMING , extractor .getContentAvailability ())
8689 );
8790 }
8891
@@ -99,15 +102,16 @@ void lockupViewModelVideo()
99102 () -> assertEquals ("https://www.youtube.com/watch?v=dQw4w9WgXcQ" , extractor .getUrl ()),
100103 () -> assertEquals ("VIDEO_TITLE" , extractor .getName ()),
101104 () -> assertEquals (974 , extractor .getDuration ()),
102- () -> assertFalse (extractor .getThumbnails ().isEmpty ())
105+ () -> assertFalse (extractor .getThumbnails ().isEmpty ()),
106+ () -> assertEquals (ContentAvailability .AVAILABLE , extractor .getContentAvailability ())
103107 );
104108 }
105109
106110 @ Test
107- void lockupViewModelLiveStream ()
111+ void lockupViewModelLiveStreamNoViewer ()
108112 throws FileNotFoundException , JsonParserException {
109113 final var json = JsonParser .object ().from (new FileInputStream (getMockPath (
110- YoutubeStreamInfoItemTest .class , "lockupViewModelLiveStream " ) + ".json" ));
114+ YoutubeStreamInfoItemTest .class , "lockupViewModelLiveStreamNoViewer " ) + ".json" ));
111115 final var timeAgoParser = TimeAgoPatternsManager .getTimeAgoParserFor (Localization .DEFAULT );
112116 final var extractor = new YoutubeStreamInfoItemLockupExtractor (json , timeAgoParser );
113117 assertAll (
@@ -119,7 +123,8 @@ void lockupViewModelLiveStream()
119123 () -> assertNull (extractor .getTextualUploadDate ()),
120124 () -> assertNull (extractor .getUploadDate ()),
121125 () -> assertEquals (0 , extractor .getViewCount ()),
122- () -> assertFalse (extractor .getThumbnails ().isEmpty ())
126+ () -> assertFalse (extractor .getThumbnails ().isEmpty ()),
127+ () -> assertEquals (ContentAvailability .AVAILABLE , extractor .getContentAvailability ())
123128 );
124129 }
125130
@@ -134,25 +139,24 @@ void lockupViewModelNoDuration()
134139 () -> assertEquals (StreamType .VIDEO_STREAM , extractor .getStreamType ()),
135140 () -> assertFalse (extractor .isAd ()),
136141 () -> assertEquals (-1 , extractor .getDuration ()),
137- () -> assertFalse (extractor .getThumbnails ().isEmpty ())
142+ () -> assertFalse (extractor .getThumbnails ().isEmpty ()),
143+ () -> assertEquals (ContentAvailability .AVAILABLE , extractor .getContentAvailability ())
138144 );
139145 }
140146
141147 /**
142- * Tests that the info row search correctly extracts date and view count
143- * from the 1-row channel format where parts are in normal order: [views, date].
148+ * Tests that the date and view count is extracted properly from the 1-row channel format.
144149 */
145150 @ Test
146- void lockupViewModelOneRowNormal ()
151+ void lockupViewModelChannelOneRow ()
147152 throws FileNotFoundException , JsonParserException {
148153 final var json = JsonParser .object ().from (new FileInputStream (getMockPath (
149- YoutubeStreamInfoItemTest .class , "lockupViewModelOneRowNormal " ) + ".json" ));
154+ YoutubeStreamInfoItemTest .class , "lockupViewModelChannelOneRow " ) + ".json" ));
150155 final var timeAgoParser = TimeAgoPatternsManager .getTimeAgoParserFor (Localization .DEFAULT );
151156 final var extractor = new YoutubeStreamInfoItemLockupExtractor (json , timeAgoParser ) {
152- // Channel tabs use 1-row format at index 0
153157 @ Override
154- protected int getInfoMetadataRowIndex () {
155- return 0 ;
158+ protected boolean isChannelOrCoursePlaylistLockupItem () {
159+ return true ;
156160 }
157161 };
158162 assertAll (
@@ -161,52 +165,25 @@ protected int getInfoMetadataRowIndex() {
161165 () -> assertEquals ("2 hours ago" , extractor .getTextualUploadDate ()),
162166 () -> assertNotNull (extractor .getUploadDate ()),
163167 () -> assertEquals (3600000 , extractor .getViewCount ()), // 3.6m views
164- () -> assertEquals (630 , extractor .getDuration ()) // 10:30
165- );
166- }
167-
168- /**
169- * Tests that the info row search correctly extracts date and view count
170- * from the 1-row channel format where parts are in reversed order: [date, views].
171- */
172- @ Test
173- void lockupViewModelOneRowReversed ()
174- throws FileNotFoundException , JsonParserException {
175- final var json = JsonParser .object ().from (new FileInputStream (getMockPath (
176- YoutubeStreamInfoItemTest .class , "lockupViewModelOneRowReversed" ) + ".json" ));
177- final var timeAgoParser = TimeAgoPatternsManager .getTimeAgoParserFor (Localization .DEFAULT );
178- final var extractor = new YoutubeStreamInfoItemLockupExtractor (json , timeAgoParser ) {
179- // Channel tabs use 1-row format at index 0
180- @ Override
181- protected int getInfoMetadataRowIndex () {
182- return 0 ;
183- }
184- };
185- assertAll (
186- () -> assertEquals (StreamType .VIDEO_STREAM , extractor .getStreamType ()),
187- () -> assertEquals ("Test Video One Row Reversed" , extractor .getName ()),
188- () -> assertEquals ("1 day ago" , extractor .getTextualUploadDate ()),
189- () -> assertNotNull (extractor .getUploadDate ()),
190- () -> assertEquals (1200 , extractor .getViewCount ()), // 1.2K views
191- () -> assertEquals (300 , extractor .getDuration ()) // 5:00
168+ () -> assertEquals (630 , extractor .getDuration ()), // 10:30
169+ () -> assertEquals (ContentAvailability .AVAILABLE , extractor .getContentAvailability ())
192170 );
193171 }
194172
195173 /**
196- * Tests that the info row search handles 1-row format with only view count
197- * (no date text present) - e.g. for livestreams with watching count only .
174+ * Tests that the info row search handles 1-row format with only view count (no date text
175+ * present), returned for livestreams on channels .
198176 */
199177 @ Test
200- void lockupViewModelOneRowViewsOnly ()
178+ void lockupViewModelChannelOneRowLiveViewsOnly ()
201179 throws FileNotFoundException , JsonParserException {
202180 final var json = JsonParser .object ().from (new FileInputStream (getMockPath (
203- YoutubeStreamInfoItemTest .class , "lockupViewModelOneRowViewsOnly " ) + ".json" ));
181+ YoutubeStreamInfoItemTest .class , "lockupViewModelChannelOneRowLiveViewsOnly " ) + ".json" ));
204182 final var timeAgoParser = TimeAgoPatternsManager .getTimeAgoParserFor (Localization .DEFAULT );
205183 final var extractor = new YoutubeStreamInfoItemLockupExtractor (json , timeAgoParser ) {
206- // Channel tabs use 1-row format at index 0
207184 @ Override
208- protected int getInfoMetadataRowIndex () {
209- return 0 ;
185+ protected boolean isChannelOrCoursePlaylistLockupItem () {
186+ return true ;
210187 }
211188 };
212189 assertAll (
@@ -215,67 +192,38 @@ protected int getInfoMetadataRowIndex() {
215192 () -> assertNull (extractor .getTextualUploadDate ()),
216193 () -> assertNull (extractor .getUploadDate ()),
217194 () -> assertEquals (500 , extractor .getViewCount ()), // 500 watching
218- () -> assertEquals (-1 , extractor .getDuration ())
195+ () -> assertEquals (-1 , extractor .getDuration ()),
196+ () -> assertEquals (ContentAvailability .AVAILABLE , extractor .getContentAvailability ())
219197 );
220198 }
221199
222- /**
223- * Tests that channel tab items with non-views text in the metadata row
224- * (e.g. section headers) don't crash and return -1 for views.
225- * Regression test for blind metadataPart(infoRowIndex, 0) fallback.
226- */
227200 @ Test
228- void lockupViewModelChannelTabSectionHeader ()
201+ void lockupViewModelChannelMembersOnly ()
229202 throws FileNotFoundException , JsonParserException {
230203 final var json = JsonParser .object ().from (new FileInputStream (getMockPath (
231- YoutubeStreamInfoItemTest .class , "lockupViewModelChannelTabSectionHeader " )
204+ YoutubeStreamInfoItemTest .class , "lockupviewmodelchannelmembersonly " )
232205 + ".json" ));
233206 final var timeAgoParser = TimeAgoPatternsManager .getTimeAgoParserFor (
234207 Localization .DEFAULT );
235208 final var extractor = new YoutubeStreamInfoItemLockupExtractor (json , timeAgoParser ) {
236- // Channel tabs use 1-row format at index 0
237209 @ Override
238- protected int getInfoMetadataRowIndex () {
239- return 0 ;
210+ protected boolean isChannelOrCoursePlaylistLockupItem () {
211+ return true ;
240212 }
241213 };
242214 assertAll (
243215 () -> assertEquals (StreamType .VIDEO_STREAM , extractor .getStreamType ()),
244- () -> assertEquals ("Section Header Video" , extractor .getName ()),
245- () -> assertNull (extractor .getTextualUploadDate ()),
246- () -> assertNull (extractor .getUploadDate ()),
216+ () -> assertFalse (extractor .isAd ()),
217+ () -> assertEquals ("https://www.youtube.com/watch?v=x3pS1_qqtIs" , extractor .getUrl ()),
218+ () -> assertEquals ("Daily Linux News - S03E105 - EU will fund European datacenters, Steam Deck's massive price increase" , extractor .getName ()),
219+ () -> assertEquals (725 , extractor .getDuration ()),
220+ () -> assertEquals ("12 hours ago" , extractor .getTextualUploadDate ()),
221+ () -> assertNotNull (extractor .getUploadDate ()),
247222 () -> assertEquals (-1 , extractor .getViewCount ()),
248- () -> assertEquals (-1 , extractor .getDuration ())
249- );
250- }
251-
252- /**
253- * Tests that live streams in channel tabs with only a channel name row
254- * (no viewer count) don't crash and return 0 for views.
255- * Regression test for blind metadataPart(infoRowIndex, 0) fallback.
256- */
257- @ Test
258- void lockupViewModelChannelTabLiveNoViewers ()
259- throws FileNotFoundException , JsonParserException {
260- final var json = JsonParser .object ().from (new FileInputStream (getMockPath (
261- YoutubeStreamInfoItemTest .class , "lockupViewModelChannelTabLiveNoViewers" )
262- + ".json" ));
263- final var timeAgoParser = TimeAgoPatternsManager .getTimeAgoParserFor (
264- Localization .DEFAULT );
265- final var extractor = new YoutubeStreamInfoItemLockupExtractor (json , timeAgoParser ) {
266- // Channel tabs use 1-row format at index 0
267- @ Override
268- protected int getInfoMetadataRowIndex () {
269- return 0 ;
270- }
271- };
272- assertAll (
273- () -> assertEquals (StreamType .LIVE_STREAM , extractor .getStreamType ()),
274- () -> assertEquals ("Live Stream No Viewers" , extractor .getName ()),
275- () -> assertNull (extractor .getTextualUploadDate ()),
276- () -> assertNull (extractor .getUploadDate ()),
277- () -> assertEquals (0 , extractor .getViewCount ()),
278- () -> assertEquals (-1 , extractor .getDuration ())
223+ () -> assertFalse (extractor .getThumbnails ().isEmpty ()),
224+ () -> assertNull (extractor .getShortDescription ()),
225+ () -> assertFalse (extractor .isShortFormContent ()),
226+ () -> assertEquals (ContentAvailability .MEMBERSHIP , extractor .getContentAvailability ())
279227 );
280228 }
281229
@@ -286,21 +234,22 @@ void emptyTitle() throws FileNotFoundException, JsonParserException {
286234 final var timeAgoParser = TimeAgoPatternsManager .getTimeAgoParserFor (Localization .DEFAULT );
287235 final var extractor = new YoutubeStreamInfoItemExtractor (json , timeAgoParser );
288236 assertAll (
289- () -> assertEquals (StreamType .VIDEO_STREAM , extractor .getStreamType ()),
290- () -> assertFalse (extractor .isAd ()),
291- () -> assertEquals ("https://www.youtube.com/watch?v=nc1kN8ZSfGQ" , extractor .getUrl ()),
292- () -> assertEquals ("" , extractor .getName ()),
293- () -> assertEquals (39 , extractor .getDuration ()),
294- () -> assertEquals ("hyper" , extractor .getUploaderName ()),
295- () -> assertEquals ("https://www.youtube.com/channel/UCSezUnbvCLYBXuUlPcXU_QQ" , extractor .getUploaderUrl ()),
296- () -> assertFalse (extractor .getUploaderAvatars ().isEmpty ()),
297- () -> assertTrue (extractor .isUploaderVerified ()),
298- () -> assertEquals ("8 years ago" , extractor .getTextualUploadDate ()),
299- () -> assertNotNull (extractor .getUploadDate ()),
300- () -> assertTrue (extractor .getViewCount () >= 1318193 ),
301- () -> assertFalse (extractor .getThumbnails ().isEmpty ()),
302- () -> assertNull (extractor .getShortDescription ()),
303- () -> assertFalse (extractor .isShortFormContent ())
237+ () -> assertEquals (StreamType .VIDEO_STREAM , extractor .getStreamType ()),
238+ () -> assertFalse (extractor .isAd ()),
239+ () -> assertEquals ("https://www.youtube.com/watch?v=nc1kN8ZSfGQ" , extractor .getUrl ()),
240+ () -> assertEquals ("" , extractor .getName ()),
241+ () -> assertEquals (39 , extractor .getDuration ()),
242+ () -> assertEquals ("hyper" , extractor .getUploaderName ()),
243+ () -> assertEquals ("https://www.youtube.com/channel/UCSezUnbvCLYBXuUlPcXU_QQ" , extractor .getUploaderUrl ()),
244+ () -> assertFalse (extractor .getUploaderAvatars ().isEmpty ()),
245+ () -> assertTrue (extractor .isUploaderVerified ()),
246+ () -> assertEquals ("8 years ago" , extractor .getTextualUploadDate ()),
247+ () -> assertNotNull (extractor .getUploadDate ()),
248+ () -> assertTrue (extractor .getViewCount () >= 1318193 ),
249+ () -> assertFalse (extractor .getThumbnails ().isEmpty ()),
250+ () -> assertNull (extractor .getShortDescription ()),
251+ () -> assertFalse (extractor .isShortFormContent ()),
252+ () -> assertEquals (ContentAvailability .AVAILABLE , extractor .getContentAvailability ())
304253 );
305254 }
306255}
0 commit comments