test: add dice roll result dialog tests and test tags (Closes #35)

Add DiceRollResultDialogTest with 4 Compose UI tests verifying dialog
shows dice count, success count, individual die chips, roll label,
and can be dismissed via OK button. Add test tags to DiceRollResultDialog
and update TestTagsTest to cover new dice roll dialog tags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shahondin1624
2026-03-13 13:43:15 +01:00
parent 9d530ed398
commit c8be6a695a
4 changed files with 152 additions and 6 deletions

View File

@@ -30,6 +30,13 @@ object TestTags {
// --- Dice / roll buttons ---
fun rollButton(name: String): String = "roll_button_${name.lowercase().replace(" ", "_")}"
// --- Dice roll result dialog ---
const val DICE_ROLL_DIALOG = "dice_roll_dialog"
const val DICE_ROLL_DICE_COUNT = "dice_roll_dice_count"
const val DICE_ROLL_SUCCESS_COUNT = "dice_roll_success_count"
const val DICE_ROLL_DISMISS_BUTTON = "dice_roll_dismiss_button"
fun dieChip(index: Int): String = "die_chip_$index"
// --- Top app bar ---
const val TOP_APP_BAR = "top_app_bar"
const val THEME_TOGGLE = "theme_toggle"

View File

@@ -8,9 +8,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.shahondin1624.lib.components.TestTags
import org.shahondin1624.lib.functions.DiceRoll
/**
@@ -29,6 +31,7 @@ fun DiceRollResultDialog(
AlertDialog(
onDismissRequest = onDismiss,
modifier = Modifier.testTag(TestTags.DICE_ROLL_DIALOG),
title = {
Text(
text = rollLabel,
@@ -46,10 +49,12 @@ fun DiceRollResultDialog(
) {
Text(
text = "${diceRoll.numberOfDice} dice rolled",
modifier = Modifier.testTag(TestTags.DICE_ROLL_DICE_COUNT),
style = MaterialTheme.typography.bodyMedium
)
Text(
text = "${diceRoll.numberOfSuccesses} successes",
modifier = Modifier.testTag(TestTags.DICE_ROLL_SUCCESS_COUNT),
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold,
color = if (diceRoll.numberOfSuccesses > 0)
@@ -92,7 +97,10 @@ fun DiceRollResultDialog(
}
},
confirmButton = {
TextButton(onClick = onDismiss) {
TextButton(
onClick = onDismiss,
modifier = Modifier.testTag(TestTags.DICE_ROLL_DISMISS_BUTTON)
) {
Text("OK")
}
}
@@ -106,14 +114,14 @@ private fun DiceResultGrid(results: List<Int>) {
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
for (value in results) {
DieChip(value)
for ((index, value) in results.withIndex()) {
DieChip(value, index)
}
}
}
@Composable
private fun DieChip(value: Int) {
private fun DieChip(value: Int, index: Int) {
val isSuccess = value >= 5
val isOne = value == 1
@@ -131,7 +139,8 @@ private fun DieChip(value: Int) {
Box(
modifier = Modifier
.size(32.dp)
.background(backgroundColor, CircleShape),
.background(backgroundColor, CircleShape)
.testTag(TestTags.dieChip(index)),
contentAlignment = Alignment.Center
) {
Text(

View File

@@ -0,0 +1,116 @@
package org.shahondin1624
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertTextContains
import androidx.compose.ui.test.onAllNodesWithTag
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.runComposeUiTest
import org.shahondin1624.lib.components.TestTags
import org.shahondin1624.lib.components.charactermodel.DiceRollResultDialog
import org.shahondin1624.lib.functions.DiceRoll
import kotlin.test.Test
import kotlin.test.assertTrue
@OptIn(ExperimentalTestApi::class)
class DiceRollResultDialogTest {
/** A deterministic DiceRoll with known results for testing. */
private fun testDiceRoll() = DiceRoll(
numberOfDice = 6,
numberOfSides = 6,
numberForSuccessOrHigher = 5,
result = listOf(1, 2, 4, 5, 5, 6),
numberOfSuccesses = 3
)
@Test
fun dialogShowsDiceCountAndSuccessCount() = runComposeUiTest {
setContent {
DiceRollResultDialog(
diceRoll = testDiceRoll(),
rollLabel = "Body",
onDismiss = {}
)
}
// Verify dialog is displayed
onNodeWithTag(TestTags.DICE_ROLL_DIALOG).assertIsDisplayed()
// Verify dice count text
onNodeWithTag(TestTags.DICE_ROLL_DICE_COUNT).assertTextContains("6 dice rolled")
// Verify success count text
onNodeWithTag(TestTags.DICE_ROLL_SUCCESS_COUNT).assertTextContains("3 successes")
}
@Test
fun dialogShowsIndividualDieChips() = runComposeUiTest {
val roll = testDiceRoll()
setContent {
DiceRollResultDialog(
diceRoll = roll,
rollLabel = "Agility",
onDismiss = {}
)
}
// Verify each die chip is displayed
for (i in roll.result.indices) {
onNodeWithTag(TestTags.dieChip(i)).assertIsDisplayed()
}
}
@Test
fun dialogShowsRollLabel() = runComposeUiTest {
setContent {
DiceRollResultDialog(
diceRoll = testDiceRoll(),
rollLabel = "Body",
onDismiss = {}
)
}
// Verify the roll label appears as title
onNodeWithText("Body").assertIsDisplayed()
}
@Test
fun dialogCanBeDismissedViaOkButton() = runComposeUiTest {
var dismissed = false
setContent {
var showDialog by remember { mutableStateOf(true) }
if (showDialog) {
DiceRollResultDialog(
diceRoll = testDiceRoll(),
rollLabel = "Body",
onDismiss = {
dismissed = true
showDialog = false
}
)
}
}
// Dialog should be visible initially
onNodeWithTag(TestTags.DICE_ROLL_DIALOG).assertIsDisplayed()
// Click dismiss button
onNodeWithTag(TestTags.DICE_ROLL_DISMISS_BUTTON).performClick()
// Verify dismiss callback was triggered
assertTrue(dismissed, "onDismiss callback should have been called")
// Dialog should no longer exist
val nodes = onAllNodesWithTag(TestTags.DICE_ROLL_DIALOG).fetchSemanticsNodes()
assertTrue(nodes.isEmpty(), "Dialog should be gone after dismiss")
}
}

View File

@@ -42,6 +42,16 @@ class TestTagsTest {
assertTrue(TestTags.PANEL_DAMAGE_MONITOR.isNotBlank())
}
@Test
fun diceRollDialogTagsAreDefined() {
assertTrue(TestTags.DICE_ROLL_DIALOG.isNotBlank())
assertTrue(TestTags.DICE_ROLL_DICE_COUNT.isNotBlank())
assertTrue(TestTags.DICE_ROLL_SUCCESS_COUNT.isNotBlank())
assertTrue(TestTags.DICE_ROLL_DISMISS_BUTTON.isNotBlank())
assertEquals("die_chip_0", TestTags.dieChip(0))
assertEquals("die_chip_5", TestTags.dieChip(5))
}
@Test
fun allTagsAreUnique() {
val staticTags = listOf(
@@ -55,7 +65,11 @@ class TestTagsTest {
TestTags.NAV_PERMANENT_DRAWER,
TestTags.TOP_APP_BAR,
TestTags.THEME_TOGGLE,
TestTags.MENU_BUTTON
TestTags.MENU_BUTTON,
TestTags.DICE_ROLL_DIALOG,
TestTags.DICE_ROLL_DICE_COUNT,
TestTags.DICE_ROLL_SUCCESS_COUNT,
TestTags.DICE_ROLL_DISMISS_BUTTON
)
assertEquals(staticTags.size, staticTags.toSet().size, "All static tags should be unique")
}