test(arch): keep the shell's decisions out of the composables
The rules that let M4 ship without Robolectric are only true while they stay true, so they are asserted rather than trusted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wmy1BpCKi8KeSjaWhYuCPV
This commit is contained in:
@@ -70,6 +70,53 @@ class ArchitectureRulesTest {
|
||||
assertThat(offenders).isEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose may live in `ui/` and in the one activity that hosts it, and
|
||||
* nowhere else — the shell's decision surface is pure Kotlin by
|
||||
* construction, which is what earns the no-Robolectric posture (D17).
|
||||
*/
|
||||
private val composeAllowlist: List<String> = kotlinSources
|
||||
.filter { file -> file.readLines().any { it.startsWith("import androidx.compose.") } }
|
||||
.map { it.invariantSeparatorsPath }
|
||||
|
||||
@Test
|
||||
fun `Compose stays inside the ui package and its one host activity`() {
|
||||
val offenders = composeAllowlist.filterNot {
|
||||
it.contains("de/jeanlucmakiola/clockula/ui/") ||
|
||||
it.endsWith("de/jeanlucmakiola/clockula/MainActivity.kt")
|
||||
}
|
||||
|
||||
assertThat(offenders).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `the ui layer names no literal colour`() {
|
||||
val literals = listOf(
|
||||
"Color(0x",
|
||||
"Color.Red", "Color.Green", "Color.Blue", "Color.Yellow", "Color.Cyan",
|
||||
"Color.Magenta", "Color.White", "Color.Black", "Color.Gray",
|
||||
"Color.LightGray", "Color.DarkGray",
|
||||
)
|
||||
val ui = kotlinSources.filter { file ->
|
||||
val path = file.invariantSeparatorsPath
|
||||
path.contains("de/jeanlucmakiola/clockula/ui/") &&
|
||||
!path.contains("de/jeanlucmakiola/clockula/ui/theme/")
|
||||
}
|
||||
|
||||
val offenders = ui.containing(*literals.toTypedArray())
|
||||
|
||||
assertThat(offenders).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `exactly one file outside the ui package may import Compose`() {
|
||||
val outsideUi = composeAllowlist.filterNot {
|
||||
it.contains("de/jeanlucmakiola/clockula/ui/")
|
||||
}
|
||||
|
||||
assertThat(outsideUi).hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `the alarm engine and its pure neighbours stay free of Android types`() {
|
||||
val jvmTestable = kotlinSources.filter { file ->
|
||||
|
||||
Reference in New Issue
Block a user