import XCTest /// Comprehensive tests for task management final class TaskUITests: BaseUITest { override func setUp() { super.setUp() // Login before each test login(username: "testuser", password: "TestPass123!") let residencesTab = app.tabBars.buttons["Residences"] XCTAssertTrue(residencesTab.waitForExistence(timeout: 10)) } // MARK: - Task List Tests func testTasksTabDisplays() { // When: User navigates to tasks tab navigateToTab("Tasks") // Then: Tasks screen should be displayed let navigationBar = app.navigationBars["All Tasks"] XCTAssertTrue(navigationBar.waitForExistence(timeout: 5), "Should show tasks navigation bar") } func testTaskColumnsDisplay() { // Given: User is on tasks tab navigateToTab("Tasks") wait(seconds: 2) // Then: Task columns should be visible let upcomingLabel = app.staticTexts["Upcoming"] let inProgressLabel = app.staticTexts["In Progress"] let doneLabel = app.staticTexts["Done"] XCTAssertTrue(upcomingLabel.exists || inProgressLabel.exists || doneLabel.exists || app.staticTexts["No tasks yet"].exists, "Should show task columns or empty state") } func testEmptyTasksState() { // Given: User has no tasks (requires account with no tasks) navigateToTab("Tasks") wait(seconds: 2) // Then: Empty state should be shown let emptyState = app.staticTexts["No tasks yet"] let addButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Add Task'")).firstMatch // Should show either tasks or empty state XCTAssertTrue(emptyState.exists || app.scrollViews.firstMatch.exists, "Should show content or empty state") } // MARK: - Create Task Tests func testCreateTaskFromTasksTab() { // Given: User is on tasks tab navigateToTab("Tasks") // When: User taps add task button let addButton = app.navigationBars.buttons.matching(identifier: "plus").firstMatch if addButton.exists { addButton.tap() wait(seconds: 1) // Then: Add task form should be displayed let titleField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'title' OR label CONTAINS[c] 'Title'")).firstMatch XCTAssertTrue(titleField.exists, "Should show add task form") // When: User fills in task details let timestamp = Int(Date().timeIntervalSince1970) titleField.tap() titleField.typeText("Test Task \(timestamp)") let descriptionField = app.textViews.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'description' OR label CONTAINS[c] 'Description'")).firstMatch if descriptionField.exists { descriptionField.tap() descriptionField.typeText("Test task description") } // When: User saves the task let saveButton = app.buttons["Save"] if saveButton.exists { saveButton.tap() } // Then: Task should be created and user returned to tasks list wait(seconds: 2) XCTAssertTrue(app.navigationBars["All Tasks"].exists || app.staticTexts["Test Task \(timestamp)"].exists, "Should create task and return to list") } } func testCreateTaskFromResidenceDetails() { // Given: User is viewing a residence navigateToTab("Residences") wait(seconds: 2) let firstResidence = app.cells.firstMatch if firstResidence.exists { firstResidence.tap() wait(seconds: 2) // When: User taps add task button let addButton = app.navigationBars.buttons.matching(identifier: "plus").firstMatch if addButton.exists { addButton.tap() wait(seconds: 1) // Then: Add task form should be displayed let titleField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'title' OR label CONTAINS[c] 'Title'")).firstMatch XCTAssertTrue(titleField.exists, "Should show add task form from residence") // When: User creates the task let timestamp = Int(Date().timeIntervalSince1970) titleField.tap() titleField.typeText("Residence Task \(timestamp)") let saveButton = app.buttons["Save"] if saveButton.exists { saveButton.tap() } // Then: Task should be created wait(seconds: 2) XCTAssertTrue(app.staticTexts["Residence Task \(timestamp)"].exists || app.navigationBars.element(boundBy: 1).exists, "Should create task for residence") } } } func testCreateTaskValidation() { // Given: User is on add task form navigateToTab("Tasks") let addButton = app.navigationBars.buttons.matching(identifier: "plus").firstMatch if addButton.exists { addButton.tap() wait(seconds: 1) // When: User tries to save without required fields let saveButton = app.buttons["Save"] if saveButton.exists { saveButton.tap() } // Then: Validation errors should be shown let errorMessages = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'required'")) XCTAssertTrue(errorMessages.count > 0 || !app.navigationBars["All Tasks"].exists, "Should show validation errors") } } // MARK: - View Task Details Tests func testViewTaskDetails() { // Given: User has tasks navigateToTab("Tasks") wait(seconds: 2) // When: User taps on a task card let taskCard = app.otherElements.containing(NSPredicate(format: "identifier CONTAINS 'TaskCard'")).firstMatch if !taskCard.exists { // Try finding by task title let taskTitle = app.staticTexts.matching(NSPredicate(format: "label CONTAINS[c] 'task'")).firstMatch if taskTitle.exists { taskTitle.tap() } } else { taskCard.tap() } // Note: Depending on implementation, tapping a task might show details or edit form wait(seconds: 1) // Verify some form of task interaction occurred } // MARK: - Edit Task Tests func testEditTaskFlow() { // Given: User is viewing/editing a task navigateToTab("Tasks") wait(seconds: 2) // Find and tap edit button on a task let editButtons = app.buttons.matching(identifier: "pencil") if editButtons.count > 0 { editButtons.firstMatch.tap() wait(seconds: 1) // When: User modifies task details let titleField = app.textFields.containing(NSPredicate(format: "value != nil AND value != ''")).firstMatch if titleField.exists { app.clearText(in: titleField) titleField.typeText("Updated Task Title") // When: User saves changes let saveButton = app.buttons["Save"] if saveButton.exists { saveButton.tap() } // Then: Changes should be saved wait(seconds: 2) let updatedTitle = app.staticTexts["Updated Task Title"] XCTAssertTrue(updatedTitle.waitForExistence(timeout: 5) || app.navigationBars["All Tasks"].exists, "Should save task changes") } } } // MARK: - Complete Task Tests func testCompleteTaskFlow() { // Given: User has an incomplete task navigateToTab("Tasks") wait(seconds: 2) // When: User taps complete button on a task let completeButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Complete'")).firstMatch if completeButton.exists { completeButton.tap() wait(seconds: 1) // Then: Complete task dialog should be shown let completionDialog = app.sheets.firstMatch XCTAssertTrue(completionDialog.exists || app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Complete'")).firstMatch.exists, "Should show completion dialog") // When: User confirms completion let confirmButton = app.buttons["Complete"] if confirmButton.exists { confirmButton.tap() } // Then: Task should be marked as complete wait(seconds: 2) // Task should move to completed column or show completion status } } func testCompleteTaskWithDetails() { // Given: User is completing a task navigateToTab("Tasks") wait(seconds: 2) let completeButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Complete'")).firstMatch if completeButton.exists { completeButton.tap() wait(seconds: 1) // When: User adds completion details let notesField = app.textViews.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'notes' OR label CONTAINS[c] 'Notes'")).firstMatch if notesField.exists { notesField.tap() notesField.typeText("Task completed successfully") } let costField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'cost' OR label CONTAINS[c] 'Cost'")).firstMatch if costField.exists { costField.tap() costField.typeText("100") } // When: User saves completion let saveButton = app.buttons["Save"] if saveButton.exists { saveButton.tap() } // Then: Task should be completed with details wait(seconds: 2) } } // MARK: - Task Status Changes Tests func testMarkTaskInProgress() { // Given: User has a pending task navigateToTab("Tasks") wait(seconds: 2) // When: User marks task as in progress let inProgressButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'In Progress'")).firstMatch if inProgressButton.exists { inProgressButton.tap() wait(seconds: 2) // Then: Task should move to In Progress column let inProgressColumn = app.staticTexts["In Progress"] XCTAssertTrue(inProgressColumn.exists, "Should have In Progress column") } } func testCancelTask() { // Given: User has an active task navigateToTab("Tasks") wait(seconds: 2) // When: User cancels a task let cancelButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Cancel'")).firstMatch if cancelButton.exists { cancelButton.tap() // Confirm cancellation if prompted let confirmButton = app.alerts.buttons["Cancel Task"] if confirmButton.exists { confirmButton.tap() } // Then: Task should be cancelled wait(seconds: 2) } } func testUncancelTask() { // Given: User has a cancelled task navigateToTab("Tasks") wait(seconds: 2) // When: User uncancels a task let uncancelButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Uncancel' OR label CONTAINS[c] 'Restore'")).firstMatch if uncancelButton.exists { uncancelButton.tap() wait(seconds: 2) // Then: Task should be restored } } // MARK: - Archive Task Tests func testArchiveTask() { // Given: User has a completed task navigateToTab("Tasks") wait(seconds: 2) // When: User archives a task let archiveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Archive'")).firstMatch if archiveButton.exists { archiveButton.tap() wait(seconds: 2) // Then: Task should be archived (moved to archived column or hidden) let archivedColumn = app.staticTexts["Archived"] // Task may be in archived column or removed from view } } func testUnarchiveTask() { // Given: User has archived tasks navigateToTab("Tasks") wait(seconds: 2) // Scroll to archived column if it exists let scrollView = app.scrollViews.firstMatch if scrollView.exists { scrollView.swipeLeft() scrollView.swipeLeft() } // When: User unarchives a task let unarchiveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Unarchive'")).firstMatch if unarchiveButton.exists { unarchiveButton.tap() wait(seconds: 2) // Then: Task should be restored from archive } } // MARK: - Task Filtering and Viewing Tests func testSwipeBetweenTaskColumns() { // Given: User is viewing tasks navigateToTab("Tasks") wait(seconds: 2) let scrollView = app.scrollViews.firstMatch if scrollView.exists { // When: User swipes to view different columns scrollView.swipeLeft() wait(seconds: 0.5) // Then: Next column should be visible scrollView.swipeLeft() wait(seconds: 0.5) // User can navigate between columns scrollView.swipeRight() wait(seconds: 0.5) } } func testTasksByResidence() { // Given: User is viewing a residence navigateToTab("Residences") wait(seconds: 2) let firstResidence = app.cells.firstMatch if firstResidence.exists { firstResidence.tap() wait(seconds: 2) // Then: Tasks for that residence should be shown let tasksSection = app.staticTexts["Tasks"] XCTAssertTrue(tasksSection.exists || app.scrollViews.firstMatch.exists, "Should show tasks section in residence details") } } // MARK: - Task Recurrence Tests func testCreateRecurringTask() { // Given: User is creating a new task navigateToTab("Tasks") let addButton = app.navigationBars.buttons.matching(identifier: "plus").firstMatch if addButton.exists { addButton.tap() wait(seconds: 1) // When: User selects recurring frequency let frequencyPicker = app.pickers.firstMatch if frequencyPicker.exists { // Select a frequency (e.g., Monthly) let monthlyOption = app.pickerWheels.element.adjust(toPickerWheelValue: "Monthly") // Task creation with recurrence } } } }