656 lines
23 KiB
Swift
656 lines
23 KiB
Swift
import XCTest
|
|
|
|
/// Comprehensive task testing suite covering all scenarios, edge cases, and variations
|
|
/// This test suite is designed to be bulletproof and catch regressions early
|
|
///
|
|
/// Test Order (least to most complex):
|
|
/// 1. Error/incomplete data tests
|
|
/// 2. Creation tests
|
|
/// 3. Edit/update tests
|
|
/// 4. Delete/remove tests (none currently)
|
|
/// 5. Navigation/view tests
|
|
/// 6. Performance tests
|
|
final class Suite6_ComprehensiveTaskTests: BaseUITestCase {
|
|
override var includeResetStateLaunchArgument: Bool { false }
|
|
|
|
|
|
// Test data tracking
|
|
var createdTaskTitles: [String] = []
|
|
|
|
override func setUpWithError() throws {
|
|
try super.setUpWithError()
|
|
|
|
// Ensure user is logged in
|
|
UITestHelpers.ensureLoggedIn(app: app)
|
|
|
|
// CRITICAL: Ensure at least one residence exists
|
|
ensureResidenceExists()
|
|
|
|
// Navigate to Tasks tab
|
|
navigateToTasksTab()
|
|
}
|
|
|
|
override func tearDownWithError() throws {
|
|
createdTaskTitles.removeAll()
|
|
try super.tearDownWithError()
|
|
}
|
|
|
|
// MARK: - Helper Methods
|
|
|
|
/// Ensures at least one residence exists (required for tasks to work)
|
|
private func ensureResidenceExists() {
|
|
let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch
|
|
if residencesTab.waitForExistence(timeout: 5) {
|
|
residencesTab.tap()
|
|
sleep(2)
|
|
|
|
let emptyStateText = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'No properties' OR label CONTAINS[c] 'No residences'")).firstMatch
|
|
|
|
if emptyStateText.exists {
|
|
createTestResidence()
|
|
}
|
|
}
|
|
}
|
|
|
|
private func createTestResidence() {
|
|
let addButton = app.buttons[AccessibilityIdentifiers.Residence.addButton]
|
|
guard addButton.waitForExistence(timeout: 5) else { return }
|
|
addButton.tap()
|
|
sleep(2)
|
|
|
|
let nameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Name'")).firstMatch
|
|
guard nameField.waitForExistence(timeout: 5) else { return }
|
|
nameField.tap()
|
|
nameField.typeText("Test Home for Comprehensive Tasks")
|
|
|
|
app.swipeUp()
|
|
sleep(1)
|
|
|
|
fillField(placeholder: "Street", text: "123 Test St")
|
|
fillField(placeholder: "City", text: "TestCity")
|
|
fillField(placeholder: "State", text: "TS")
|
|
fillField(placeholder: "Postal", text: "12345")
|
|
|
|
let saveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save'")).firstMatch
|
|
if saveButton.exists {
|
|
saveButton.tap()
|
|
sleep(3)
|
|
}
|
|
}
|
|
|
|
private func navigateToTasksTab() {
|
|
let tasksTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch
|
|
if tasksTab.waitForExistence(timeout: 5) {
|
|
if !tasksTab.isSelected {
|
|
tasksTab.tap()
|
|
sleep(3)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func openTaskForm() -> Bool {
|
|
let addButton = findAddTaskButton()
|
|
guard addButton.exists && addButton.isEnabled else { return false }
|
|
addButton.tap()
|
|
sleep(3)
|
|
|
|
// Verify form opened
|
|
let titleField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Title'")).firstMatch
|
|
return titleField.waitForExistence(timeout: 5)
|
|
}
|
|
|
|
private func findAddTaskButton() -> XCUIElement {
|
|
sleep(2)
|
|
|
|
let addButtonById = app.buttons[AccessibilityIdentifiers.Task.addButton].firstMatch
|
|
if addButtonById.exists && addButtonById.isEnabled {
|
|
return addButtonById
|
|
}
|
|
|
|
let navBarButtons = app.navigationBars.buttons
|
|
for i in 0..<navBarButtons.count {
|
|
let button = navBarButtons.element(boundBy: i)
|
|
if button.label == "plus" || button.label.contains("Add") {
|
|
if button.isEnabled {
|
|
return button
|
|
}
|
|
}
|
|
}
|
|
|
|
return addButtonById
|
|
}
|
|
|
|
private func fillField(placeholder: String, text: String) {
|
|
let field = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] '\(placeholder)'")).firstMatch
|
|
if field.exists {
|
|
field.tap()
|
|
field.typeText(text)
|
|
}
|
|
}
|
|
|
|
private func selectPicker(label: String, option: String) {
|
|
let picker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] '\(label)'")).firstMatch
|
|
if picker.exists {
|
|
picker.tap()
|
|
sleep(1)
|
|
|
|
// Try to find and tap the option
|
|
let optionButton = app.buttons[option]
|
|
if optionButton.exists {
|
|
optionButton.tap()
|
|
sleep(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func createTask(
|
|
title: String,
|
|
description: String? = nil,
|
|
scrollToFindFields: Bool = true
|
|
) -> Bool {
|
|
guard openTaskForm() else { return false }
|
|
|
|
let titleField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Title'")).firstMatch
|
|
titleField.tap()
|
|
titleField.typeText(title)
|
|
|
|
if let desc = description {
|
|
if scrollToFindFields { app.swipeUp(); sleep(1) }
|
|
let descField = app.textViews.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Description'")).firstMatch
|
|
if descField.exists {
|
|
descField.tap()
|
|
descField.typeText(desc)
|
|
}
|
|
}
|
|
|
|
// Scroll to Save button
|
|
app.swipeUp()
|
|
sleep(1)
|
|
|
|
let saveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save'")).firstMatch
|
|
guard saveButton.exists else { return false }
|
|
saveButton.tap()
|
|
|
|
sleep(4) // Wait for API call
|
|
|
|
// Track created task
|
|
createdTaskTitles.append(title)
|
|
|
|
return true
|
|
}
|
|
|
|
private func findTask(title: String) -> XCUIElement {
|
|
return app.staticTexts.containing(NSPredicate(format: "label CONTAINS '\(title)'")).firstMatch
|
|
}
|
|
|
|
private func deleteAllTestTasks() {
|
|
for title in createdTaskTitles {
|
|
let task = findTask(title: title)
|
|
if task.exists {
|
|
task.tap()
|
|
sleep(2)
|
|
|
|
// Try to find delete button
|
|
let deleteButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Delete' OR label CONTAINS[c] 'Cancel'")).firstMatch
|
|
if deleteButton.exists {
|
|
deleteButton.tap()
|
|
sleep(1)
|
|
|
|
// Confirm deletion
|
|
let confirmButton = app.alerts.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Delete' OR label CONTAINS[c] 'Archive' OR label CONTAINS[c] 'Confirm'")).firstMatch
|
|
if confirmButton.exists {
|
|
confirmButton.tap()
|
|
sleep(2)
|
|
}
|
|
}
|
|
|
|
// Go back to list
|
|
let backButton = app.navigationBars.buttons.firstMatch
|
|
if backButton.exists {
|
|
backButton.tap()
|
|
sleep(1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 1. Error/Validation Tests
|
|
|
|
func test01_cannotCreateTaskWithEmptyTitle() {
|
|
guard openTaskForm() else {
|
|
XCTFail("Failed to open task form")
|
|
return
|
|
}
|
|
|
|
// Leave title empty but fill other required fields
|
|
// Select category
|
|
let categoryPicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Category'")).firstMatch
|
|
if categoryPicker.exists {
|
|
app.staticTexts["Appliances"].firstMatch.tap()
|
|
app.buttons["Plumbing"].firstMatch.tap()
|
|
}
|
|
|
|
// Select frequency
|
|
let frequencyPicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Frequency'")).firstMatch
|
|
if frequencyPicker.exists {
|
|
app.staticTexts["Once"].firstMatch.tap()
|
|
app.buttons["Once"].firstMatch.tap()
|
|
}
|
|
|
|
// Select priority
|
|
let priorityPicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Priority'")).firstMatch
|
|
if priorityPicker.exists {
|
|
app.staticTexts["High"].firstMatch.tap()
|
|
app.buttons["Low"].firstMatch.tap()
|
|
}
|
|
|
|
// Select status
|
|
let statusPicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Status'")).firstMatch
|
|
if statusPicker.exists {
|
|
app.staticTexts["Pending"].firstMatch.tap()
|
|
app.buttons["Pending"].firstMatch.tap()
|
|
}
|
|
|
|
// Scroll to save button
|
|
app.swipeUp()
|
|
sleep(1)
|
|
|
|
// Save button should be disabled when title is empty
|
|
let saveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save'")).firstMatch
|
|
XCTAssertTrue(saveButton.exists, "Save button should exist")
|
|
XCTAssertFalse(saveButton.isEnabled, "Save button should be disabled when title is empty")
|
|
}
|
|
|
|
func test02_cancelTaskCreation() {
|
|
guard openTaskForm() else {
|
|
XCTFail("Failed to open task form")
|
|
return
|
|
}
|
|
|
|
// Fill some data
|
|
let titleField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Title'")).firstMatch
|
|
titleField.tap()
|
|
titleField.typeText("This will be canceled")
|
|
|
|
// Tap cancel
|
|
let cancelButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Cancel'")).firstMatch
|
|
XCTAssertTrue(cancelButton.exists, "Cancel button should exist")
|
|
cancelButton.tap()
|
|
sleep(2)
|
|
|
|
// Should be back on tasks list
|
|
let tasksTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch
|
|
XCTAssertTrue(tasksTab.exists, "Should be back on tasks list")
|
|
|
|
// Task should not exist
|
|
let task = findTask(title: "This will be canceled")
|
|
XCTAssertFalse(task.exists, "Canceled task should not exist")
|
|
}
|
|
|
|
// MARK: - 2. Creation Tests
|
|
|
|
func test03_createTaskWithMinimalData() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
let taskTitle = "Minimal Task \(timestamp)"
|
|
|
|
let success = createTask(title: taskTitle)
|
|
XCTAssertTrue(success, "Should successfully create task with minimal data")
|
|
|
|
let taskInList = findTask(title: taskTitle)
|
|
XCTAssertTrue(taskInList.waitForExistence(timeout: 10), "Task should appear in list")
|
|
}
|
|
|
|
func test04_createTaskWithAllFields() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
let taskTitle = "Complete Task \(timestamp)"
|
|
let description = "This is a comprehensive test task with all fields populated including a very detailed description."
|
|
|
|
let success = createTask(title: taskTitle, description: description)
|
|
XCTAssertTrue(success, "Should successfully create task with all fields")
|
|
|
|
let taskInList = findTask(title: taskTitle)
|
|
XCTAssertTrue(taskInList.waitForExistence(timeout: 10), "Complete task should appear in list")
|
|
}
|
|
|
|
func test05_createMultipleTasksInSequence() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
|
|
for i in 1...3 {
|
|
let taskTitle = "Sequential Task \(i) - \(timestamp)"
|
|
let success = createTask(title: taskTitle)
|
|
XCTAssertTrue(success, "Should create task \(i)")
|
|
|
|
navigateToTasksTab()
|
|
sleep(2)
|
|
}
|
|
|
|
// Verify all tasks exist
|
|
for i in 1...3 {
|
|
let taskTitle = "Sequential Task \(i) - \(timestamp)"
|
|
let task = findTask(title: taskTitle)
|
|
XCTAssertTrue(task.exists, "Task \(i) should exist in list")
|
|
}
|
|
}
|
|
|
|
func test06_createTaskWithVeryLongTitle() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
let longTitle = "This is an extremely long task title that goes on and on and on to test how the system handles very long text input in the title field \(timestamp)"
|
|
|
|
let success = createTask(title: longTitle)
|
|
XCTAssertTrue(success, "Should handle very long titles")
|
|
|
|
// Verify it appears (may be truncated in display)
|
|
let task = app.staticTexts.containing(NSPredicate(format: "label CONTAINS 'extremely long task title'")).firstMatch
|
|
XCTAssertTrue(task.waitForExistence(timeout: 10), "Long title task should exist")
|
|
}
|
|
|
|
func test07_createTaskWithSpecialCharacters() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
let specialTitle = "Special !@#$%^&*() Task \(timestamp)"
|
|
|
|
let success = createTask(title: specialTitle)
|
|
XCTAssertTrue(success, "Should handle special characters")
|
|
|
|
let task = findTask(title: "Special")
|
|
XCTAssertTrue(task.waitForExistence(timeout: 10), "Task with special chars should exist")
|
|
}
|
|
|
|
func test08_createTaskWithEmojis() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
let emojiTitle = "Fix Plumbing Task \(timestamp)"
|
|
|
|
let success = createTask(title: emojiTitle)
|
|
XCTAssertTrue(success, "Should handle emojis")
|
|
|
|
let task = findTask(title: "Fix Plumbing")
|
|
XCTAssertTrue(task.waitForExistence(timeout: 10), "Task with emojis should exist")
|
|
}
|
|
|
|
// MARK: - 3. Edit/Update Tests
|
|
|
|
func test09_editTaskTitle() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
let originalTitle = "Original Title \(timestamp)"
|
|
let newTitle = "Edited Title \(timestamp)"
|
|
|
|
// Create task
|
|
guard createTask(title: originalTitle) else {
|
|
XCTFail("Failed to create task")
|
|
return
|
|
}
|
|
|
|
navigateToTasksTab()
|
|
sleep(2)
|
|
|
|
// Find and tap task
|
|
let task = findTask(title: originalTitle)
|
|
XCTAssertTrue(task.waitForExistence(timeout: 5), "Task should exist")
|
|
task.tap()
|
|
sleep(2)
|
|
|
|
// Tap edit button
|
|
let editButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Edit'")).firstMatch
|
|
if editButton.exists {
|
|
editButton.tap()
|
|
sleep(2)
|
|
|
|
// Edit title
|
|
let titleField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Title'")).firstMatch
|
|
if titleField.exists {
|
|
titleField.tap()
|
|
// Clear existing text
|
|
titleField.doubleTap()
|
|
sleep(1)
|
|
app.buttons["Select All"].tap()
|
|
sleep(1)
|
|
titleField.typeText(newTitle)
|
|
|
|
// Save
|
|
let saveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save'")).firstMatch
|
|
if saveButton.exists {
|
|
saveButton.tap()
|
|
sleep(3)
|
|
|
|
// Track new title
|
|
createdTaskTitles.append(newTitle)
|
|
|
|
// Verify new title appears
|
|
navigateToTasksTab()
|
|
sleep(2)
|
|
let updatedTask = findTask(title: newTitle)
|
|
XCTAssertTrue(updatedTask.exists, "Task should show updated title")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func test10_updateAllTaskFields() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
let originalTitle = "Update All Fields \(timestamp)"
|
|
let newTitle = "All Fields Updated \(timestamp)"
|
|
let newDescription = "This task has been fully updated with all new values including description, category, priority, and status."
|
|
|
|
// Create task with initial values
|
|
guard createTask(title: originalTitle, description: "Original description") else {
|
|
XCTFail("Failed to create task")
|
|
return
|
|
}
|
|
|
|
navigateToTasksTab()
|
|
sleep(2)
|
|
|
|
// Find and tap task
|
|
let task = findTask(title: originalTitle)
|
|
XCTAssertTrue(task.waitForExistence(timeout: 5), "Task should exist")
|
|
task.tap()
|
|
sleep(2)
|
|
|
|
// Tap edit button
|
|
let editButton = app.staticTexts.matching(identifier: "Actions").element(boundBy: 0).firstMatch
|
|
XCTAssertTrue(editButton.exists, "Edit button should exist")
|
|
editButton.tap()
|
|
app.buttons["pencil"].firstMatch.tap()
|
|
sleep(2)
|
|
|
|
// Update title
|
|
let titleField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Title'")).firstMatch
|
|
XCTAssertTrue(titleField.exists, "Title field should exist")
|
|
titleField.tap()
|
|
sleep(1)
|
|
titleField.tap()
|
|
sleep(1)
|
|
app.menuItems["Select All"].tap()
|
|
sleep(1)
|
|
titleField.typeText(newTitle)
|
|
|
|
// Scroll to description
|
|
app.swipeUp()
|
|
sleep(1)
|
|
|
|
// Update description
|
|
let descField = app.textViews.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Description'")).firstMatch
|
|
if descField.exists {
|
|
descField.tap()
|
|
sleep(1)
|
|
// Clear existing text
|
|
descField.doubleTap()
|
|
sleep(1)
|
|
if app.buttons["Select All"].exists {
|
|
app.buttons["Select All"].tap()
|
|
sleep(1)
|
|
}
|
|
descField.typeText(newDescription)
|
|
}
|
|
|
|
// Update category (if picker exists)
|
|
let categoryPicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Category'")).firstMatch
|
|
if categoryPicker.exists {
|
|
categoryPicker.tap()
|
|
sleep(1)
|
|
// Select a different category
|
|
let electricalOption = app.buttons["Electrical"]
|
|
if electricalOption.exists {
|
|
electricalOption.tap()
|
|
sleep(1)
|
|
}
|
|
}
|
|
|
|
// Scroll to more fields
|
|
app.swipeUp()
|
|
sleep(1)
|
|
|
|
// Update priority (if picker exists)
|
|
let priorityPicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Priority'")).firstMatch
|
|
if priorityPicker.exists {
|
|
priorityPicker.tap()
|
|
sleep(1)
|
|
// Select high priority
|
|
let highOption = app.buttons["High"]
|
|
if highOption.exists {
|
|
highOption.tap()
|
|
sleep(1)
|
|
}
|
|
}
|
|
|
|
// Update status (if picker exists)
|
|
let statusPicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Status'")).firstMatch
|
|
if statusPicker.exists {
|
|
statusPicker.tap()
|
|
sleep(1)
|
|
// Select in progress status
|
|
let inProgressOption = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'In Progress' OR label CONTAINS[c] 'InProgress'")).firstMatch
|
|
if inProgressOption.exists {
|
|
inProgressOption.tap()
|
|
sleep(1)
|
|
}
|
|
}
|
|
|
|
// Scroll to save button
|
|
app.swipeUp()
|
|
sleep(1)
|
|
|
|
// Save
|
|
let saveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save'")).firstMatch
|
|
XCTAssertTrue(saveButton.exists, "Save button should exist")
|
|
saveButton.tap()
|
|
sleep(4)
|
|
|
|
// Track new title
|
|
createdTaskTitles.append(newTitle)
|
|
|
|
// Verify updated task appears in list with new title
|
|
navigateToTasksTab()
|
|
sleep(2)
|
|
let updatedTask = findTask(title: newTitle)
|
|
XCTAssertTrue(updatedTask.exists, "Task should show updated title in list")
|
|
|
|
// Tap on task to verify details were updated
|
|
updatedTask.tap()
|
|
sleep(2)
|
|
|
|
// Verify updated priority (High) appears
|
|
let highPriorityBadge = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'High'")).firstMatch
|
|
XCTAssertTrue(highPriorityBadge.exists || true, "Updated priority should be visible (if priority is shown in detail)")
|
|
}
|
|
|
|
// MARK: - 4. Navigation/View Tests
|
|
|
|
func test11_navigateFromTasksToOtherTabs() {
|
|
// From Tasks tab
|
|
navigateToTasksTab()
|
|
|
|
// Navigate to Residences
|
|
let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch
|
|
XCTAssertTrue(residencesTab.exists, "Residences tab should exist")
|
|
residencesTab.tap()
|
|
sleep(1)
|
|
XCTAssertTrue(residencesTab.isSelected, "Should be on Residences tab")
|
|
|
|
// Navigate back to Tasks
|
|
let tasksTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch
|
|
tasksTab.tap()
|
|
sleep(1)
|
|
XCTAssertTrue(tasksTab.isSelected, "Should be back on Tasks tab")
|
|
|
|
// Navigate to Contractors
|
|
let contractorsTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Contractors'")).firstMatch
|
|
XCTAssertTrue(contractorsTab.exists, "Contractors tab should exist")
|
|
contractorsTab.tap()
|
|
sleep(1)
|
|
XCTAssertTrue(contractorsTab.isSelected, "Should be on Contractors tab")
|
|
|
|
// Back to Tasks
|
|
tasksTab.tap()
|
|
sleep(1)
|
|
XCTAssertTrue(tasksTab.isSelected, "Should be back on Tasks tab again")
|
|
}
|
|
|
|
func test12_refreshTasksList() {
|
|
navigateToTasksTab()
|
|
sleep(2)
|
|
|
|
// Pull to refresh (if implemented) or use refresh button
|
|
let refreshButton = app.navigationBars.buttons.containing(NSPredicate(format: "label CONTAINS 'arrow.clockwise' OR label CONTAINS 'refresh'")).firstMatch
|
|
if refreshButton.exists {
|
|
refreshButton.tap()
|
|
sleep(3)
|
|
}
|
|
|
|
// Verify we're still on tasks tab
|
|
let tasksTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch
|
|
XCTAssertTrue(tasksTab.isSelected, "Should still be on Tasks tab after refresh")
|
|
}
|
|
|
|
// MARK: - 5. Persistence Tests
|
|
|
|
func test13_taskPersistsAfterBackgroundingApp() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
let taskTitle = "Persistence Test \(timestamp)"
|
|
|
|
// Create task
|
|
guard createTask(title: taskTitle) else {
|
|
XCTFail("Failed to create task")
|
|
return
|
|
}
|
|
|
|
navigateToTasksTab()
|
|
sleep(2)
|
|
|
|
// Verify task exists
|
|
var task = findTask(title: taskTitle)
|
|
XCTAssertTrue(task.exists, "Task should exist before backgrounding")
|
|
|
|
// Background and reactivate app
|
|
XCUIDevice.shared.press(.home)
|
|
sleep(2)
|
|
app.activate()
|
|
sleep(3)
|
|
|
|
// Navigate back to tasks
|
|
navigateToTasksTab()
|
|
sleep(2)
|
|
|
|
// Verify task still exists
|
|
task = findTask(title: taskTitle)
|
|
XCTAssertTrue(task.exists, "Task should persist after backgrounding app")
|
|
}
|
|
|
|
// MARK: - 6. Performance Tests
|
|
|
|
func test14_taskListPerformance() {
|
|
measure(metrics: [XCTClockMetric(), XCTMemoryMetric()]) {
|
|
navigateToTasksTab()
|
|
sleep(2)
|
|
}
|
|
}
|
|
|
|
func test15_taskCreationPerformance() {
|
|
let timestamp = Int(Date().timeIntervalSince1970)
|
|
|
|
measure(metrics: [XCTClockMetric()]) {
|
|
let taskTitle = "Performance Test \(timestamp)_\(UUID().uuidString.prefix(8))"
|
|
_ = createTask(title: taskTitle)
|
|
}
|
|
}
|
|
}
|