Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
Expand Down Expand Up @@ -217,6 +218,8 @@ private fun ConversationTitleBar(
text = state.subject?.title.orEmpty(),
style = CodeTheme.typography.textMedium,
color = CodeTheme.colors.textMain,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)

// Beside the name, not at the bar's edge: what is muted is this chat, and
Expand All @@ -237,6 +240,8 @@ private fun ConversationTitleBar(
),
style = CodeTheme.typography.textSmall,
color = CodeTheme.colors.textSecondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import com.flipcash.app.messenger.internal.screens.profile.ProfileShortcuts
import com.flipcash.app.theme.FlipcashPreview
import com.flipcash.services.models.UserProfile
import com.flipcash.services.models.chat.ChatType
import com.flipcash.services.models.chat.MuteState
import com.flipcash.services.models.chat.ViewerState
import com.getcode.navigation.core.CodeNavigator
import io.mockk.mockk
import org.junit.Rule
Expand Down Expand Up @@ -135,6 +137,43 @@ class ChatIdentityScreenshotTest {
capture("chat_top_bar_identity.png")
}

/** A DM name too long for the bar, muted so the bell has to keep its place beside it. */
@Test
fun rendersLongNameTopBar() {
val navigator = mockk<CodeNavigator>(relaxed = true)
val longNamedTipUser = namedTipUser.copy(
profile = namedTipUser.profile.copy(
displayName = "Grace Brewster Murray Hopper, Rear Admiral",
),
)
composeRule.mainClock.autoAdvance = false
composeRule.setContent {
FlipcashPreview(showBackground = true) {
Column(
modifier = Modifier.width(360.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
listOf(namedTipUser, longNamedTipUser).forEach { participant ->
ChatTopBar(
navigator = navigator,
state = ChatViewModel.State(
subject = ChatSubject.TipUser(participant),
chatType = ChatType.TIP_DM,
viewerState = ViewerState(mute = MuteState.Forever, version = 1L),
),
onBarHeightChange = {},
chatActionHandler = {},
dispatch = {},
)
}
}
}
}
repeat(10) { composeRule.mainClock.advanceTimeByFrame() }

capture("chat_top_bar_long_name.png")
}

@Test
fun rendersProfileHeaderIdentityStates() {
val joinDate = Instant.fromEpochMilliseconds(1_700_000_000_000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package com.flipcash.app.messenger.internal

import androidx.activity.ComponentActivity
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.SemanticsActions
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.semantics.SemanticsProperties
import androidx.compose.ui.test.SemanticsMatcher
import androidx.compose.ui.test.assert
import androidx.compose.ui.test.click
import androidx.compose.ui.test.hasClickAction
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.test.onNodeWithText
Expand All @@ -19,6 +22,8 @@ import com.flipcash.app.theme.FlipcashPreview
import com.flipcash.services.models.chat.ChatId
import com.flipcash.shared.chat.models.ChatAction
import com.flipcash.services.models.chat.ChatType
import com.flipcash.services.models.chat.MuteState
import com.flipcash.services.models.chat.ViewerState
import com.getcode.navigation.core.CodeNavigator
import io.mockk.mockk
import io.mockk.verify
Expand All @@ -27,6 +32,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.robolectric.annotation.GraphicsMode
import kotlin.test.assertEquals

/**
Expand All @@ -36,6 +42,8 @@ import kotlin.test.assertEquals
* these hold in place: the row still announces itself as a button and still acts on a tap.
*/
@RunWith(RobolectricTestRunner::class)
// Native graphics so text measures at its real width; legacy mode lays a long title out on one line.
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(sdk = [34], qualifiers = "w400dp-h800dp-xhdpi")
class ConversationTitleBarTest {

Expand All @@ -53,12 +61,22 @@ class ConversationTitleBarTest {

private val navigator = mockk<CodeNavigator>(relaxed = true)

private fun show(onAction: (ChatAction) -> Unit = {}) {
private val longTitle = "The Extraordinarily Long Name Of A Group That Keeps Going"

private fun show(
subject: ChatSubject = group,
viewerState: ViewerState? = null,
onAction: (ChatAction) -> Unit = {},
) {
composeTestRule.setContent {
FlipcashPreview {
ChatTopBar(
navigator = navigator,
state = ChatViewModel.State(chatType = ChatType.GROUP, subject = group),
state = ChatViewModel.State(
chatType = ChatType.GROUP,
subject = subject,
viewerState = viewerState,
),
onBarHeightChange = {},
chatActionHandler = onAction,
dispatch = {},
Expand Down Expand Up @@ -122,4 +140,25 @@ class ConversationTitleBarTest {

verify(exactly = 1) { navigator.pop() }
}

/**
* The bar is a fixed 56dp, so a title that wraps has its extra lines clipped by it. Muted, so the
* bell takes its share of the row too.
*/
@Test
fun `a long title stays on one line`() {
show(
subject = group.copy(groupTitle = longTitle),
viewerState = ViewerState(mute = MuteState.Forever, version = 1L),
)

assertEquals(1, composeTestRule.textLayout(longTitle).lineCount)
}

private fun AndroidComposeTestRule<*, *>.textLayout(text: String): TextLayoutResult {
val results = mutableListOf<TextLayoutResult>()
onNodeWithText(text, useUnmergedTree = true).fetchSemanticsNode()
.config[SemanticsActions.GetTextLayoutResult].action?.invoke(results)
return results.single()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import com.flipcash.services.models.chat.ChatId
import com.flipcash.services.models.chat.ChatRuleRequirement
import com.flipcash.services.models.chat.ChatRules
import com.flipcash.services.models.chat.ChatType
import com.flipcash.services.models.chat.MuteState
import com.flipcash.services.models.chat.ViewerState
import com.getcode.navigation.core.CodeNavigator
import com.getcode.opencode.model.financial.Fiat
import com.getcode.solana.keys.Mint
Expand Down Expand Up @@ -122,6 +124,39 @@ class GroupChromeScreenshotTest {
capture("group_top_bar.png")
}

/** A title too long for the bar, muted so the bell has to keep its place beside it. */
@Test
fun rendersLongGroupTitleBar() {
val navigator = mockk<CodeNavigator>(relaxed = true)
composeRule.mainClock.autoAdvance = false
composeRule.setContent {
FlipcashPreview(showBackground = true) {
Column(
modifier = Modifier.width(360.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
listOf(memberedGroup, memberedGroup.copy(groupTitle = LONG_GROUP_TITLE))
.forEach { group ->
ChatTopBar(
navigator = navigator,
state = ChatViewModel.State(
subject = group,
chatType = ChatType.GROUP,
viewerState = ViewerState(mute = MuteState.Forever, version = 1L),
),
onBarHeightChange = {},
chatActionHandler = {},
dispatch = {},
)
}
}
}
}
repeat(10) { composeRule.mainClock.advanceTimeByFrame() }

capture("group_top_bar_long_title.png")
}

@Test
fun rendersGroupInfoCard() {
composeRule.mainClock.autoAdvance = false
Expand Down Expand Up @@ -351,4 +386,8 @@ class GroupChromeScreenshotTest {
if (right < left || bottom < top) return this
return Bitmap.createBitmap(this, left, top, right - left + 1, bottom - top + 1)
}

private companion object {
const val LONG_GROUP_TITLE = "The Extraordinarily Long Name Of A Group That Keeps Going"
}
}
Loading