Skip to content

Commit 4bebf3d

Browse files
committed
Add unit tests for lockup extractor edge cases
Tests cover: normal video with duration badge, video without duration badge (Shorts), and live stream. Mocks added for all three cases. Update disabled testMoreRelatedItems comment to reflect the fix.
1 parent 29bafb7 commit 4bebf3d

5 files changed

Lines changed: 379 additions & 1 deletion

File tree

extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamInfoItemTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,58 @@ void lockupViewModelPremiere()
8686
);
8787
}
8888

89+
@Test
90+
void lockupViewModelVideo()
91+
throws FileNotFoundException, JsonParserException {
92+
final var json = JsonParser.object().from(new FileInputStream(getMockPath(
93+
YoutubeStreamInfoItemTest.class, "lockupViewModelVideo") + ".json"));
94+
final var timeAgoParser = TimeAgoPatternsManager.getTimeAgoParserFor(Localization.DEFAULT);
95+
final var extractor = new YoutubeStreamInfoItemLockupExtractor(json, timeAgoParser);
96+
assertAll(
97+
() -> assertEquals(StreamType.VIDEO_STREAM, extractor.getStreamType()),
98+
() -> assertFalse(extractor.isAd()),
99+
() -> assertEquals("https://www.youtube.com/watch?v=dQw4w9WgXcQ", extractor.getUrl()),
100+
() -> assertEquals("VIDEO_TITLE", extractor.getName()),
101+
() -> assertEquals(974, extractor.getDuration()),
102+
() -> assertFalse(extractor.getThumbnails().isEmpty())
103+
);
104+
}
105+
106+
@Test
107+
void lockupViewModelLiveStream()
108+
throws FileNotFoundException, JsonParserException {
109+
final var json = JsonParser.object().from(new FileInputStream(getMockPath(
110+
YoutubeStreamInfoItemTest.class, "lockupViewModelLiveStream") + ".json"));
111+
final var timeAgoParser = TimeAgoPatternsManager.getTimeAgoParserFor(Localization.DEFAULT);
112+
final var extractor = new YoutubeStreamInfoItemLockupExtractor(json, timeAgoParser);
113+
assertAll(
114+
() -> assertEquals(StreamType.LIVE_STREAM, extractor.getStreamType()),
115+
() -> assertFalse(extractor.isAd()),
116+
() -> assertEquals("https://www.youtube.com/watch?v=LIVE_VIDEO_ID", extractor.getUrl()),
117+
() -> assertEquals("LIVE_VIDEO_TITLE", extractor.getName()),
118+
() -> assertEquals(-1, extractor.getDuration()),
119+
() -> assertNull(extractor.getTextualUploadDate()),
120+
() -> assertNull(extractor.getUploadDate()),
121+
() -> assertEquals(0, extractor.getViewCount()),
122+
() -> assertFalse(extractor.getThumbnails().isEmpty())
123+
);
124+
}
125+
126+
@Test
127+
void lockupViewModelNoDuration()
128+
throws FileNotFoundException, JsonParserException {
129+
final var json = JsonParser.object().from(new FileInputStream(getMockPath(
130+
YoutubeStreamInfoItemTest.class, "lockupViewModelNoDuration") + ".json"));
131+
final var timeAgoParser = TimeAgoPatternsManager.getTimeAgoParserFor(Localization.DEFAULT);
132+
final var extractor = new YoutubeStreamInfoItemLockupExtractor(json, timeAgoParser);
133+
assertAll(
134+
() -> assertEquals(StreamType.VIDEO_STREAM, extractor.getStreamType()),
135+
() -> assertFalse(extractor.isAd()),
136+
() -> assertEquals(-1, extractor.getDuration()),
137+
() -> assertFalse(extractor.getThumbnails().isEmpty())
138+
);
139+
}
140+
89141
@Test
90142
void emptyTitle() throws FileNotFoundException, JsonParserException {
91143
final var json = JsonParser.object().from(new FileInputStream(getMockPath(

extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/search/YoutubeSearchExtractorTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ protected SearchExtractor createExtractor() throws Exception {
235235
Collections.singletonList("Learn more")
236236
));
237237
}
238-
// testMoreRelatedItems is broken because a video has no duration shown
238+
// testMoreRelatedItems: a video in this mock has no duration badge; getDuration() now
239+
// returns -1 instead of throwing, but the mock may need re-recording before re-enabling.
239240
@Test @Override public void testMoreRelatedItems() { }
240241
@Override public StreamingService expectedService() { return YouTube; }
241242
@Override public String expectedName() { return QUERY; }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
{
2+
"contentImage": {
3+
"thumbnailViewModel": {
4+
"image": {
5+
"sources": [
6+
{
7+
"url": "https://i.ytimg.com/vi/LIVE_VIDEO_ID/hqdefault.jpg",
8+
"width": 168,
9+
"height": 94
10+
},
11+
{
12+
"url": "https://i.ytimg.com/vi/LIVE_VIDEO_ID/hqdefault.jpg",
13+
"width": 336,
14+
"height": 188
15+
}
16+
]
17+
},
18+
"overlays": [
19+
{
20+
"thumbnailBottomOverlayViewModel": {
21+
"badges": [
22+
{
23+
"thumbnailBadgeViewModel": {
24+
"badgeStyle": "THUMBNAIL_OVERLAY_BADGE_STYLE_LIVE",
25+
"text": "LIVE"
26+
}
27+
}
28+
]
29+
}
30+
},
31+
{
32+
"thumbnailHoverOverlayToggleActionsViewModel": {
33+
"buttons": []
34+
}
35+
}
36+
]
37+
}
38+
},
39+
"metadata": {
40+
"lockupMetadataViewModel": {
41+
"title": {
42+
"content": "LIVE_VIDEO_TITLE"
43+
},
44+
"image": {
45+
"decoratedAvatarViewModel": {
46+
"avatar": {
47+
"avatarViewModel": {
48+
"image": {
49+
"sources": [
50+
{
51+
"url": "https://yt3.ggpht.com/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
52+
"width": 68,
53+
"height": 68
54+
}
55+
]
56+
},
57+
"avatarImageSize": "AVATAR_SIZE_M"
58+
}
59+
},
60+
"a11yLabel": "Go to channel",
61+
"rendererContext": {
62+
"commandContext": {
63+
"onTap": {
64+
"innertubeCommand": {
65+
"commandMetadata": {
66+
"webCommandMetadata": {
67+
"url": "/@LIVE_CHANNEL_HANDLE"
68+
}
69+
},
70+
"browseEndpoint": {
71+
"browseId": "UCD_on7-zu7Zuc3zissQvrgw",
72+
"canonicalBaseUrl": "/@LIVE_CHANNEL_HANDLE"
73+
}
74+
}
75+
}
76+
}
77+
}
78+
}
79+
},
80+
"metadata": {
81+
"contentMetadataViewModel": {
82+
"metadataRows": [
83+
{
84+
"metadataParts": [
85+
{
86+
"text": {
87+
"content": "LIVE_CHANNEL_NAME",
88+
"styleRuns": [],
89+
"attachmentRuns": []
90+
}
91+
}
92+
]
93+
}
94+
],
95+
"delimiter": ""
96+
}
97+
},
98+
"menuButton": {}
99+
}
100+
},
101+
"contentId": "LIVE_VIDEO_ID",
102+
"contentType": "LOCKUP_CONTENT_TYPE_VIDEO"
103+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
{
2+
"contentImage": {
3+
"thumbnailViewModel": {
4+
"image": {
5+
"sources": [
6+
{
7+
"url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
8+
"width": 168,
9+
"height": 94
10+
},
11+
{
12+
"url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
13+
"width": 336,
14+
"height": 188
15+
}
16+
]
17+
},
18+
"overlays": [
19+
{
20+
"thumbnailHoverOverlayToggleActionsViewModel": {
21+
"buttons": []
22+
}
23+
}
24+
]
25+
}
26+
},
27+
"metadata": {
28+
"lockupMetadataViewModel": {
29+
"title": {
30+
"content": "VIDEO_TITLE_SHORT"
31+
},
32+
"image": {
33+
"decoratedAvatarViewModel": {
34+
"avatar": {
35+
"avatarViewModel": {
36+
"image": {
37+
"sources": [
38+
{
39+
"url": "https://yt3.ggpht.com/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
40+
"width": 68,
41+
"height": 68
42+
}
43+
]
44+
},
45+
"avatarImageSize": "AVATAR_SIZE_M"
46+
}
47+
},
48+
"a11yLabel": "Go to channel",
49+
"rendererContext": {
50+
"commandContext": {
51+
"onTap": {
52+
"innertubeCommand": {
53+
"commandMetadata": {
54+
"webCommandMetadata": {
55+
"url": "/@VIDEO_CHANNEL_HANDLE"
56+
}
57+
},
58+
"browseEndpoint": {
59+
"browseId": "UCD_on7-zu7Zuc3zissQvrgw",
60+
"canonicalBaseUrl": "/@VIDEO_CHANNEL_HANDLE"
61+
}
62+
}
63+
}
64+
}
65+
}
66+
}
67+
},
68+
"metadata": {
69+
"contentMetadataViewModel": {
70+
"metadataRows": [
71+
{
72+
"metadataParts": [
73+
{
74+
"text": {
75+
"content": "VIDEO_CHANNEL_NAME",
76+
"styleRuns": [],
77+
"attachmentRuns": []
78+
}
79+
}
80+
]
81+
},
82+
{
83+
"metadataParts": [
84+
{
85+
"text": {
86+
"content": "500K views"
87+
}
88+
},
89+
{
90+
"text": {
91+
"content": "1 month ago"
92+
}
93+
}
94+
]
95+
}
96+
],
97+
"delimiter": ""
98+
}
99+
},
100+
"menuButton": {}
101+
}
102+
},
103+
"contentId": "dQw4w9WgXcQ",
104+
"contentType": "LOCKUP_CONTENT_TYPE_VIDEO"
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
{
2+
"contentImage": {
3+
"thumbnailViewModel": {
4+
"image": {
5+
"sources": [
6+
{
7+
"url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
8+
"width": 168,
9+
"height": 94
10+
},
11+
{
12+
"url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
13+
"width": 336,
14+
"height": 188
15+
}
16+
]
17+
},
18+
"overlays": [
19+
{
20+
"thumbnailBottomOverlayViewModel": {
21+
"badges": [
22+
{
23+
"thumbnailBadgeViewModel": {
24+
"text": "16:14",
25+
"badgeStyle": "THUMBNAIL_OVERLAY_BADGE_STYLE_DEFAULT"
26+
}
27+
}
28+
]
29+
}
30+
},
31+
{
32+
"thumbnailHoverOverlayToggleActionsViewModel": {
33+
"buttons": []
34+
}
35+
}
36+
]
37+
}
38+
},
39+
"metadata": {
40+
"lockupMetadataViewModel": {
41+
"title": {
42+
"content": "VIDEO_TITLE"
43+
},
44+
"image": {
45+
"decoratedAvatarViewModel": {
46+
"avatar": {
47+
"avatarViewModel": {
48+
"image": {
49+
"sources": [
50+
{
51+
"url": "https://yt3.ggpht.com/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
52+
"width": 68,
53+
"height": 68
54+
}
55+
]
56+
},
57+
"avatarImageSize": "AVATAR_SIZE_M"
58+
}
59+
},
60+
"a11yLabel": "Go to channel",
61+
"rendererContext": {
62+
"commandContext": {
63+
"onTap": {
64+
"innertubeCommand": {
65+
"commandMetadata": {
66+
"webCommandMetadata": {
67+
"url": "/@VIDEO_CHANNEL_HANDLE"
68+
}
69+
},
70+
"browseEndpoint": {
71+
"browseId": "UCD_on7-zu7Zuc3zissQvrgw",
72+
"canonicalBaseUrl": "/@VIDEO_CHANNEL_HANDLE"
73+
}
74+
}
75+
}
76+
}
77+
}
78+
}
79+
},
80+
"metadata": {
81+
"contentMetadataViewModel": {
82+
"metadataRows": [
83+
{
84+
"metadataParts": [
85+
{
86+
"text": {
87+
"content": "VIDEO_CHANNEL_NAME",
88+
"styleRuns": [],
89+
"attachmentRuns": []
90+
}
91+
}
92+
]
93+
},
94+
{
95+
"metadataParts": [
96+
{
97+
"text": {
98+
"content": "1.2M views"
99+
}
100+
},
101+
{
102+
"text": {
103+
"content": "2 years ago"
104+
}
105+
}
106+
]
107+
}
108+
],
109+
"delimiter": ""
110+
}
111+
},
112+
"menuButton": {}
113+
}
114+
},
115+
"contentId": "dQw4w9WgXcQ",
116+
"contentType": "LOCKUP_CONTENT_TYPE_VIDEO"
117+
}

0 commit comments

Comments
 (0)