Fix: expect/actual enableTestTagsAsResourceId() for iOS compile

testTagsAsResourceId is Android-only; its use in commonMain broke
compileKotlinIosSimulatorArm64. Wrap behind expect fun — Android impl
sets the semantic, other platforms return Modifier unchanged. Blocks
P3 iOS parity gallery otherwise.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey T
2026-04-18 19:20:48 -05:00
parent f56d854acc
commit c57743dca0
17 changed files with 66 additions and 35 deletions

View File

@@ -0,0 +1,9 @@
package com.tt.honeyDue.ui.support
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class)
actual fun Modifier.enableTestTagsAsResourceId(): Modifier =
this.semantics { testTagsAsResourceId = true }

View File

@@ -16,12 +16,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.ApiResultHandler import com.tt.honeyDue.ui.components.ApiResultHandler
import com.tt.honeyDue.ui.components.HandleErrors import com.tt.honeyDue.ui.components.HandleErrors
import com.tt.honeyDue.viewmodel.DocumentViewModel import com.tt.honeyDue.viewmodel.DocumentViewModel
@@ -80,7 +79,7 @@ fun DocumentDetailScreen(
} }
Scaffold( Scaffold(
modifier = Modifier.semantics { testTagsAsResourceId = true }, modifier = Modifier.enableTestTagsAsResourceId(),
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { Text(stringResource(Res.string.documents_details), fontWeight = FontWeight.Bold) }, title = { Text(stringResource(Res.string.documents_details), fontWeight = FontWeight.Bold) },

View File

@@ -16,14 +16,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.AuthenticatedImage import com.tt.honeyDue.ui.components.AuthenticatedImage
import com.tt.honeyDue.viewmodel.DocumentViewModel import com.tt.honeyDue.viewmodel.DocumentViewModel
import com.tt.honeyDue.viewmodel.ResidenceViewModel import com.tt.honeyDue.viewmodel.ResidenceViewModel
@@ -188,7 +187,7 @@ fun DocumentFormScreen(
} }
Scaffold( Scaffold(
modifier = Modifier.semantics { testTagsAsResourceId = true }, modifier = Modifier.enableTestTagsAsResourceId(),
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { title = {

View File

@@ -10,13 +10,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.documents.DocumentsTabContent import com.tt.honeyDue.ui.components.documents.DocumentsTabContent
import com.tt.honeyDue.ui.subscription.UpgradeFeatureScreen import com.tt.honeyDue.ui.subscription.UpgradeFeatureScreen
import com.tt.honeyDue.utils.SubscriptionHelper import com.tt.honeyDue.utils.SubscriptionHelper
@@ -83,7 +82,7 @@ fun DocumentsScreen(
} }
Scaffold( Scaffold(
modifier = Modifier.semantics { testTagsAsResourceId = true }, modifier = Modifier.enableTestTagsAsResourceId(),
topBar = { topBar = {
Column { Column {
TopAppBar( TopAppBar(

View File

@@ -20,8 +20,6 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
@@ -31,6 +29,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.HandleErrors import com.tt.honeyDue.ui.components.HandleErrors
import com.tt.honeyDue.ui.components.auth.AuthHeader import com.tt.honeyDue.ui.components.auth.AuthHeader
import com.tt.honeyDue.ui.components.auth.GoogleSignInButton import com.tt.honeyDue.ui.components.auth.GoogleSignInButton
@@ -111,12 +110,11 @@ fun LoginScreen(
val isLoading = loginState is ApiResult.Loading || googleSignInState is ApiResult.Loading val isLoading = loginState is ApiResult.Loading || googleSignInState is ApiResult.Loading
WarmGradientBackground { WarmGradientBackground {
@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class)
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.imePadding() .imePadding()
.semantics { testTagsAsResourceId = true }, .enableTestTagsAsResourceId(),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
OrganicCard( OrganicCard(

View File

@@ -12,8 +12,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@@ -25,6 +23,7 @@ import com.tt.honeyDue.models.ResidenceShareCode
import com.tt.honeyDue.network.ApiResult import com.tt.honeyDue.network.ApiResult
import com.tt.honeyDue.network.APILayer import com.tt.honeyDue.network.APILayer
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.common.StandardErrorState import com.tt.honeyDue.ui.components.common.StandardErrorState
import com.tt.honeyDue.ui.theme.* import com.tt.honeyDue.ui.theme.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -76,7 +75,7 @@ fun ManageUsersScreen(
WarmGradientBackground { WarmGradientBackground {
Scaffold( Scaffold(
modifier = Modifier.semantics { testTagsAsResourceId = true }, modifier = Modifier.enableTestTagsAsResourceId(),
containerColor = androidx.compose.ui.graphics.Color.Transparent, containerColor = androidx.compose.ui.graphics.Color.Transparent,
topBar = { topBar = {
TopAppBar( TopAppBar(

View File

@@ -18,8 +18,6 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
@@ -28,6 +26,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.HandleErrors import com.tt.honeyDue.ui.components.HandleErrors
import com.tt.honeyDue.ui.components.auth.AuthHeader import com.tt.honeyDue.ui.components.auth.AuthHeader
import com.tt.honeyDue.ui.components.auth.RequirementItem import com.tt.honeyDue.ui.components.auth.RequirementItem
@@ -88,9 +87,8 @@ fun RegisterScreen(
} }
WarmGradientBackground { WarmGradientBackground {
@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class)
Scaffold( Scaffold(
modifier = Modifier.semantics { testTagsAsResourceId = true }, modifier = Modifier.enableTestTagsAsResourceId(),
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { Text(stringResource(Res.string.auth_register_title), fontWeight = FontWeight.SemiBold) }, title = { Text(stringResource(Res.string.auth_register_title), fontWeight = FontWeight.SemiBold) },

View File

@@ -13,13 +13,12 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.AddNewTaskDialog import com.tt.honeyDue.ui.components.AddNewTaskDialog
import com.tt.honeyDue.ui.components.ApiResultHandler import com.tt.honeyDue.ui.components.ApiResultHandler
import com.tt.honeyDue.ui.components.CompleteTaskDialog import com.tt.honeyDue.ui.components.CompleteTaskDialog
@@ -423,7 +422,7 @@ fun ResidenceDetailScreen(
Scaffold( Scaffold(
modifier = Modifier modifier = Modifier
.semantics { testTagsAsResourceId = true } .enableTestTagsAsResourceId()
.testTag(AccessibilityIds.Residence.detailView), .testTag(AccessibilityIds.Residence.detailView),
snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
topBar = { topBar = {

View File

@@ -12,13 +12,12 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.viewmodel.ResidenceViewModel import com.tt.honeyDue.viewmodel.ResidenceViewModel
import com.tt.honeyDue.repository.LookupsRepository import com.tt.honeyDue.repository.LookupsRepository
import com.tt.honeyDue.data.LocalDataManager import com.tt.honeyDue.data.LocalDataManager
@@ -161,7 +160,7 @@ fun ResidenceFormScreen(
} }
Scaffold( Scaffold(
modifier = Modifier.semantics { testTagsAsResourceId = true }, modifier = Modifier.enableTestTagsAsResourceId(),
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { Text(if (isEditMode) stringResource(Res.string.properties_edit_title) else stringResource(Res.string.properties_add_title)) }, title = { Text(if (isEditMode) stringResource(Res.string.properties_edit_title) else stringResource(Res.string.properties_add_title)) },

View File

@@ -22,8 +22,6 @@ import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -31,6 +29,7 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.ApiResultHandler import com.tt.honeyDue.ui.components.ApiResultHandler
import com.tt.honeyDue.ui.components.common.StatItem import com.tt.honeyDue.ui.components.common.StatItem
import com.tt.honeyDue.ui.components.residence.TaskStatChip import com.tt.honeyDue.ui.components.residence.TaskStatChip
@@ -118,7 +117,7 @@ fun ResidencesScreen(
} }
Scaffold( Scaffold(
modifier = Modifier.semantics { testTagsAsResourceId = true }, modifier = Modifier.enableTestTagsAsResourceId(),
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { title = {

View File

@@ -11,8 +11,6 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@@ -20,6 +18,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.HandleErrors import com.tt.honeyDue.ui.components.HandleErrors
import com.tt.honeyDue.ui.components.auth.AuthHeader import com.tt.honeyDue.ui.components.auth.AuthHeader
import com.tt.honeyDue.ui.components.common.ErrorCard import com.tt.honeyDue.ui.components.common.ErrorCard
@@ -69,9 +68,8 @@ fun VerifyEmailScreen(
} }
} }
@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class)
Scaffold( Scaffold(
modifier = Modifier.semantics { testTagsAsResourceId = true }, modifier = Modifier.enableTestTagsAsResourceId(),
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { Text(stringResource(Res.string.auth_verify_title), fontWeight = FontWeight.SemiBold) }, title = { Text(stringResource(Res.string.auth_verify_title), fontWeight = FontWeight.SemiBold) },

View File

@@ -39,7 +39,6 @@ import androidx.compose.ui.semantics.LiveRegionMode
import androidx.compose.ui.semantics.error import androidx.compose.ui.semantics.error
import androidx.compose.ui.semantics.liveRegion import androidx.compose.ui.semantics.liveRegion
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
@@ -48,6 +47,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tt.honeyDue.network.ApiResult import com.tt.honeyDue.network.ApiResult
import com.tt.honeyDue.testing.AccessibilityIds import com.tt.honeyDue.testing.AccessibilityIds
import com.tt.honeyDue.ui.support.enableTestTagsAsResourceId
import com.tt.honeyDue.ui.components.common.StandardCard import com.tt.honeyDue.ui.components.common.StandardCard
import com.tt.honeyDue.ui.components.forms.FormTextField import com.tt.honeyDue.ui.components.forms.FormTextField
import com.tt.honeyDue.ui.theme.AppRadius import com.tt.honeyDue.ui.theme.AppRadius
@@ -86,7 +86,7 @@ fun JoinResidenceScreen(
} }
Scaffold( Scaffold(
modifier = Modifier.semantics { testTagsAsResourceId = true }, modifier = Modifier.enableTestTagsAsResourceId(),
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { title = {

View File

@@ -0,0 +1,15 @@
package com.tt.honeyDue.ui.support
import androidx.compose.ui.Modifier
/**
* Opt-in to exposing Compose [Modifier.testTag] values as Android View
* resource IDs so Espresso/UI-Automator tests can select them. No-op on
* non-Android platforms.
*
* Apply once on a screen's root Scaffold / Box:
* ```
* Scaffold(modifier = Modifier.enableTestTagsAsResourceId(), ...)
* ```
*/
expect fun Modifier.enableTestTagsAsResourceId(): Modifier

View File

@@ -0,0 +1,5 @@
package com.tt.honeyDue.ui.support
import androidx.compose.ui.Modifier
actual fun Modifier.enableTestTagsAsResourceId(): Modifier = this

View File

@@ -0,0 +1,5 @@
package com.tt.honeyDue.ui.support
import androidx.compose.ui.Modifier
actual fun Modifier.enableTestTagsAsResourceId(): Modifier = this

View File

@@ -0,0 +1,5 @@
package com.tt.honeyDue.ui.support
import androidx.compose.ui.Modifier
actual fun Modifier.enableTestTagsAsResourceId(): Modifier = this

View File

@@ -0,0 +1,5 @@
package com.tt.honeyDue.ui.support
import androidx.compose.ui.Modifier
actual fun Modifier.enableTestTagsAsResourceId(): Modifier = this