Files
honeyDueKMP/iosApp/MyCribUITests/AccessibilityIdentifiers.swift
Trey t 56b1f57ec7 Add comprehensive UI test suite with XCUITest
Added complete UI test suite covering authentication, residences, tasks,
and contractors. Tests follow best practices with helper methods, proper
waits, and accessibility identifier usage.

New test files:
- UITestHelpers.swift: Shared helper methods for login, navigation, waits
- AuthenticationTests.swift: Login, registration, logout flow tests
- ComprehensiveResidenceTests.swift: Full residence CRUD and validation tests
- ComprehensiveTaskTests.swift: Task creation, editing, completion tests
- ComprehensiveContractorTests.swift: Contractor management and edge case tests
- ResidenceTests.swift: Additional residence-specific scenarios
- TaskTests.swift: Additional task scenarios
- SimpleLoginTest.swift: Basic smoke test for CI/CD
- MyCribUITests.swift: Base test class setup
- AccessibilityIdentifiers.swift: Test target copy of identifiers

Test coverage:
- Authentication: Login, registration, logout, error handling
- Residences: Create, edit, delete, validation, multi-field scenarios
- Tasks: Create, complete, edit, cancel, status changes
- Contractors: Create with minimal/full data, phone formats, specialties

All tests use accessibility identifiers for reliable element location and
include proper waits for asynchronous operations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 23:06:57 -06:00

213 lines
9.3 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"
// 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"
// Verification
static let verificationCodeField = "Verification.CodeField"
static let verifyButton = "Verification.VerifyButton"
static let resendCodeButton = "Verification.ResendButton"
}
// 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"
}
// MARK: - Residence
struct Residence {
// List
static let addButton = "Residence.AddButton"
static let residencesList = "Residence.List"
static let residenceCard = "Residence.Card"
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 tasksList = "Task.List"
static let taskCard = "Task.Card"
static let emptyStateView = "Task.EmptyState"
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 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 saveButton = "DocumentForm.SaveButton"
static let formCancelButton = "DocumentForm.CancelButton"
// Detail
static let detailView = "DocumentDetail.View"
static let editButton = "DocumentDetail.EditButton"
static let deleteButton = "DocumentDetail.DeleteButton"
static let shareButton = "DocumentDetail.ShareButton"
static let downloadButton = "DocumentDetail.DownloadButton"
}
// 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)"
}
}