From 60eb9985981dff8d91f804702268283102860a37 Mon Sep 17 00:00:00 2001 From: weishaupt <1+weishaupt@noreply.localhost> Date: Mon, 19 Oct 2026 01:20:28 +0000 Subject: [PATCH] Add app/src/test/java/space/bloggin/vellum --- .../java/space/bloggin/vellum/DataTest.kt | 31 +++++ .../java/space/bloggin/vellum/ScreensTest.kt | 110 ++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 app/src/test/java/space/bloggin/vellum/DataTest.kt create mode 100644 app/src/test/java/space/bloggin/vellum/ScreensTest.kt diff --git a/app/src/test/java/space/bloggin/vellum/DataTest.kt b/app/src/test/java/space/bloggin/vellum/DataTest.kt new file mode 100644 index 0000000..1d09b39 --- /dev/null +++ b/app/src/test/java/space/bloggin/vellum/DataTest.kt @@ -0,0 +1,31 @@ +package space.bloggin.vellum + +import androidx.test.core.app.ApplicationProvider +import org.junit.Assert.* +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [34]) +class DataTest { + private val b by lazy { Bible.get(ApplicationProvider.getApplicationContext()) } + + @Test fun everyCuratedRefParsesAndHasText() { + val bad = Votd.pool.filter { s -> val r = b.parseRef(s); r == null || r.verse == 0 || b.plainRange(0, r).isBlank() } + assertTrue("bad refs: $bad", bad.isEmpty()) + println("VOTD pool size " + Votd.pool.size) + } + @Test fun search() { + val h = b.search(0, "still waters", 0) + assertTrue(h.any { it.ref == Ref(19, 23, 2) }) + assertEquals(Ref(43, 3, 16), b.parseRef("jn 3:16")) + assertEquals(Ref(46, 13, 4, 7), b.parseRef("1 cor 13:4-7")) + assertEquals(Ref(19, 23, 0), b.parseRef("Psalm 23")) + assertTrue(b.strongsUses("G25").size > 50) + assertTrue(b.xrefs(43, 3, 16).isNotEmpty()) + Plans.all.forEach { p -> val d = p.build(b); assertEquals(p.days, d.size); assertTrue(p.name, d.all { it.isNotEmpty() }) } + assertEquals(31102, b.verseItems.size) + } +} diff --git a/app/src/test/java/space/bloggin/vellum/ScreensTest.kt b/app/src/test/java/space/bloggin/vellum/ScreensTest.kt new file mode 100644 index 0000000..801885f --- /dev/null +++ b/app/src/test/java/space/bloggin/vellum/ScreensTest.kt @@ -0,0 +1,110 @@ +package space.bloggin.vellum + +import android.graphics.Bitmap +import androidx.compose.ui.test.hasSetTextAction +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onRoot +import androidx.compose.ui.test.performTextInput +import androidx.test.core.app.ApplicationProvider +import com.github.takahirom.roborazzi.captureRoboImage +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode +import java.io.File + +@RunWith(RobolectricTestRunner::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@Config(sdk = [34], qualifiers = "w411dp-h891dp-xxhdpi") +class ScreensTest { + @get:Rule val rule = createAndroidComposeRule() + + private val out = File("build/shots").apply { mkdirs() } + private fun shot(name: String) { + rule.waitForIdle() + rule.mainClock.advanceTimeBy(2500) + rule.waitForIdle() + rule.onRoot().captureRoboImage(File(out, "$name.png").path) + } + private fun st() = rule.activity.state + private fun ui(block: AppState.() -> Unit) { rule.runOnUiThread { st().block() }; rule.waitForIdle() } + + @Test + fun phone() { + shot("01_votd") + ui { goTo(Ref(40, 5, 1)) } + shot("02_matthew5") + ui { selection.addAll(listOf(Ref(40, 5, 3), Ref(40, 5, 4), Ref(40, 5, 5))) } + shot("03_selection") + ui { selection.clear(); showSheet(Sheet.StrongsWords(Ref(43, 3, 16))) } + shot("04_strongs_words") + ui { showSheet(Sheet.StrongsDef("G25", "loved"), stack = true) } + shot("05_strongs_def") + ui { closeSheet(); showSheet(Sheet.Compare(listOf(Ref(43, 3, 16)))) } + shot("06_comparison") + ui { showSheet(Sheet.Xrefs(Ref(43, 3, 16))) } + shot("07_xrefs") + ui { closeSheet(); settings.wordStudy = true; goTo(Ref(1, 1, 1)) } + shot("08_genesis_wordstudy") + ui { settings.wordStudy = false; settings.night = true; goTo(Ref(19, 23, 1)) } + shot("09_night_ps23") + ui { settings.night = false; settings.mode = 1; goTo(Ref(43, 3, 16)) } + shot("10_reel") + ui { settings.mode = 0; settings.bg = 1; goTo(Ref(43, 14, 1)) } + shot("11_papyrus_john14") + ui { settings.bg = 0; open(Screen.Appearance) } + shot("12_appearance") + ui { back(); open(Screen.GoTo) } + shot("13_goto") + ui { back(); open(Screen.Search) } + rule.onNode(hasSetTextAction()).performTextInput("still waters") + shot("14_search") + ui { back(); user.startPlan("year2"); user.setDayDone("year2", 1, true); open(Screen.PlansScreen) } + shot("15_plans") + ui { back(); open(Screen.TopicsScreen) } + shot("16_topics") + ui { open(Screen.TopicDetail(Topics.all[1])) } + shot("17_topic_anxiety") + ui { screens.clear(); open(Screen.ShareImg(bible.plainRange(0, Ref(20, 3, 5, 6)), "Proverbs 3:5-6")) } + shot("18_share_image") + ui { screens.clear(); drawerOpen = true } + shot("19_drawer") + ui { drawerOpen = false; showSheet(Sheet.ReadAloud) } + shot("20_listen") + ui { closeSheet(); showSheet(Sheet.Translations) } + shot("21_translations") + ui { closeSheet(); showSheet(Sheet.NoteEdit(Ref(43, 3, 16))) } + shot("22_note") + ui { closeSheet(); user.setNote(Ref(43, 3, 17), "Not to condemn. Read this one to Dad."); user.setHighlight(listOf(Ref(43, 3, 16)), 1); user.toggleBookmark(Ref(43, 3, 18)); goTo(Ref(43, 3, 14)) } + shot("23_marks") + + // the share images themselves + val ctx = ApplicationProvider.getApplicationContext() + val text = Bible.get(ctx).plainRange(0, Ref(20, 3, 5, 6)) + ImageShape.entries.forEachIndexed { i, sh -> + val bmp = ShareImage.render(ctx, text, "Proverbs 3:5-6 (KJV)", ImageStyle(backdrop = listOf(0, 1, 3, 4)[i], font = i % 5, shape = sh)) + File(out, "img_${sh.name.lowercase()}.png").outputStream().use { bmp.compress(Bitmap.CompressFormat.PNG, 100, it) } + } + } +} + +@RunWith(RobolectricTestRunner::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@Config(sdk = [34], qualifiers = "w841dp-h760dp-xxhdpi") +class FoldTest { + @get:Rule val rule = createAndroidComposeRule() + + @Test + fun inner() { + val out = File("build/shots").apply { mkdirs() } + rule.runOnUiThread { rule.activity.state.settings.parallel = 2; rule.activity.state.goTo(Ref(40, 6, 9)) } + rule.waitForIdle(); rule.mainClock.advanceTimeBy(2500); rule.waitForIdle() + rule.onRoot().captureRoboImage(File(out, "30_fold_parallel.png").path) + rule.runOnUiThread { rule.activity.state.settings.parallel = -1; rule.activity.state.settings.mode = 1; rule.activity.state.goTo(Ref(19, 46, 10)) } + rule.waitForIdle(); rule.mainClock.advanceTimeBy(2500); rule.waitForIdle() + rule.onRoot().captureRoboImage(File(out, "31_fold_reel.png").path) + rule.runOnUiThread { rule.activity.state.settings.mode = 0 } + } +}