// Copyright 2026 Umbra Tools (umbratools.com) // SPDX-License-Identifier: Apache-2.0 package com.bm.pagescribe.book import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test class PageCoverageTest { @Test fun `a book with no pages has no coverage`() { assertNull(PageCoverage.of(emptyMap())) } @Test fun `a single captured page is a complete one-page range`() { val coverage = PageCoverage.of(mapOf(7 to true))!! assertEquals(7, coverage.low) assertEquals(7, coverage.high) assertEquals(1, coverage.expected) assertEquals(1, coverage.captured) assertTrue(coverage.complete) assertEquals(emptyList(), coverage.missing) assertEquals(emptyList(), coverage.recapture) } @Test fun `a contiguous run is complete`() { val coverage = PageCoverage.of(mapOf(42 to true, 43 to true, 44 to true, 45 to true))!! assertEquals(42, coverage.low) assertEquals(45, coverage.high) assertEquals(4, coverage.expected) assertEquals(4, coverage.captured) assertEquals(0, coverage.toShoot) assertTrue(coverage.complete) } @Test fun `folios skipped between two spreads are reported missing`() { // The user shot 42/43 then 46/47 and flipped past two pages. val coverage = PageCoverage.of( mapOf(42 to true, 43 to true, 46 to true, 47 to true), )!! assertEquals(listOf(44, 45), coverage.missing) assertEquals(emptyList(), coverage.recapture) assertEquals(2, coverage.toShoot) assertFalse(coverage.complete) } @Test fun `a folio with no text needs to be re-shot, not marked missing`() { // Page 44's number was read but its body came out blank. val coverage = PageCoverage.of( mapOf(42 to true, 43 to true, 44 to false, 45 to true), )!! assertEquals(emptyList(), coverage.missing) assertEquals(listOf(44), coverage.recapture) assertEquals(3, coverage.captured) assertEquals(4, coverage.expected) assertEquals(1, coverage.toShoot) } @Test fun `a blank final page still widens the range`() { // The last spread produced only a folio on page 47. val coverage = PageCoverage.of(mapOf(46 to true, 47 to false))!! assertEquals(46, coverage.low) assertEquals(47, coverage.high) assertEquals(2, coverage.expected) assertEquals(listOf(47), coverage.recapture) } @Test fun `missing and blank pages are both counted as to shoot`() { val coverage = PageCoverage.of( mapOf(10 to true, 11 to false, 13 to true, 14 to false), )!! // 12 was never photographed; 11 and 14 were, but blank. assertEquals(listOf(12), coverage.missing) assertEquals(listOf(11, 14), coverage.recapture) assertEquals(2, coverage.captured) assertEquals(5, coverage.expected) assertEquals(3, coverage.toShoot) } @Test fun `slots run in folio order and carry their state`() { val coverage = PageCoverage.of(mapOf(3 to true, 4 to false, 6 to true))!! assertEquals(listOf(3, 4, 5, 6), coverage.slots.map { it.number }) assertEquals( listOf( PageState.CAPTURED, PageState.NEEDS_RECAPTURE, PageState.MISSING, PageState.CAPTURED, ), coverage.slots.map { it.state }, ) } }