Files
honeyDueKMP/iosApp/iosApp/Helpers/AccessibilityIdentifiers.swift
T
Trey t f5f02145a2 test: add accessibility identifiers along the onboarding-to-residence-detail path
Scaffolding for the gitea#2 regression XCUITest. No user-visible
change — pure metadata for UI automation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 09:33:47 -05:00

328 lines
16 KiB
Swift

import Foundation
/// Centralized accessibility identifiers for UI testing
/// These identifiers are used by XCUITests to locate and interact with UI elements
struct AccessibilityIdentifiers {
// MARK: - Authentication
struct Authentication {
static let usernameField = "Login.UsernameField"
static let passwordField = "Login.PasswordField"
static let loginButton = "Login.LoginButton"
static let signUpButton = "Login.SignUpButton"
static let forgotPasswordButton = "Login.ForgotPasswordButton"
static let passwordVisibilityToggle = "Login.PasswordVisibilityToggle"
static let appleSignInButton = "Login.AppleSignInButton"
static let googleSignInButton = "Login.GoogleSignInButton"
// Registration
static let registerUsernameField = "Register.UsernameField"
static let registerEmailField = "Register.EmailField"
static let registerPasswordField = "Register.PasswordField"
static let registerConfirmPasswordField = "Register.ConfirmPasswordField"
static let registerButton = "Register.RegisterButton"
static let registerCancelButton = "Register.CancelButton"
static let registerErrorMessage = "Register.ErrorMessage"
// Verification
static let verificationCodeField = "Verification.CodeField"
static let verifyButton = "Verification.VerifyButton"
static let resendCodeButton = "Verification.ResendButton"
static let verificationLogoutButton = "Verification.LogoutButton"
}
// MARK: - Navigation
struct Navigation {
static let residencesTab = "TabBar.Residences"
static let tasksTab = "TabBar.Tasks"
static let contractorsTab = "TabBar.Contractors"
static let documentsTab = "TabBar.Documents"
static let profileTab = "TabBar.Profile"
static let backButton = "Navigation.BackButton"
static let settingsButton = "Navigation.SettingsButton"
}
// MARK: - Residence
struct Residence {
// List
static let addButton = "Residence.AddButton"
static let residencesList = "Residence.List"
static let residenceCard = "Residence.Card"
/// Prefix for individual residence cells in the list. Suffix with the
/// residence id to address a specific cell (e.g. "Residence.Cell.42").
static let cellPrefix = "Residence.Cell"
static let emptyStateView = "Residence.EmptyState"
static let emptyStateButton = "Residence.EmptyState.AddButton"
// Form
static let nameField = "ResidenceForm.NameField"
static let propertyTypePicker = "ResidenceForm.PropertyTypePicker"
static let streetAddressField = "ResidenceForm.StreetAddressField"
static let apartmentUnitField = "ResidenceForm.ApartmentUnitField"
static let cityField = "ResidenceForm.CityField"
static let stateProvinceField = "ResidenceForm.StateProvinceField"
static let postalCodeField = "ResidenceForm.PostalCodeField"
static let countryField = "ResidenceForm.CountryField"
static let bedroomsField = "ResidenceForm.BedroomsField"
static let bathroomsField = "ResidenceForm.BathroomsField"
static let squareFootageField = "ResidenceForm.SquareFootageField"
static let lotSizeField = "ResidenceForm.LotSizeField"
static let yearBuiltField = "ResidenceForm.YearBuiltField"
static let descriptionField = "ResidenceForm.DescriptionField"
static let isPrimaryToggle = "ResidenceForm.IsPrimaryToggle"
static let saveButton = "ResidenceForm.SaveButton"
static let formCancelButton = "ResidenceForm.CancelButton"
// Detail
static let detailView = "ResidenceDetail.View"
static let editButton = "ResidenceDetail.EditButton"
static let deleteButton = "ResidenceDetail.DeleteButton"
static let shareButton = "ResidenceDetail.ShareButton"
static let manageUsersButton = "ResidenceDetail.ManageUsersButton"
static let tasksSection = "ResidenceDetail.TasksSection"
static let addTaskButton = "ResidenceDetail.AddTaskButton"
}
// MARK: - Task
struct Task {
// List/Kanban
static let addButton = "Task.AddButton"
static let refreshButton = "Task.RefreshButton"
static let tasksList = "Task.List"
static let taskCard = "Task.Card"
/// Prefix for individual task rows. Suffix with the task id to
/// address a specific row (e.g. "Task.Row.42"). Use `BEGINSWITH`
/// in tests to detect "any task row exists".
static let rowPrefix = "Task.Row"
static let emptyStateView = "Task.EmptyState"
/// Label rendered when a residence-detail tasks section has no tasks
/// in any kanban column. Asserted ABSENT after onboarding bulk-create
/// in the gitea#2 regression test.
static let noTasksLabel = "Task.NoTasksLabel"
static let kanbanView = "Task.KanbanView"
static let overdueColumn = "Task.Column.Overdue"
static let upcomingColumn = "Task.Column.Upcoming"
static let inProgressColumn = "Task.Column.InProgress"
static let completedColumn = "Task.Column.Completed"
// Form
static let titleField = "TaskForm.TitleField"
static let descriptionField = "TaskForm.DescriptionField"
static let categoryPicker = "TaskForm.CategoryPicker"
static let frequencyPicker = "TaskForm.FrequencyPicker"
static let priorityPicker = "TaskForm.PriorityPicker"
static let statusPicker = "TaskForm.StatusPicker"
static let dueDatePicker = "TaskForm.DueDatePicker"
static let intervalDaysField = "TaskForm.IntervalDaysField"
static let estimatedCostField = "TaskForm.EstimatedCostField"
static let residencePicker = "TaskForm.ResidencePicker"
static let saveButton = "TaskForm.SaveButton"
static let formCancelButton = "TaskForm.CancelButton"
// Detail
static let detailView = "TaskDetail.View"
static let editButton = "TaskDetail.EditButton"
static let deleteButton = "TaskDetail.DeleteButton"
static let markInProgressButton = "TaskDetail.MarkInProgressButton"
static let completeButton = "TaskDetail.CompleteButton"
static let detailCancelButton = "TaskDetail.CancelButton"
// Completion
static let completionDatePicker = "TaskCompletion.CompletionDatePicker"
static let actualCostField = "TaskCompletion.ActualCostField"
static let ratingView = "TaskCompletion.RatingView"
static let notesField = "TaskCompletion.NotesField"
static let photosPicker = "TaskCompletion.PhotosPicker"
static let submitButton = "TaskCompletion.SubmitButton"
}
// MARK: - Contractor
struct Contractor {
static let addButton = "Contractor.AddButton"
static let contractorsList = "Contractor.List"
static let contractorCard = "Contractor.Card"
static let emptyStateView = "Contractor.EmptyState"
// Form
static let nameField = "ContractorForm.NameField"
static let companyField = "ContractorForm.CompanyField"
static let emailField = "ContractorForm.EmailField"
static let phoneField = "ContractorForm.PhoneField"
static let specialtyPicker = "ContractorForm.SpecialtyPicker"
static let ratingView = "ContractorForm.RatingView"
static let notesField = "ContractorForm.NotesField"
static let saveButton = "ContractorForm.SaveButton"
static let formCancelButton = "ContractorForm.CancelButton"
// Detail
static let detailView = "ContractorDetail.View"
static let menuButton = "ContractorDetail.MenuButton"
static let editButton = "ContractorDetail.EditButton"
static let deleteButton = "ContractorDetail.DeleteButton"
static let callButton = "ContractorDetail.CallButton"
static let emailButton = "ContractorDetail.EmailButton"
}
// MARK: - Document
struct Document {
static let addButton = "Document.AddButton"
static let documentsList = "Document.List"
static let documentCard = "Document.Card"
static let emptyStateView = "Document.EmptyState"
// Form
static let titleField = "DocumentForm.TitleField"
static let typePicker = "DocumentForm.TypePicker"
static let categoryPicker = "DocumentForm.CategoryPicker"
static let residencePicker = "DocumentForm.ResidencePicker"
static let filePicker = "DocumentForm.FilePicker"
static let notesField = "DocumentForm.NotesField"
static let expirationDatePicker = "DocumentForm.ExpirationDatePicker"
static let itemNameField = "DocumentForm.ItemNameField"
static let modelNumberField = "DocumentForm.ModelNumberField"
static let serialNumberField = "DocumentForm.SerialNumberField"
static let providerField = "DocumentForm.ProviderField"
static let providerContactField = "DocumentForm.ProviderContactField"
static let tagsField = "DocumentForm.TagsField"
static let locationField = "DocumentForm.LocationField"
static let saveButton = "DocumentForm.SaveButton"
static let formCancelButton = "DocumentForm.CancelButton"
// Detail
static let detailView = "DocumentDetail.View"
static let menuButton = "DocumentDetail.MenuButton"
static let editButton = "DocumentDetail.EditButton"
static let deleteButton = "DocumentDetail.DeleteButton"
static let shareButton = "DocumentDetail.ShareButton"
static let downloadButton = "DocumentDetail.DownloadButton"
}
// MARK: - Onboarding
struct Onboarding {
// Welcome Screen
static let welcomeTitle = "Onboarding.WelcomeTitle"
static let startFreshButton = "Onboarding.StartFreshButton"
static let joinExistingButton = "Onboarding.JoinExistingButton"
static let loginButton = "Onboarding.LoginButton"
// Value Props Screen
static let valuePropsTitle = "Onboarding.ValuePropsTitle"
static let valuePropsNextButton = "Onboarding.ValuePropsNextButton"
// Name Residence Screen
static let nameResidenceTitle = "Onboarding.NameResidenceTitle"
static let residenceNameField = "Onboarding.ResidenceNameField"
static let nameResidenceContinueButton = "Onboarding.NameResidenceContinueButton"
// Create Account Screen
static let createAccountTitle = "Onboarding.CreateAccountTitle"
static let appleSignInButton = "Onboarding.AppleSignInButton"
static let emailSignUpExpandButton = "Onboarding.EmailSignUpExpandButton"
static let usernameField = "Onboarding.UsernameField"
static let emailField = "Onboarding.EmailField"
static let passwordField = "Onboarding.PasswordField"
static let confirmPasswordField = "Onboarding.ConfirmPasswordField"
static let createAccountButton = "Onboarding.CreateAccountButton"
static let loginLinkButton = "Onboarding.LoginLinkButton"
// Verify Email Screen
static let verifyEmailTitle = "Onboarding.VerifyEmailTitle"
static let verificationCodeField = "Onboarding.VerificationCodeField"
static let verifyButton = "Onboarding.VerifyButton"
// Join Residence Screen
static let joinResidenceTitle = "Onboarding.JoinResidenceTitle"
static let shareCodeField = "Onboarding.ShareCodeField"
static let joinResidenceButton = "Onboarding.JoinResidenceButton"
// First Task Screen
static let firstTaskTitle = "Onboarding.FirstTaskTitle"
static let taskSelectionCounter = "Onboarding.TaskSelectionCounter"
static let addPopularTasksButton = "Onboarding.AddPopularTasksButton"
static let addTasksContinueButton = "Onboarding.AddTasksContinueButton"
/// Submit/continue button at the bottom of the First-Task screen.
/// Triggers `POST /api/tasks/bulk/` for the selected templates.
static let submitTasksButton = "Onboarding.SubmitTasksButton"
/// Tab bar control above the task list. The "Browse All" segment is
/// addressed via `app.buttons["Browse All"]` from the segmented
/// picker once this identifier is set.
static let firstTaskTabBar = "Onboarding.FirstTaskTabBar"
/// Tab segment that shows the full template catalog.
/// Tap from a test by addressing the Picker's segment label
/// "Browse All" within the element identified above.
static let browseAllTab = "Onboarding.BrowseAllTab"
static let taskCategorySection = "Onboarding.TaskCategorySection"
static let taskTemplateRow = "Onboarding.TaskTemplateRow"
/// Prefix for individual template rows on the First-Task screen
/// (Browse All tab). Suffix with the backend template id
/// e.g. `"Onboarding.TemplateRow.123"`. Tests use `BEGINSWITH` to
/// pick the first N rows deterministically without knowing ids.
static let templateRowPrefix = "Onboarding.TemplateRow"
// Subscription Screen
static let subscriptionTitle = "Onboarding.SubscriptionTitle"
static let yearlyPlanCard = "Onboarding.YearlyPlanCard"
static let monthlyPlanCard = "Onboarding.MonthlyPlanCard"
static let startTrialButton = "Onboarding.StartTrialButton"
static let continueWithFreeButton = "Onboarding.ContinueWithFreeButton"
// Navigation
static let backButton = "Onboarding.BackButton"
static let skipButton = "Onboarding.SkipButton"
static let progressIndicator = "Onboarding.ProgressIndicator"
}
// MARK: - Password Reset
struct PasswordReset {
static let emailField = "PasswordReset.EmailField"
static let sendCodeButton = "PasswordReset.SendCodeButton"
static let backToLoginButton = "PasswordReset.BackToLoginButton"
static let codeField = "PasswordReset.CodeField"
static let verifyCodeButton = "PasswordReset.VerifyCodeButton"
static let resendCodeButton = "PasswordReset.ResendCodeButton"
static let newPasswordField = "PasswordReset.NewPasswordField"
static let confirmPasswordField = "PasswordReset.ConfirmPasswordField"
static let resetButton = "PasswordReset.ResetButton"
static let returnToLoginButton = "PasswordReset.ReturnToLoginButton"
}
// MARK: - Profile
struct Profile {
static let logoutButton = "Profile.LogoutButton"
static let editProfileButton = "Profile.EditProfileButton"
static let settingsButton = "Profile.SettingsButton"
static let notificationsToggle = "Profile.NotificationsToggle"
static let darkModeToggle = "Profile.DarkModeToggle"
static let aboutButton = "Profile.AboutButton"
static let helpButton = "Profile.HelpButton"
}
// MARK: - Alerts & Modals
struct Alert {
static let confirmButton = "Alert.ConfirmButton"
static let cancelButton = "Alert.CancelButton"
static let deleteButton = "Alert.DeleteButton"
static let okButton = "Alert.OKButton"
}
// MARK: - Common
struct Common {
static let loadingIndicator = "Common.LoadingIndicator"
static let errorView = "Common.ErrorView"
static let retryButton = "Common.RetryButton"
static let searchField = "Common.SearchField"
static let filterButton = "Common.FilterButton"
static let sortButton = "Common.SortButton"
static let refreshControl = "Common.RefreshControl"
}
}
// MARK: - Helper Extension
extension String {
/// Convenience method to generate dynamic identifiers
/// Example: "Residence.Card.\(residenceId)"
func withId(_ id: Any) -> String {
return "\(self).\(id)"
}
}