1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
package org.terst.feedreader.ui
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
/**
* The YouTube placeholder: recognising one, and building a page its embed will actually play in.
*
* Both halves come from the same report: "YouTube play is misconfigured, long click on YouTube
* placeholder should open the URL directly."
*/
class YouTubeLinksTest {
/**
* What a long-press on the reader's video placeholder actually reports.
*
* Not the link's href, which is what the first version of this assumed and got wrong on the
* device: the placeholder is `<a href="...watch?v=ID"><img src="...i.ytimg.com/vi/ID/..."></a>`,
* and for an image inside a link WebView's hit test reports SRC_IMAGE_ANCHOR_TYPE with the
* *image's* URL in `extra`, not the anchor's. Long-pressing the thumbnail produced the
* ordinary link menu showing `https://i.ytimg.com/vi/dQw4w9WgXcQ/hq720.jpg`.
*
* The thumbnail URL carries the video id, so it is resolved back to the video.
*/
@Test
fun `a long-press on the thumbnail resolves to the video, which is what WebView reports`() {
assertEquals(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
youTubeTargetForLongPress("https://i.ytimg.com/vi/dQw4w9WgXcQ/hq720.jpg")
)
}
@Test
fun `any thumbnail size resolves, since the reader has used more than one`() {
assertEquals(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
youTubeTargetForLongPress("https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg")
)
assertEquals(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
youTubeTargetForLongPress("https://i9.ytimg.com/vi_webp/dQw4w9WgXcQ/hq720.webp")
)
}
@Test
fun `a watch link resolves to itself, for wherever one does come through`() {
assertEquals(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
youTubeTargetForLongPress("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
)
}
@Test
fun `a short youtu-be link resolves to the video`() {
assertEquals(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
youTubeTargetForLongPress("https://youtu.be/dQw4w9WgXcQ")
)
}
@Test
fun `an ordinary article link is not a video`() {
assertNull(youTubeTargetForLongPress("https://www.nytimes.com/2026/10/20/us/politics/x.html"))
}
@Test
fun `an ordinary article image is not a video`() {
assertNull(youTubeTargetForLongPress("https://www.westhawaiitoday.com/wp-content/uploads/reef.jpg"))
}
@Test
fun `a lookalike host is not YouTube`() {
assertNull(youTubeTargetForLongPress("https://notyoutube.com/watch?v=dQw4w9WgXcQ"))
assertNull(youTubeTargetForLongPress("https://youtube.com.evil.example/watch?v=dQw4w9WgXcQ"))
assertNull(youTubeTargetForLongPress("https://i.ytimg.com.evil.example/vi/dQw4w9WgXcQ/hq720.jpg"))
}
@Test
fun `a YouTube link that is not one video stays on the ordinary menu`() {
assertNull(youTubeTargetForLongPress("https://www.youtube.com/@someone"))
assertNull(youTubeTargetForLongPress("https://www.youtube.com/playlist?list=PL123"))
}
@Test
fun `rubbish is not a video`() {
assertNull(youTubeTargetForLongPress(""))
assertNull(youTubeTargetForLongPress("not a url at all"))
}
// --- the embed ----------------------------------------------------------------------
@Test
fun `the embed url is the privacy-preserving nocookie one, playing inline`() {
val url = youTubeEmbedUrl("dQw4w9WgXcQ")
assertTrue(url.startsWith("https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ"))
assertTrue(url.contains("autoplay=1"))
assertTrue(url.contains("playsinline=1"))
}
@Test
fun `the embed is sent a referrer, which is the whole reason it plays`() {
assertTrue(YOUTUBE_EMBED_REFERRER.startsWith("https://"))
}
@Test
fun `the referrer says nothing about what is being read`() {
// A constant, so YouTube learns the app and nothing else. The article's own URL would
// work just as well and would tell YouTube what he reads, which is the thing the
// nocookie domain is already chosen to avoid.
assertFalse(YOUTUBE_EMBED_REFERRER.contains("?"))
assertTrue("a reserved TLD can never become somebody's real site", YOUTUBE_EMBED_REFERRER.contains(".invalid"))
}
@Test
fun `a video id that could break out of the url is scrubbed`() {
val url = youTubeEmbedUrl("""a"><script>alert(1)</script>""")
assertFalse("markup from the id reached the url: $url", url.contains("<"))
assertTrue(url.startsWith("https://www.youtube-nocookie.com/embed/ascriptalert1script?"))
}
@Test
fun `the watch link for a video is the one a phone can hand to the YouTube app`() {
assertEquals("https://www.youtube.com/watch?v=dQw4w9WgXcQ", youTubeWatchUrl("dQw4w9WgXcQ"))
}
// --- giving the player a height -------------------------------------------------------
@Test
fun `the fit script sizes the player from the height the page does know`() {
val js = YOUTUBE_FIT_PLAYER_JS
assertTrue("percentage heights are what resolve to zero: $js", js.contains("window.innerHeight"))
assertTrue(js.contains("dispatchEvent"))
}
@Test
fun `the fit script overrides YouTube's own styles, which would otherwise win`() {
assertTrue(YOUTUBE_FIT_PLAYER_JS.contains("!important"))
}
@Test
fun `the fit script covers the video element and the containers above it`() {
val js = YOUTUBE_FIT_PLAYER_JS
assertTrue(js.contains("html,body"))
assertTrue(js.contains("#movie_player"))
assertTrue(js.contains("video{height:"))
}
@Test
fun `the fit script does nothing when the page has no height to copy`() {
assertTrue("must not pin the player to zero", YOUTUBE_FIT_PLAYER_JS.contains("if (!h) { return; }"))
}
}
|