diff --git a/app/src/androidTest/java/de/jeanlucmakiola/clockula/ui/AlarmsInstrumentedTest.kt b/app/src/androidTest/java/de/jeanlucmakiola/clockula/ui/AlarmsInstrumentedTest.kt index 0ec1af1..ace87ca 100644 --- a/app/src/androidTest/java/de/jeanlucmakiola/clockula/ui/AlarmsInstrumentedTest.kt +++ b/app/src/androidTest/java/de/jeanlucmakiola/clockula/ui/AlarmsInstrumentedTest.kt @@ -209,11 +209,13 @@ class AlarmsInstrumentedTest { // No confirmation: the list underneath offers the Undo instead. composeTestRule.onNodeWithContentDescription(string(R.string.editor_delete)).performClick() + // The delete runs on the application scope, which Compose's idling + // does not track, so the test waits for storage rather than for idle. + composeTestRule.waitUntil(STORAGE_TIMEOUT_MS) { stored(id) == null } composeTestRule.waitForIdle() composeTestRule.onNodeWithText("Work").assertDoesNotExist() composeTestRule.onNodeWithText(string(R.string.action_undo)).assertIsDisplayed() - assertThat(stored(id)).isNull() } @OptIn(ExperimentalTestApi::class) @@ -225,13 +227,18 @@ class AlarmsInstrumentedTest { composeTestRule.onNodeWithText("Work") .performCustomAccessibilityActionWithLabel(string(R.string.action_delete)) + composeTestRule.waitUntil(STORAGE_TIMEOUT_MS) { stored(id) == null } composeTestRule.waitForIdle() - assertThat(stored(id)).isNull() composeTestRule.onNodeWithText(string(R.string.action_undo)).performClick() + composeTestRule.waitUntil(STORAGE_TIMEOUT_MS) { stored(id) != null } composeTestRule.waitForIdle() composeTestRule.onNodeWithText("Work").assertIsDisplayed() - assertThat(stored(id)).isNotNull() + } + + private companion object { + /** Delete and restore run on the application scope, outside Compose's idling. */ + const val STORAGE_TIMEOUT_MS = 5_000L } } diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/ui/timers/TimersViewModel.kt b/app/src/main/java/de/jeanlucmakiola/clockula/ui/timers/TimersViewModel.kt index 234130a..b672fde 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/ui/timers/TimersViewModel.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/ui/timers/TimersViewModel.kt @@ -100,8 +100,10 @@ class TimersViewModel @Inject internal constructor( * Through the engine, so a *ringing* timer cannot be deleted into a stuck * ring (D2). Still no confirmation; the snackbar's Undo now covers the slip. */ - fun onDelete(timerId: Long) = launchOnEngine { - engine.delete(timerId)?.let(undo::offer) + fun onDelete(timerId: Long) { + // On the application scope, as the alarm list's is: a back press while + // the engine lock is busy must not drop a delete the user saw happen. + appScope.launch { engine.delete(timerId)?.let(undo::offer) } } /**