diff options
Diffstat (limited to 'app/src/test/java/org/terst')
| -rw-r--r-- | app/src/test/java/org/terst/feedreader/data/SettingsTest.kt | 23 | ||||
| -rw-r--r-- | app/src/test/java/org/terst/feedreader/ui/ImageZoomTest.kt | 104 |
2 files changed, 127 insertions, 0 deletions
diff --git a/app/src/test/java/org/terst/feedreader/data/SettingsTest.kt b/app/src/test/java/org/terst/feedreader/data/SettingsTest.kt index 5b2048b..5cace1a 100644 --- a/app/src/test/java/org/terst/feedreader/data/SettingsTest.kt +++ b/app/src/test/java/org/terst/feedreader/data/SettingsTest.kt @@ -29,4 +29,27 @@ class SettingsTest { fun `pinch zoom result is clamped to the maximum reader font size`() { assertEquals(READER_FONT_SIZE_RANGE_PX.last, pinchZoomFontSizePx(28, 3.0f)) } + + @Test + fun `text already laid out at the wanted size needs no zoom`() { + assertEquals(UNZOOMED_TEXT_ZOOM_PERCENT, readerTextZoomPercent(renderedPx = 18, targetPx = 18)) + } + + @Test + fun `a bigger wanted size lifts the text zoom proportionally`() { + assertEquals(156, readerTextZoomPercent(renderedPx = 18, targetPx = 28)) + } + + @Test + fun `a smaller wanted size drops the text zoom proportionally`() { + assertEquals(78, readerTextZoomPercent(renderedPx = 18, targetPx = 14)) + } + + @Test + fun `text zoom is measured against the size the page is laid out at, not the saved size`() { + // Pinch, release, pinch again before the reload at the new size has landed: the page is + // still laid out at 18px even though 22px is the saved size, so going on to 24px has to + // be 24/18 -- measuring it against the saved 22px would visibly shrink the text first. + assertEquals(133, readerTextZoomPercent(renderedPx = 18, targetPx = 24)) + } } diff --git a/app/src/test/java/org/terst/feedreader/ui/ImageZoomTest.kt b/app/src/test/java/org/terst/feedreader/ui/ImageZoomTest.kt index 81ecc33..3f7078d 100644 --- a/app/src/test/java/org/terst/feedreader/ui/ImageZoomTest.kt +++ b/app/src/test/java/org/terst/feedreader/ui/ImageZoomTest.kt @@ -169,6 +169,110 @@ class ImageZoomTest { } @Test + fun `a drag on a zoomed image pans it`() { + // The regression this function exists for: the viewer computed its pan bounds from + // values captured once at composition (viewport still zero, image not yet decoded), + // which pinned every offset to 0 -- a zoomed image simply refused to pan. + val panned = imageZoomTransform( + ImageZoomState(scale = 2f), + viewportSize = 1000f to 1000f, + intrinsicSize = 1000f to 1000f, + pan = -100f to -50f, + gestureZoom = 1f + ) + assertEquals(2f, panned.scale, 0.001f) + assertEquals(-100f, panned.offsetX, 0.001f) + assertEquals(-50f, panned.offsetY, 0.001f) + } + + @Test + fun `a drag on an unzoomed image leaves it where it is`() { + val panned = imageZoomTransform( + ImageZoomState(scale = 1f), + viewportSize = 1000f to 1000f, + intrinsicSize = 1000f to 1000f, + pan = 100f to 100f, + gestureZoom = 1f + ) + assertEquals(0f, panned.offsetX, 0.001f) + assertEquals(0f, panned.offsetY, 0.001f) + } + + @Test + fun `a pan stops at the edge of the scaled image`() { + val panned = imageZoomTransform( + ImageZoomState(scale = 2f, offsetX = 400f), + viewportSize = 1000f to 1000f, + intrinsicSize = 1000f to 1000f, + pan = 300f to 0f, + gestureZoom = 1f + ) + assertEquals(500f, panned.offsetX, 0.001f) + } + + @Test + fun `a pinch zooms and clamps the existing pan to the new scale`() { + val zoomedOut = imageZoomTransform( + ImageZoomState(scale = 2f, offsetX = 500f, offsetY = 500f), + viewportSize = 1000f to 1000f, + intrinsicSize = 1000f to 1000f, + pan = 0f to 0f, + gestureZoom = 0.1f + ) + assertEquals(1f, zoomedOut.scale, 0.001f) + assertEquals(0f, zoomedOut.offsetX, 0.001f) + assertEquals(0f, zoomedOut.offsetY, 0.001f) + } + + @Test + fun `a letterboxed image pans along its long axis only`() { + // A 2000x1000 photo fitted into a 1000x1000 viewport is 1000x500 on screen, so at 2x + // it fills the viewport exactly -- there's nothing above or below it to pan to, but + // dragging sideways still works. + val panned = imageZoomTransform( + ImageZoomState(scale = 2f), + viewportSize = 1000f to 1000f, + intrinsicSize = 2000f to 1000f, + pan = -200f to 300f, + gestureZoom = 1f + ) + assertEquals(-200f, panned.offsetX, 0.001f) + assertEquals(0f, panned.offsetY, 0.001f) + } + + @Test + fun `an image that hasn't reported its size yet can still be panned`() { + // Coil reports intrinsic size only once the image decodes; a pinch-and-drag before + // then is bounded by the viewport rather than refusing to move. + val panned = imageZoomTransform( + ImageZoomState(scale = 2f), + viewportSize = 1000f to 1000f, + intrinsicSize = 0f to 0f, + pan = -300f to 0f, + gestureZoom = 1f + ) + assertEquals(-300f, panned.offsetX, 0.001f) + } + + @Test + fun `double-tapping zooms in from the fitted size`() { + val zoomed = imageZoomDoubleTap(ImageZoomState(), 1000f to 1000f, 1000f to 1000f) + assertTrue(zoomed.scale > 1f) + } + + @Test + fun `double-tapping a panned, zoomed image returns it to fitted and centered`() { + val reset = imageZoomDoubleTap( + ImageZoomState(scale = 3f, offsetX = 300f, offsetY = -200f), + 1000f to 1000f, + 1000f to 1000f + ) + assertEquals(1f, reset.scale, 0.001f) + assertEquals(0f, reset.offsetX, 0.001f) + assertEquals(0f, reset.offsetY, 0.001f) + } + + @Test fun `an image whose size isn't known yet is assumed to fill the viewport`() { // Coil only reports intrinsic size once the image has actually decoded; until then // panning has to be bounded by something, and the viewport is the safe guess. |
