diff options
Diffstat (limited to 'app/src/test/java/org/terst/feedreader/ui/ImageZoomTest.kt')
| -rw-r--r-- | app/src/test/java/org/terst/feedreader/ui/ImageZoomTest.kt | 104 |
1 files changed, 104 insertions, 0 deletions
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. |
