test(arch): the platform's intents stay at the door, and the show intent stays pointed
Three new rules. Nothing under `domain/` may name `android.content.Intent`, so the validator stays testable without a device. The `AlarmClock` action strings may be named only under `domain/interop/` and `interop/`. And `AndroidAlarmScheduler` may not name `AlarmRingActivity` — the defect this milestone fixed would otherwise come back the next time someone reaches for a "show the alarm" intent.
This commit is contained in:
@@ -135,6 +135,9 @@ class ArchitectureRulesTest {
|
||||
val path = file.invariantSeparatorsPath
|
||||
path.contains("de/jeanlucmakiola/clockula/domain/alarm/") ||
|
||||
path.endsWith("de/jeanlucmakiola/clockula/alarm/AlarmEngine.kt") ||
|
||||
// M9 D28: the AlarmClock orchestrator is JVM-testable by
|
||||
// construction, exactly as the three engines are.
|
||||
path.endsWith("de/jeanlucmakiola/clockula/interop/AlarmClockHandler.kt") ||
|
||||
path.endsWith("de/jeanlucmakiola/clockula/timer/TimerEngine.kt") ||
|
||||
path.endsWith("de/jeanlucmakiola/clockula/stopwatch/StopwatchEngine.kt") ||
|
||||
path.endsWith("de/jeanlucmakiola/clockula/alarm/AlarmResolver.kt") ||
|
||||
@@ -308,4 +311,46 @@ class ArchitectureRulesTest {
|
||||
|
||||
assertThat(offenders).isEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* M9 D28: one vocabulary for the platform's `AlarmClock` strings, so a
|
||||
* second file cannot hardcode `"android.intent.action.SET_ALARM"` and drift
|
||||
* away from the door everyone else goes through.
|
||||
*/
|
||||
@Test
|
||||
fun `the platform alarm-clock literals live in one file`() {
|
||||
val offenders = kotlinSources
|
||||
.containing("android.intent.action.SET_ALARM", "android.intent.extra.alarm.")
|
||||
.filterNot { it.endsWith("de/jeanlucmakiola/clockula/domain/interop/AlarmClockContract.kt") }
|
||||
|
||||
assertThat(offenders).isEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* M9 D21: the next-alarm show intent is what the system opens when the user
|
||||
* taps the status-bar alarm icon. Pointing it at the ring screen opens a
|
||||
* ring screen for an alarm that is not ringing, which closes itself — so
|
||||
* the fix is pinned rather than left to be re-broken.
|
||||
*/
|
||||
@Test
|
||||
fun `the next-alarm show intent never names the ring screen`() {
|
||||
val scheduler = kotlinSources
|
||||
.filter { it.invariantSeparatorsPath.endsWith("alarm/android/AndroidAlarmScheduler.kt") }
|
||||
|
||||
assertThat(scheduler.usingInCode("AlarmRingActivity")).isEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* M9 D28: the screen does not parse intents — the mirror of "the screen
|
||||
* schedules no timer and decides no ring".
|
||||
*/
|
||||
@Test
|
||||
fun `the screen parses no intent from another app`() {
|
||||
val ui = kotlinSources
|
||||
.filter { it.invariantSeparatorsPath.contains("de/jeanlucmakiola/clockula/ui/") }
|
||||
|
||||
val offenders = ui.usingInCode("AlarmClockHandler", "AlarmClockRequests", "IntentExtras")
|
||||
|
||||
assertThat(offenders).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user