ui: share bulk download deletion confirmation

This commit is contained in:
austinried
2026-11-04 12:16:06 +00:00
parent 69f41b3459
commit 11abd4afbd
6 changed files with 219 additions and 91 deletions
@@ -6,8 +6,13 @@ import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.subtracks.data.model.BulkDownloadAction
import com.subtracks.data.model.DownloadList
import com.subtracks.ui.theme.SubtracksTheme
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.emptyFlow
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -55,6 +60,115 @@ class DeleteDownloadsDialogTest {
composeRule.onNodeWithText("512 B", substring = true).assertIsDisplayed()
}
@Test
fun sharedWorkflowLooksUpBytesAndConfirmsTheRequestedTargetOnce() {
val actions = mutableListOf<Triple<DownloadList, String, BulkDownloadAction>>()
lateinit var controller: PendingDownloadDeleteController
renderWorkflow(
downloadedBytes = { list, refId ->
assertEquals(DownloadList.Album, list)
assertEquals("al1", refId)
1_500_000
},
onAction = { list, refId, action -> actions += Triple(list, refId, action) },
onController = { controller = it },
)
composeRule.runOnIdle {
controller.onAction("Kid A", DownloadList.Album, "al1", BulkDownloadAction.Delete) { _, _, _ -> }
}
composeRule.waitUntil { controller.pending != null }
composeRule.onNodeWithText("Kid A", substring = true).assertIsDisplayed()
composeRule.onNodeWithText("MB", substring = true).assertIsDisplayed()
composeRule.onNodeWithText("Delete").performClick()
composeRule.runOnIdle {
assertEquals(listOf(Triple(DownloadList.Album, "al1", BulkDownloadAction.Delete)), actions)
assertNull(controller.pending)
}
}
@Test
fun sharedWorkflowCancelDoesNotConfirm() {
val actions = mutableListOf<BulkDownloadAction>()
lateinit var controller: PendingDownloadDeleteController
renderWorkflow(
onAction = { _, _, action -> actions += action },
onController = { controller = it },
)
composeRule.runOnIdle {
controller.onAction("Kid A", DownloadList.Album, "al1", BulkDownloadAction.Delete) { _, _, _ -> }
}
composeRule.waitUntil { controller.pending != null }
composeRule.onNodeWithText("Cancel").performClick()
composeRule.runOnIdle {
assertEquals(emptyList<BulkDownloadAction>(), actions)
assertNull(controller.pending)
}
}
@Test
fun sharedWorkflowDismissesWithTheContextMenu() {
val dismissals = MutableSharedFlow<Unit>(replay = 1)
lateinit var controller: PendingDownloadDeleteController
renderWorkflow(dismissals = dismissals, onController = { controller = it })
composeRule.runOnIdle {
controller.onAction("Kid A", DownloadList.Album, "al1", BulkDownloadAction.Delete) { _, _, _ -> }
}
composeRule.waitUntil { controller.pending != null }
composeRule.runOnIdle { dismissals.tryEmit(Unit) }
composeRule.waitUntil { controller.pending == null }
composeRule.onNodeWithText("Delete").assertDoesNotExist()
}
@Test
fun sharedWorkflowDispatchesNonDeleteActionsImmediately() {
val actions = mutableListOf<Triple<DownloadList, String, BulkDownloadAction>>()
var lookups = 0
lateinit var controller: PendingDownloadDeleteController
renderWorkflow(
downloadedBytes = { _, _ ->
lookups++
0
},
onAction = { list, refId, action -> actions += Triple(list, refId, action) },
onController = { controller = it },
)
composeRule.runOnIdle {
controller.onAction("Kid A", DownloadList.Album, "al1", BulkDownloadAction.Download) { list, refId, action ->
actions += Triple(list, refId, action)
}
}
composeRule.runOnIdle {
assertEquals(listOf(Triple(DownloadList.Album, "al1", BulkDownloadAction.Download)), actions)
assertEquals(0, lookups)
assertNull(controller.pending)
}
}
private fun renderWorkflow(
dismissals: kotlinx.coroutines.flow.Flow<Unit> = emptyFlow(),
downloadedBytes: suspend (DownloadList, String) -> Long = { _, _ -> 0 },
onAction: (DownloadList, String, BulkDownloadAction) -> Unit = { _, _, _ -> },
onController: (PendingDownloadDeleteController) -> Unit,
) {
composeRule.setContent {
SubtracksTheme {
val controller = rememberPendingDownloadDelete(dismissals, downloadedBytes)
onController(controller)
PendingDownloadDeleteConfirmation(controller) { pending ->
onAction(pending.list, pending.refId, BulkDownloadAction.Delete)
}
}
}
}
private fun render(
bytes: Long = 0,
onConfirm: () -> Unit = {},