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
|
val path = file.invariantSeparatorsPath
|
||||||
path.contains("de/jeanlucmakiola/clockula/domain/alarm/") ||
|
path.contains("de/jeanlucmakiola/clockula/domain/alarm/") ||
|
||||||
path.endsWith("de/jeanlucmakiola/clockula/alarm/AlarmEngine.kt") ||
|
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/timer/TimerEngine.kt") ||
|
||||||
path.endsWith("de/jeanlucmakiola/clockula/stopwatch/StopwatchEngine.kt") ||
|
path.endsWith("de/jeanlucmakiola/clockula/stopwatch/StopwatchEngine.kt") ||
|
||||||
path.endsWith("de/jeanlucmakiola/clockula/alarm/AlarmResolver.kt") ||
|
path.endsWith("de/jeanlucmakiola/clockula/alarm/AlarmResolver.kt") ||
|
||||||
@@ -308,4 +311,46 @@ class ArchitectureRulesTest {
|
|||||||
|
|
||||||
assertThat(offenders).isEmpty()
|
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