UI Test Suite4: Comprehensive residence tests (iOS parity)
Ports Suite4_ComprehensiveResidenceTests.swift. testTags on residence screens via AccessibilityIds.Residence.*. CRUD + join + manage users + multi-residence switch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,9 @@ import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
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.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
@@ -21,6 +24,7 @@ import com.tt.honeyDue.models.ResidenceUser
|
||||
import com.tt.honeyDue.models.ResidenceShareCode
|
||||
import com.tt.honeyDue.network.ApiResult
|
||||
import com.tt.honeyDue.network.APILayer
|
||||
import com.tt.honeyDue.testing.AccessibilityIds
|
||||
import com.tt.honeyDue.ui.theme.*
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
@@ -64,6 +68,7 @@ fun ManageUsersScreen(
|
||||
|
||||
WarmGradientBackground {
|
||||
Scaffold(
|
||||
modifier = Modifier.semantics { testTagsAsResourceId = true },
|
||||
containerColor = androidx.compose.ui.graphics.Color.Transparent,
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
@@ -128,7 +133,8 @@ fun ManageUsersScreen(
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues),
|
||||
.padding(paddingValues)
|
||||
.testTag(AccessibilityIds.Residence.manageUsersList),
|
||||
contentPadding = PaddingValues(OrganicSpacing.lg),
|
||||
verticalArrangement = Arrangement.spacedBy(OrganicSpacing.lg)
|
||||
) {
|
||||
@@ -462,7 +468,10 @@ private fun UserCard(
|
||||
}
|
||||
|
||||
if (canRemove) {
|
||||
IconButton(onClick = onRemove) {
|
||||
IconButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.manageUsersRemoveButton),
|
||||
onClick = onRemove
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Delete,
|
||||
contentDescription = stringResource(Res.string.manage_users_remove),
|
||||
|
||||
@@ -12,10 +12,14 @@ import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tt.honeyDue.testing.AccessibilityIds
|
||||
import com.tt.honeyDue.ui.components.AddNewTaskDialog
|
||||
import com.tt.honeyDue.ui.components.ApiResultHandler
|
||||
import com.tt.honeyDue.ui.components.CompleteTaskDialog
|
||||
@@ -302,6 +306,7 @@ fun ResidenceDetailScreen(
|
||||
text = { Text(stringResource(Res.string.properties_delete_name_confirm, residence.name)) },
|
||||
confirmButton = {
|
||||
Button(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.confirmDeleteButton),
|
||||
onClick = {
|
||||
showDeleteConfirmation = false
|
||||
residenceViewModel.deleteResidence(residenceId)
|
||||
@@ -415,6 +420,9 @@ fun ResidenceDetailScreen(
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier
|
||||
.semantics { testTagsAsResourceId = true }
|
||||
.testTag(AccessibilityIds.Residence.detailView),
|
||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
@@ -449,6 +457,7 @@ fun ResidenceDetailScreen(
|
||||
// Share button - only show for primary owners
|
||||
if (residence.ownerId == currentUser?.id) {
|
||||
IconButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.shareButton),
|
||||
onClick = {
|
||||
val shareCheck = SubscriptionHelper.canShareResidence()
|
||||
if (shareCheck.allowed) {
|
||||
@@ -473,39 +482,48 @@ fun ResidenceDetailScreen(
|
||||
|
||||
// Manage Users button - only show for primary owners
|
||||
if (residence.ownerId == currentUser?.id) {
|
||||
IconButton(onClick = {
|
||||
val shareCheck = SubscriptionHelper.canShareResidence()
|
||||
if (shareCheck.allowed) {
|
||||
if (onNavigateToManageUsers != null) {
|
||||
onNavigateToManageUsers(
|
||||
residence.id,
|
||||
residence.name,
|
||||
residence.ownerId == currentUser?.id,
|
||||
residence.ownerId
|
||||
)
|
||||
IconButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.manageUsersButton),
|
||||
onClick = {
|
||||
val shareCheck = SubscriptionHelper.canShareResidence()
|
||||
if (shareCheck.allowed) {
|
||||
if (onNavigateToManageUsers != null) {
|
||||
onNavigateToManageUsers(
|
||||
residence.id,
|
||||
residence.name,
|
||||
residence.ownerId == currentUser?.id,
|
||||
residence.ownerId
|
||||
)
|
||||
} else {
|
||||
showManageUsersDialog = true
|
||||
}
|
||||
} else {
|
||||
showManageUsersDialog = true
|
||||
upgradeTriggerKey = shareCheck.triggerKey
|
||||
showUpgradePrompt = true
|
||||
}
|
||||
} else {
|
||||
upgradeTriggerKey = shareCheck.triggerKey
|
||||
showUpgradePrompt = true
|
||||
}
|
||||
}) {
|
||||
) {
|
||||
Icon(Icons.Default.People, contentDescription = stringResource(Res.string.properties_manage_users))
|
||||
}
|
||||
}
|
||||
|
||||
IconButton(onClick = {
|
||||
onNavigateToEditResidence(residence)
|
||||
}) {
|
||||
IconButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.editButton),
|
||||
onClick = {
|
||||
onNavigateToEditResidence(residence)
|
||||
}
|
||||
) {
|
||||
Icon(Icons.Default.Edit, contentDescription = stringResource(Res.string.properties_edit_residence))
|
||||
}
|
||||
|
||||
// Delete button - only show for primary owners
|
||||
if (residence.ownerId == currentUser?.id) {
|
||||
IconButton(onClick = {
|
||||
showDeleteConfirmation = true
|
||||
}) {
|
||||
IconButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.deleteButton),
|
||||
onClick = {
|
||||
showDeleteConfirmation = true
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Delete,
|
||||
contentDescription = stringResource(Res.string.properties_delete_residence),
|
||||
@@ -524,6 +542,7 @@ fun ResidenceDetailScreen(
|
||||
// Don't show FAB if tasks are blocked (limit=0)
|
||||
if (!isTasksBlocked.allowed) {
|
||||
FloatingActionButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.addTaskButton),
|
||||
onClick = {
|
||||
val (allowed, triggerKey) = canAddTask()
|
||||
if (allowed) {
|
||||
@@ -819,7 +838,8 @@ fun ResidenceDetailScreen(
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = OrganicSpacing.compact),
|
||||
.padding(vertical = OrganicSpacing.compact)
|
||||
.testTag(AccessibilityIds.Residence.tasksSection),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(OrganicSpacing.compact)
|
||||
) {
|
||||
|
||||
@@ -11,10 +11,14 @@ import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tt.honeyDue.testing.AccessibilityIds
|
||||
import com.tt.honeyDue.viewmodel.ResidenceViewModel
|
||||
import com.tt.honeyDue.repository.LookupsRepository
|
||||
import com.tt.honeyDue.data.DataManager
|
||||
@@ -156,11 +160,15 @@ fun ResidenceFormScreen(
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.semantics { testTagsAsResourceId = true },
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text(if (isEditMode) stringResource(Res.string.properties_edit_title) else stringResource(Res.string.properties_add_title)) },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onNavigateBack) {
|
||||
IconButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.formCancelButton),
|
||||
onClick = onNavigateBack
|
||||
) {
|
||||
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(Res.string.common_back))
|
||||
}
|
||||
}
|
||||
@@ -188,7 +196,9 @@ fun ResidenceFormScreen(
|
||||
value = name,
|
||||
onValueChange = { name = it },
|
||||
label = { Text(stringResource(Res.string.properties_form_name_required)) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.nameField),
|
||||
isError = nameError.isNotEmpty(),
|
||||
supportingText = if (nameError.isNotEmpty()) {
|
||||
{ Text(nameError, color = MaterialTheme.colorScheme.error) }
|
||||
@@ -209,7 +219,8 @@ fun ResidenceFormScreen(
|
||||
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.menuAnchor(),
|
||||
.menuAnchor()
|
||||
.testTag(AccessibilityIds.Residence.propertyTypePicker),
|
||||
enabled = propertyTypes.isNotEmpty()
|
||||
)
|
||||
ExposedDropdownMenu(
|
||||
@@ -239,42 +250,54 @@ fun ResidenceFormScreen(
|
||||
value = streetAddress,
|
||||
onValueChange = { streetAddress = it },
|
||||
label = { Text(stringResource(Res.string.properties_form_street)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.streetAddressField)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
value = apartmentUnit,
|
||||
onValueChange = { apartmentUnit = it },
|
||||
label = { Text(stringResource(Res.string.properties_form_apartment)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.apartmentUnitField)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
value = city,
|
||||
onValueChange = { city = it },
|
||||
label = { Text(stringResource(Res.string.properties_form_city)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.cityField)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
value = stateProvince,
|
||||
onValueChange = { stateProvince = it },
|
||||
label = { Text(stringResource(Res.string.properties_form_state)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.stateProvinceField)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
value = postalCode,
|
||||
onValueChange = { postalCode = it },
|
||||
label = { Text(stringResource(Res.string.properties_form_postal)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.postalCodeField)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
value = country,
|
||||
onValueChange = { country = it },
|
||||
label = { Text(stringResource(Res.string.properties_form_country)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.countryField)
|
||||
)
|
||||
|
||||
// Optional fields section
|
||||
@@ -294,7 +317,9 @@ fun ResidenceFormScreen(
|
||||
onValueChange = { bedrooms = it.filter { char -> char.isDigit() } },
|
||||
label = { Text(stringResource(Res.string.properties_bedrooms)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.weight(1f)
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.testTag(AccessibilityIds.Residence.bedroomsField)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
@@ -302,7 +327,9 @@ fun ResidenceFormScreen(
|
||||
onValueChange = { bathrooms = it },
|
||||
label = { Text(stringResource(Res.string.properties_bathrooms)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
||||
modifier = Modifier.weight(1f)
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.testTag(AccessibilityIds.Residence.bathroomsField)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -311,7 +338,9 @@ fun ResidenceFormScreen(
|
||||
onValueChange = { squareFootage = it.filter { char -> char.isDigit() } },
|
||||
label = { Text(stringResource(Res.string.properties_form_sqft)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.squareFootageField)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
@@ -319,7 +348,9 @@ fun ResidenceFormScreen(
|
||||
onValueChange = { lotSize = it },
|
||||
label = { Text(stringResource(Res.string.properties_form_lot_size)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.lotSizeField)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
@@ -327,14 +358,18 @@ fun ResidenceFormScreen(
|
||||
onValueChange = { yearBuilt = it.filter { char -> char.isDigit() } },
|
||||
label = { Text(stringResource(Res.string.properties_year_built)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.yearBuiltField)
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
value = description,
|
||||
onValueChange = { description = it },
|
||||
label = { Text(stringResource(Res.string.properties_form_description)) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.Residence.descriptionField),
|
||||
minLines = 3,
|
||||
maxLines = 5
|
||||
)
|
||||
@@ -345,6 +380,7 @@ fun ResidenceFormScreen(
|
||||
) {
|
||||
Text(stringResource(Res.string.properties_form_primary))
|
||||
Switch(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.isPrimaryToggle),
|
||||
checked = isPrimary,
|
||||
onCheckedChange = { isPrimary = it }
|
||||
)
|
||||
@@ -404,6 +440,7 @@ fun ResidenceFormScreen(
|
||||
|
||||
// Submit button
|
||||
OrganicPrimaryButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.saveButton),
|
||||
text = if (isEditMode) stringResource(Res.string.properties_form_update) else stringResource(Res.string.properties_form_create),
|
||||
onClick = {
|
||||
if (validateForm()) {
|
||||
|
||||
@@ -19,12 +19,16 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.scale
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
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.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tt.honeyDue.testing.AccessibilityIds
|
||||
import com.tt.honeyDue.ui.components.ApiResultHandler
|
||||
import com.tt.honeyDue.ui.components.common.StatItem
|
||||
import com.tt.honeyDue.ui.components.residence.TaskStatChip
|
||||
@@ -108,6 +112,7 @@ fun ResidencesScreen(
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.semantics { testTagsAsResourceId = true },
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
@@ -128,29 +133,35 @@ fun ResidencesScreen(
|
||||
actions = {
|
||||
// Only show Join button if not blocked (limit>0)
|
||||
if (!isBlocked.allowed) {
|
||||
IconButton(onClick = {
|
||||
val (allowed, triggerKey) = canAddProperty()
|
||||
if (allowed) {
|
||||
onJoinResidence()
|
||||
} else {
|
||||
upgradeTriggerKey = triggerKey
|
||||
showUpgradePrompt = true
|
||||
IconButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.joinButton),
|
||||
onClick = {
|
||||
val (allowed, triggerKey) = canAddProperty()
|
||||
if (allowed) {
|
||||
onJoinResidence()
|
||||
} else {
|
||||
upgradeTriggerKey = triggerKey
|
||||
showUpgradePrompt = true
|
||||
}
|
||||
}
|
||||
}) {
|
||||
) {
|
||||
Icon(Icons.Default.GroupAdd, contentDescription = stringResource(Res.string.properties_join_title))
|
||||
}
|
||||
}
|
||||
// Add property button
|
||||
if (!isBlocked.allowed) {
|
||||
IconButton(onClick = {
|
||||
val (allowed, triggerKey) = canAddProperty()
|
||||
if (allowed) {
|
||||
onAddResidence()
|
||||
} else {
|
||||
upgradeTriggerKey = triggerKey
|
||||
showUpgradePrompt = true
|
||||
IconButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.addButton),
|
||||
onClick = {
|
||||
val (allowed, triggerKey) = canAddProperty()
|
||||
if (allowed) {
|
||||
onAddResidence()
|
||||
} else {
|
||||
upgradeTriggerKey = triggerKey
|
||||
showUpgradePrompt = true
|
||||
}
|
||||
}
|
||||
}) {
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.AddCircle,
|
||||
contentDescription = stringResource(Res.string.properties_add_button),
|
||||
@@ -172,6 +183,7 @@ fun ResidencesScreen(
|
||||
if (hasResidences && !isBlocked.allowed) {
|
||||
Box(modifier = Modifier.padding(bottom = 80.dp)) {
|
||||
FloatingActionButton(
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.addFab),
|
||||
onClick = {
|
||||
val (allowed, triggerKey) = canAddProperty()
|
||||
if (allowed) {
|
||||
@@ -208,7 +220,8 @@ fun ResidencesScreen(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues),
|
||||
.padding(paddingValues)
|
||||
.testTag(AccessibilityIds.Residence.emptyStateView),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Column(
|
||||
@@ -247,7 +260,8 @@ fun ResidencesScreen(
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(0.7f)
|
||||
.height(56.dp),
|
||||
.height(56.dp)
|
||||
.testTag(AccessibilityIds.Residence.emptyStateButton),
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
) {
|
||||
Row(
|
||||
@@ -330,7 +344,9 @@ fun ResidencesScreen(
|
||||
.padding(paddingValues)
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.testTag(AccessibilityIds.Residence.residencesList),
|
||||
contentPadding = PaddingValues(
|
||||
start = OrganicSpacing.cozy,
|
||||
end = OrganicSpacing.cozy,
|
||||
@@ -446,6 +462,7 @@ fun ResidencesScreen(
|
||||
OrganicCard(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(AccessibilityIds.withId(AccessibilityIds.Residence.residenceCard, residence.id))
|
||||
.clickable { onResidenceClick(residence.id) },
|
||||
accentColor = if (hasOverdue) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary,
|
||||
showBlob = true,
|
||||
|
||||
@@ -34,6 +34,9 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
@@ -41,6 +44,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tt.honeyDue.network.ApiResult
|
||||
import com.tt.honeyDue.testing.AccessibilityIds
|
||||
import com.tt.honeyDue.ui.components.common.StandardCard
|
||||
import com.tt.honeyDue.ui.components.forms.FormTextField
|
||||
import com.tt.honeyDue.ui.theme.AppRadius
|
||||
@@ -79,6 +83,7 @@ fun JoinResidenceScreen(
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.semantics { testTagsAsResourceId = true },
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
@@ -139,6 +144,7 @@ fun JoinResidenceScreen(
|
||||
value = code,
|
||||
onValueChange = { viewModel.updateCode(it) },
|
||||
label = "Share Code",
|
||||
modifier = Modifier.testTag(AccessibilityIds.Residence.joinShareCodeField),
|
||||
placeholder = "ABC123",
|
||||
enabled = !isLoading,
|
||||
error = error,
|
||||
@@ -182,7 +188,8 @@ fun JoinResidenceScreen(
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(56.dp),
|
||||
.height(56.dp)
|
||||
.testTag(AccessibilityIds.Residence.joinSubmitButton),
|
||||
) {
|
||||
if (isLoading) {
|
||||
CircularProgressIndicator(
|
||||
|
||||
Reference in New Issue
Block a user