105 lines
3.6 KiB
Kotlin
105 lines
3.6 KiB
Kotlin
// 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<Int>(), coverage.missing)
|
|
assertEquals(emptyList<Int>(), 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<Int>(), 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<Int>(), 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 },
|
|
)
|
|
}
|
|
}
|