feat: add centralized TestTags and testTag modifiers (Closes #31) #44
@@ -17,9 +17,11 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.ui.tooling.preview.Preview
|
||||
import org.shahondin1624.lib.components.TestTags
|
||||
import org.shahondin1624.lib.components.UiConstants
|
||||
import org.shahondin1624.lib.components.charactermodel.attributespage.AttributesPage
|
||||
import org.shahondin1624.model.EXAMPLE_CHARACTER
|
||||
@@ -73,7 +75,9 @@ private fun AppContent(
|
||||
onClick = {
|
||||
scope.launch { drawerState.close() }
|
||||
},
|
||||
modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp)
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 12.dp, vertical = 4.dp)
|
||||
.testTag(TestTags.NAV_CHARACTER_SHEET)
|
||||
)
|
||||
|
||||
NavigationDrawerItem(
|
||||
@@ -84,7 +88,9 @@ private fun AppContent(
|
||||
scope.launch { drawerState.close() }
|
||||
// TODO: Navigate to settings
|
||||
},
|
||||
modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp)
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 12.dp, vertical = 4.dp)
|
||||
.testTag(TestTags.NAV_SETTINGS)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -95,7 +101,8 @@ private fun AppContent(
|
||||
TopAppBar(
|
||||
title = { Text("Shadowrun Character Sheet") },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
scope.launch {
|
||||
if (drawerState.isClosed) {
|
||||
drawerState.open()
|
||||
@@ -103,12 +110,17 @@ private fun AppContent(
|
||||
drawerState.close()
|
||||
}
|
||||
}
|
||||
}) {
|
||||
},
|
||||
modifier = Modifier.testTag(TestTags.MENU_BUTTON)
|
||||
) {
|
||||
Icon(Icons.Default.Menu, contentDescription = "Menu")
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
IconButton(onClick = { isDark = !isDark }) {
|
||||
IconButton(
|
||||
onClick = { isDark = !isDark },
|
||||
modifier = Modifier.testTag(TestTags.THEME_TOGGLE)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (isDark) {
|
||||
Icons.Default.LightMode
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.shahondin1624.lib.components
|
||||
|
||||
/**
|
||||
* Centralized test tag strings for Compose UI test identification.
|
||||
*
|
||||
* Usage: `Modifier.testTag(TestTags.attributeCard("Body"))`
|
||||
*
|
||||
* Tags that reference components not yet implemented are included so that
|
||||
* future stories can import them without creating a new file.
|
||||
*/
|
||||
object TestTags {
|
||||
// --- Attribute cards ---
|
||||
fun attributeCard(type: String): String = "attribute_card_${type.lowercase()}"
|
||||
|
||||
// --- Talent cards ---
|
||||
fun talentCard(name: String): String = "talent_card_${name.lowercase().replace(" ", "_")}"
|
||||
|
||||
// --- Panels (defined for future character display stories) ---
|
||||
const val PANEL_CHARACTER_HEADER = "panel_character_header"
|
||||
const val PANEL_RESOURCES = "panel_resources"
|
||||
const val PANEL_DERIVED_ATTRIBUTES = "panel_derived_attributes"
|
||||
const val PANEL_DAMAGE_MONITOR = "panel_damage_monitor"
|
||||
|
||||
// --- Navigation items ---
|
||||
const val NAV_CHARACTER_SHEET = "nav_character_sheet"
|
||||
const val NAV_SETTINGS = "nav_settings"
|
||||
|
||||
// --- Dice / roll buttons ---
|
||||
fun rollButton(name: String): String = "roll_button_${name.lowercase().replace(" ", "_")}"
|
||||
|
||||
// --- Top app bar ---
|
||||
const val TOP_APP_BAR = "top_app_bar"
|
||||
const val THEME_TOGGLE = "theme_toggle"
|
||||
const val MENU_BUTTON = "menu_button"
|
||||
}
|
||||
@@ -14,9 +14,11 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.shahondin1624.lib.components.TestTags
|
||||
import org.shahondin1624.lib.components.UiConstants.SMALL_PADDING
|
||||
import org.shahondin1624.lib.functions.DiceRoll
|
||||
import org.shahondin1624.model.attributes.Attribute
|
||||
@@ -33,7 +35,7 @@ fun Attribute(
|
||||
) {
|
||||
var isInDarkMode by LocalThemeIsDark.current
|
||||
val textColor = if (isInDarkMode) Color.Black else Color.White
|
||||
Card {
|
||||
Card(modifier = Modifier.testTag(TestTags.attributeCard(attribute.type.name))) {
|
||||
Row(
|
||||
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Start
|
||||
@@ -64,7 +66,9 @@ fun Attribute(
|
||||
val result = attribute.test()
|
||||
onRoll(result)
|
||||
},
|
||||
modifier = Modifier.padding(end = SMALL_PADDING)
|
||||
modifier = Modifier
|
||||
.padding(end = SMALL_PADDING)
|
||||
.testTag(TestTags.rollButton(attribute.type.name))
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(Res.drawable.dice),
|
||||
|
||||
@@ -20,9 +20,11 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.shahondin1624.lib.components.TestTags
|
||||
import org.shahondin1624.lib.components.UiConstants.SMALL_PADDING
|
||||
import org.shahondin1624.lib.functions.DiceRoll
|
||||
import org.shahondin1624.model.attributes.Attributes
|
||||
@@ -41,7 +43,7 @@ fun Talent(
|
||||
) {
|
||||
var isInDarkMode by LocalThemeIsDark.current
|
||||
val textColor = if (isInDarkMode) Color.Black else Color.White
|
||||
Card {
|
||||
Card(modifier = Modifier.testTag(TestTags.talentCard(talent.name))) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Start
|
||||
@@ -84,7 +86,9 @@ fun Talent(
|
||||
val result = talent.test(modifiers = emptyList(), attributes = attributes)
|
||||
onRoll(result)
|
||||
},
|
||||
modifier = Modifier.padding(end = SMALL_PADDING)
|
||||
modifier = Modifier
|
||||
.padding(end = SMALL_PADDING)
|
||||
.testTag(TestTags.rollButton(talent.name))
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(Res.drawable.dice),
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.shahondin1624
|
||||
|
||||
import org.shahondin1624.lib.components.TestTags
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class TestTagsTest {
|
||||
|
||||
@Test
|
||||
fun attributeCardTagFormat() {
|
||||
assertEquals("attribute_card_body", TestTags.attributeCard("Body"))
|
||||
assertEquals("attribute_card_agility", TestTags.attributeCard("Agility"))
|
||||
assertEquals("attribute_card_charisma", TestTags.attributeCard("Charisma"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun talentCardTagFormat() {
|
||||
assertEquals("talent_card_firearms", TestTags.talentCard("Firearms"))
|
||||
assertEquals("talent_card_close_combat", TestTags.talentCard("Close Combat"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rollButtonTagFormat() {
|
||||
assertEquals("roll_button_body", TestTags.rollButton("Body"))
|
||||
assertEquals("roll_button_close_combat", TestTags.rollButton("Close Combat"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun navTagsAreDefined() {
|
||||
assertEquals("nav_character_sheet", TestTags.NAV_CHARACTER_SHEET)
|
||||
assertEquals("nav_settings", TestTags.NAV_SETTINGS)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun panelTagsAreDefined() {
|
||||
assertTrue(TestTags.PANEL_CHARACTER_HEADER.isNotBlank())
|
||||
assertTrue(TestTags.PANEL_RESOURCES.isNotBlank())
|
||||
assertTrue(TestTags.PANEL_DERIVED_ATTRIBUTES.isNotBlank())
|
||||
assertTrue(TestTags.PANEL_DAMAGE_MONITOR.isNotBlank())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun allTagsAreUnique() {
|
||||
val staticTags = listOf(
|
||||
TestTags.PANEL_CHARACTER_HEADER,
|
||||
TestTags.PANEL_RESOURCES,
|
||||
TestTags.PANEL_DERIVED_ATTRIBUTES,
|
||||
TestTags.PANEL_DAMAGE_MONITOR,
|
||||
TestTags.NAV_CHARACTER_SHEET,
|
||||
TestTags.NAV_SETTINGS,
|
||||
TestTags.TOP_APP_BAR,
|
||||
TestTags.THEME_TOGGLE,
|
||||
TestTags.MENU_BUTTON
|
||||
)
|
||||
assertEquals(staticTags.size, staticTags.toSet().size, "All static tags should be unique")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user