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
@@ -0,0 +1,96 @@
package com.plainstudio.stackcasino.feature.lobby

import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.plainstudio.stackcasino.navigation.Route
import com.plainstudio.stackcasino.ui.theme.StackcasinoTheme
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class LobbyScreenTest {
@get:Rule
val composeRule = createComposeRule()

@Test
fun success_state_renders_user_balance_games_and_recent_activity() {
composeRule.setContent {
StackcasinoTheme {
LobbyScreen(
state = LobbyUiState.Success(previewLobbyData()),
onNavigate = {},
onRetry = {},
onUseCache = {},
)
}
}

composeRule.onNodeWithText("John Doe").assertIsDisplayed()
composeRule.onNodeWithText("$1,234.56").assertIsDisplayed()
composeRule.onNodeWithText("European Roulette").assertIsDisplayed()
composeRule.onNodeWithText("LAST PLAYED").assertIsDisplayed()
composeRule.onNodeWithText("Deposit").assertIsDisplayed()
// Recent activity sits below the fold on shorter viewports;
// scrollTo lands it before asserting.
composeRule.onNodeWithText("+$125.50").performScrollTo().assertIsDisplayed()
}

@Test
fun success_state_routes_game_card_taps_to_the_matching_game_route() {
var navigated: Route? = null
composeRule.setContent {
StackcasinoTheme {
LobbyScreen(
state = LobbyUiState.Success(previewLobbyData()),
onNavigate = { navigated = it },
onRetry = {},
onUseCache = {},
)
}
}

// The Crash label appears twice (game card + recent activity); the
// unambiguous handle is the European Roulette card.
composeRule.onNodeWithText("European Roulette").performClick()
composeRule.waitForIdle()

assertEquals(Route.Roulette, navigated)
}

@Test
fun error_state_renders_retry_and_use_cache_actions() {
var retried = false
var usedCache = false
composeRule.setContent {
StackcasinoTheme {
LobbyScreen(
state =
LobbyUiState.Error(
message = "Failed to sync.",
lastSyncedLabel = "Last synced 4 minutes ago",
),
onNavigate = {},
onRetry = { retried = true },
onUseCache = { usedCache = true },
)
}
}

composeRule.onNodeWithText("Connection Lost").assertIsDisplayed()
composeRule.onNodeWithText("RETRY").assertIsDisplayed()
composeRule.onNodeWithText("USE CACHE").assertIsDisplayed()

composeRule.onNodeWithText("RETRY").performClick()
composeRule.onNodeWithText("USE CACHE").performClick()
composeRule.waitForIdle()

assertEquals(true, retried)
assertEquals(true, usedCache)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.plainstudio.stackcasino.R
import com.plainstudio.stackcasino.ui.components.gridBackground
import com.plainstudio.stackcasino.ui.theme.AccentViolet
import com.plainstudio.stackcasino.ui.theme.AccentVioletSoft
import com.plainstudio.stackcasino.ui.theme.SemanticDanger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,47 +59,6 @@ internal fun Modifier.backgroundGlow(): Modifier =
drawRect(brush = bottomGlow)
}

/**
* Subtle 24dp dotted grid. Mockup CSS (styles.css):
*
* .grid-bg {
* background-image:
* linear-gradient(rgba(255,255,255,0.035) 1px, transparent 1px),
* linear-gradient(90deg, rgba(255,255,255,0.035) 1px, transparent 1px);
* background-size: 24px 24px;
* }
*
* The mockup wraps the grid div with `opacity-40` which would bring the
* effective alpha down to ~0.014; we keep the underlying 0.035 because
* the violet glow saturates the surface and a slightly stronger grid
* stays perceptible.
*/
internal fun Modifier.gridBackground(): Modifier =
drawBehind {
val cellPx = GridCellSize.toPx()
val strokePx = GridLineWidth.toPx()
var x = 0f
while (x <= size.width) {
drawLine(
color = GridLineColor,
start = Offset(x, 0f),
end = Offset(x, size.height),
strokeWidth = strokePx,
)
x += cellPx
}
var y = 0f
while (y <= size.height) {
drawLine(
color = GridLineColor,
start = Offset(0f, y),
end = Offset(size.width, y),
strokeWidth = strokePx,
)
y += cellPx
}
}

// ---------------------------------------------------------------------------
// Brand glow shadow (sign-in / loading button)
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -271,11 +230,6 @@ private const val BOTTOM_GLOW_CENTER_X_FRACTION = 0.2f
private const val BOTTOM_GLOW_CENTER_Y_FRACTION = 0.9f
private const val BOTTOM_GLOW_RADIUS_FRACTION = 0.55f

// Grid background.
private val GridLineColor = Color.White.copy(alpha = 0.035f)
private val GridCellSize = 24.dp
private val GridLineWidth = 1.dp

// Brand glow shadow.
private val ButtonGlowColor = AccentViolet.copy(alpha = 0.35f)
private val ButtonGlowElevation = 12.dp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.plainstudio.stackcasino.feature.lobby

/**
* Static seed used by both the lobby @Preview composables and the live
* navigation entry until the Firestore-backed ViewModel ships.
*
* Numbers and labels mirror the mockup mock-data
* (mockup/js/screens/lobby.js) so the rendered screen matches the
* design source one-for-one.
*/
internal fun previewLobbyData(): LobbyData =
LobbyData(
user = previewUser(),
balance = previewBalance(),
session = previewSession(),
games = previewGames(),
recentActivity = previewRecentActivity(),
)

private fun previewUser(): UserSummary =
UserSummary(
displayName = "John Doe",
greeting = "Good Evening",
hasUnreadNotifications = true,
)

private fun previewBalance(): BalanceSummary =
BalanceSummary(
amountLabel = "$1,234.56",
currencyCode = "USDC",
networkLabel = "Polygon",
todayPnLLabel = "+$45.00 Today",
lockedSubtitle = "No active bets",
)

private fun previewSession(): SessionStats = SessionStats(rounds = 8, wins = 5, losses = 3)

private fun previewGames(): List<GameCardData> =
listOf(
GameCardData(
key = GameKey.Roulette,
title = "European Roulette",
subtitle = "European",
infoRight = "RTP 97.3%",
),
GameCardData(
key = GameKey.Blackjack,
title = "Blackjack",
subtitle = "Classic",
infoRight = "RTP 99.5%",
),
GameCardData(
key = GameKey.Crash,
title = "Crash",
subtitle = "Multiplier",
infoRight = "Last 2.41x",
isLastPlayed = true,
),
GameCardData(
key = GameKey.Mines,
title = "Mines",
subtitle = "5x5 Grid",
infoRight = "Up to 24x",
),
GameCardData(
key = GameKey.Coinflip,
title = "Coinflip",
subtitle = "x2 Payout",
infoRight = "Heads · Tails",
),
)

private fun previewRecentActivity(): List<RecentRound> =
listOf(
RecentRound(
game = GameKey.Crash,
gameLabel = "Crash",
agoLabel = "2m ago",
resultLabel = "2.51x",
amountLabel = "+$125.50",
outcome = RoundOutcome.Win,
),
RecentRound(
game = GameKey.Roulette,
gameLabel = "Roulette",
agoLabel = "18m ago",
resultLabel = "7x",
amountLabel = "+$175.00",
outcome = RoundOutcome.Win,
),
RecentRound(
game = GameKey.Blackjack,
gameLabel = "Blackjack",
agoLabel = "1h ago",
resultLabel = "Bust",
amountLabel = "-$100.00",
outcome = RoundOutcome.Loss,
),
)
Loading
Loading