package org.terst.feedreader.ui import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test class ImageZoomTest { @Test fun `a bare image is wrapped in a zoom link pointing at its own source`() { val html = linkifyImagesForZoom("""
hi
""")
assertEquals(
"""hi
""",
html
)
}
@Test
fun `an image already inside a link is left alone`() {
// The YouTube thumbnail ReaderExtractor synthesizes is exactly this shape -- wrapping it
// again would swallow the tap that's supposed to play the video.
val original =
"""
"""
assertEquals(original, linkifyImagesForZoom(original))
}
@Test
fun `an image after a closed link is still wrapped`() {
val html = linkifyImagesForZoom("""t
""")
assertTrue(html.endsWith("""
"""))
}
@Test
fun `a protocol-relative image source becomes an https zoom target`() {
val html = linkifyImagesForZoom("""
""")
assertEquals("""
""", html)
}
@Test
fun `a relative image source is left alone`() {
// Relative srcs resolve against the WebView's base URL, which a custom-scheme href
// can't reproduce -- better to leave the image un-zoomable than to build a dead link.
val original = """
"""
assertEquals(original, linkifyImagesForZoom(original))
}
@Test
fun `a data uri image is left alone`() {
val original = """
""")
assertTrue(html.contains(""""""))
}
@Test
fun `a zoom-scheme url resolves back to the image it wraps`() {
assertEquals("https://ex.com/a.jpg", zoomableImageTarget("feedreader-image:https://ex.com/a.jpg"))
}
@Test
fun `a plain link straight to an image file is a zoom target too`() {
// WordPress's default "link to media file" wraps article images in exactly this --
// the image is inside an , so it never gets a zoom-scheme href of its own.
assertEquals("https://ex.com/photo.JPEG?w=900", zoomableImageTarget("https://ex.com/photo.JPEG?w=900"))
}
@Test
fun `an ordinary article link is not a zoom target`() {
assertNull(zoomableImageTarget("https://ex.com/2026/09/some-article"))
}
@Test
fun `an svg link is not a zoom target`() {
// Coil's default decoders can't render SVG, so a viewer opened on one shows nothing.
assertNull(zoomableImageTarget("https://ex.com/icon.svg"))
}
@Test
fun `reader html makes an article's own images zoomable`() {
val html = wrapReaderHtml("""x
""")
assertTrue(html.contains("""
"""))
}
@Test
fun `reader html makes the synthesized hero image zoomable too`() {
val html = wrapReaderHtml("no image of its own
", imageUrl = "https://ex.com/hero.jpg") assertTrue(html.contains("""""")) assertTrue(html.contains("""class="article-hero"""")) } @Test fun `reader html leaves a youtube thumbnail tapping through to the video`() { // The thumbnail is synthesized from an