From b48988388ac3f55cc01fbd7edc51785bdd17fecd Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 3 Sep 2026 23:02:35 -0400 Subject: [PATCH] test(chat): cover the selection bar's re-narrowing of a stale bubble Gating the actions on the edit and delete windows (#1403) made the ToggleMessageSelection reducer re-apply them to the bubble it selects, so a transcript row resolved well inside a window no longer offers an action the server would answer CANNOT_EDIT or CANNOT_DELETE. Nothing asserted that. One test per window, because a window wired to the wrong capability passes either test alone. Both fail when the narrowing is dropped from the reducer. --- .../internal/ChatMessageActionReducerTest.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/apps/flipcash/features/messenger/src/test/kotlin/com/flipcash/app/messenger/internal/ChatMessageActionReducerTest.kt b/apps/flipcash/features/messenger/src/test/kotlin/com/flipcash/app/messenger/internal/ChatMessageActionReducerTest.kt index fdbeadda33..bbc557ea3b 100644 --- a/apps/flipcash/features/messenger/src/test/kotlin/com/flipcash/app/messenger/internal/ChatMessageActionReducerTest.kt +++ b/apps/flipcash/features/messenger/src/test/kotlin/com/flipcash/app/messenger/internal/ChatMessageActionReducerTest.kt @@ -3,6 +3,7 @@ package com.flipcash.app.messenger.internal import androidx.compose.foundation.text.input.TextFieldState import com.flipcash.services.models.chat.MessageContent import com.flipcash.shared.chat.MessageCapability +import com.flipcash.shared.chat.MessagePolicy import com.flipcash.shared.chat.models.ChatListItem import kotlin.test.Test import kotlin.test.assertEquals @@ -10,6 +11,7 @@ import kotlin.test.assertFalse import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue +import kotlin.time.Duration.Companion.minutes import kotlin.time.Instant /** @@ -58,6 +60,36 @@ class ChatMessageActionReducerTest { assertEquals(target.capabilities, state.selectionCapabilities) } + @Test + fun `selecting a bubble past its edit window drops Edit`() { + // The transcript resolved this bubble when it was mapped, which may have been well inside a + // window that has since closed. Offering Edit anyway costs a round-trip the server answers + // CANNOT_EDIT. sentAt is decades old, so any finite window here has closed. + val state = reduce( + ChatViewModel.State(messagePolicy = MessagePolicy(editWindow = 5.minutes)), + ChatViewModel.Event.ToggleMessageSelection(bubble(1)), + ) + + assertEquals( + setOf(MessageCapability.Copy, MessageCapability.Delete), + state.selectionCapabilities, + ) + } + + @Test + fun `selecting a bubble past its delete window drops Delete`() { + // Separate from the case above so a window wired to the wrong capability cannot pass both. + val state = reduce( + ChatViewModel.State(messagePolicy = MessagePolicy(deleteWindow = 5.minutes)), + ChatViewModel.Event.ToggleMessageSelection(bubble(1)), + ) + + assertEquals( + setOf(MessageCapability.Copy, MessageCapability.Edit), + state.selectionCapabilities, + ) + } + @Test fun `long-pressing the selected bubble again clears the bar`() { val target = bubble(1)