471 lines
17 KiB
Swift
471 lines
17 KiB
Swift
import XCTest
|
|
|
|
/// Comprehensive tests for multi-user residence features
|
|
final class MultiUserUITests: BaseUITest {
|
|
|
|
override func setUp() {
|
|
super.setUp()
|
|
// Login as primary owner
|
|
login(username: "testowner", password: "TestPass123!")
|
|
let residencesTab = app.tabBars.buttons["Residences"]
|
|
XCTAssertTrue(residencesTab.waitForExistence(timeout: 10))
|
|
}
|
|
|
|
// MARK: - Manage Users Tests
|
|
|
|
func testManageUsersButtonVisibleForOwner() {
|
|
// Given: User owns a residence
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
// Then: Manage users button should be visible
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
XCTAssertTrue(manageUsersButton.exists, "Owner should see manage users button")
|
|
}
|
|
}
|
|
|
|
func testManageUsersButtonHiddenForSharedUser() {
|
|
// Given: User is a shared user (not owner)
|
|
logout()
|
|
login(username: "shareduser", password: "TestPass123!")
|
|
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
// Find a shared residence
|
|
let sharedResidence = app.cells.firstMatch
|
|
if sharedResidence.exists {
|
|
sharedResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
// Then: Manage users button should NOT be visible
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
XCTAssertFalse(manageUsersButton.exists, "Shared user should not see manage users button")
|
|
}
|
|
}
|
|
|
|
func testOpenManageUsersScreen() {
|
|
// Given: Owner is viewing a residence
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
// When: Owner taps manage users button
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// Then: Manage users screen should be displayed
|
|
let manageUsersTitle = app.navigationBars["Manage Users"]
|
|
XCTAssertTrue(manageUsersTitle.waitForExistence(timeout: 3), "Should show manage users screen")
|
|
|
|
// And: User list should be visible
|
|
let usersList = app.scrollViews.firstMatch
|
|
XCTAssertTrue(usersList.exists, "Should show users list")
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Share Code Tests
|
|
|
|
func testShareCodeInitiallyBlank() {
|
|
// Given: Owner opens manage users screen
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// Then: Share code should be blank initially
|
|
let noActiveCode = app.staticTexts["No active code"]
|
|
XCTAssertTrue(noActiveCode.exists, "Share code should start blank")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGenerateShareCode() {
|
|
// Given: Owner is on manage users screen
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// When: Owner taps generate code button
|
|
let generateButton = app.buttons["Generate"]
|
|
if !generateButton.exists {
|
|
// Button might say "New Code" if there's an existing code
|
|
let newCodeButton = app.buttons["New Code"]
|
|
if newCodeButton.exists {
|
|
newCodeButton.tap()
|
|
}
|
|
} else {
|
|
generateButton.tap()
|
|
}
|
|
|
|
// Then: Share code should be generated and displayed
|
|
wait(seconds: 2)
|
|
let shareCodeTexts = app.staticTexts.matching(NSPredicate(format: "label.length == 6 AND label MATCHES %@", "[A-Z0-9]{6}"))
|
|
XCTAssertTrue(shareCodeTexts.count > 0, "Should display 6-character share code")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testRegenerateShareCode() {
|
|
// Given: Owner has generated a share code
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// Generate first code
|
|
let generateButton = app.buttons["Generate"]
|
|
if generateButton.exists {
|
|
generateButton.tap()
|
|
wait(seconds: 2)
|
|
|
|
let firstCode = app.staticTexts.matching(NSPredicate(format: "label.length == 6 AND label MATCHES %@", "[A-Z0-9]{6}")).firstMatch.label
|
|
|
|
// When: Owner generates new code
|
|
let newCodeButton = app.buttons["New Code"]
|
|
if newCodeButton.exists {
|
|
newCodeButton.tap()
|
|
wait(seconds: 2)
|
|
|
|
// Then: A different code should be generated
|
|
let secondCode = app.staticTexts.matching(NSPredicate(format: "label.length == 6 AND label MATCHES %@", "[A-Z0-9]{6}")).firstMatch.label
|
|
XCTAssertNotEqual(firstCode, secondCode, "New code should be different")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Join Residence Tests
|
|
|
|
func testJoinResidenceWithValidCode() {
|
|
// This test requires coordination between two accounts
|
|
// Given: Owner generates a share code
|
|
var shareCode: String = ""
|
|
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
let generateButton = app.buttons["Generate"]
|
|
if generateButton.exists {
|
|
generateButton.tap()
|
|
wait(seconds: 2)
|
|
|
|
shareCode = app.staticTexts.matching(NSPredicate(format: "label.length == 6 AND label MATCHES %@", "[A-Z0-9]{6}")).firstMatch.label
|
|
}
|
|
|
|
// Close manage users screen
|
|
let closeButton = app.buttons["Close"]
|
|
if closeButton.exists {
|
|
closeButton.tap()
|
|
}
|
|
}
|
|
}
|
|
|
|
// When: Different user joins with code
|
|
if !shareCode.isEmpty {
|
|
logout()
|
|
login(username: "newuser", password: "TestPass123!")
|
|
|
|
navigateToTab("Residences")
|
|
wait(seconds: 1)
|
|
|
|
// Find join residence button
|
|
let joinButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Join'")).firstMatch
|
|
if joinButton.exists {
|
|
joinButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// Enter share code
|
|
let codeField = app.textFields.firstMatch
|
|
if codeField.exists {
|
|
codeField.tap()
|
|
codeField.typeText(shareCode)
|
|
|
|
// Submit
|
|
let submitButton = app.buttons["Join"]
|
|
if submitButton.exists {
|
|
submitButton.tap()
|
|
wait(seconds: 2)
|
|
|
|
// Then: User should be added to residence
|
|
let successMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Successfully joined'"))
|
|
XCTAssertTrue(successMessage.firstMatch.exists || app.cells.count > 0,
|
|
"Should join residence successfully")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func testJoinResidenceWithInvalidCode() {
|
|
// Given: User is on join residence screen
|
|
navigateToTab("Residences")
|
|
|
|
let joinButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Join'")).firstMatch
|
|
if joinButton.exists {
|
|
joinButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// When: User enters invalid code
|
|
let codeField = app.textFields.firstMatch
|
|
if codeField.exists {
|
|
codeField.tap()
|
|
codeField.typeText("INVALID")
|
|
|
|
let submitButton = app.buttons["Join"]
|
|
if submitButton.exists {
|
|
submitButton.tap()
|
|
wait(seconds: 2)
|
|
|
|
// Then: Error message should be shown
|
|
let errorMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Invalid' OR label CONTAINS[c] 'not found'"))
|
|
XCTAssertTrue(errorMessage.firstMatch.exists, "Should show invalid code error")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - User List Tests
|
|
|
|
func testUserListShowsAllUsers() {
|
|
// Given: Residence has multiple users
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// Then: User count should be displayed
|
|
let userCountLabel = app.staticTexts.matching(NSPredicate(format: "label CONTAINS[c] 'Users'"))
|
|
XCTAssertTrue(userCountLabel.count > 0, "Should show user count")
|
|
|
|
// And: Individual users should be listed
|
|
let usersList = app.scrollViews.firstMatch
|
|
XCTAssertTrue(usersList.exists, "Should show users list")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testOwnerLabelDisplayed() {
|
|
// Given: Owner is viewing manage users screen
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// Then: Owner badge should be visible next to owner's name
|
|
let ownerBadge = app.staticTexts["Owner"]
|
|
XCTAssertTrue(ownerBadge.exists, "Should show Owner badge")
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Remove User Tests
|
|
|
|
func testRemoveUserAsOwner() {
|
|
// Given: Owner has residence with multiple users
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// When: Owner taps remove button on a user
|
|
let removeButtons = app.buttons.matching(identifier: "trash")
|
|
if removeButtons.count > 0 {
|
|
let initialUserCount = removeButtons.count
|
|
removeButtons.firstMatch.tap()
|
|
|
|
// Confirm removal if prompted
|
|
let confirmButton = app.alerts.buttons["Remove"]
|
|
if confirmButton.exists {
|
|
confirmButton.tap()
|
|
}
|
|
|
|
// Then: User should be removed
|
|
wait(seconds: 2)
|
|
let newUserCount = app.buttons.matching(identifier: "trash").count
|
|
XCTAssertTrue(newUserCount < initialUserCount, "Should remove user")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func testCannotRemoveOwner() {
|
|
// Given: Owner is viewing manage users
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// Then: Owner row should NOT have remove button
|
|
let ownerLabel = app.staticTexts["Owner"]
|
|
if ownerLabel.exists {
|
|
// Check if there's a remove button in the same container
|
|
// Owner should not have a remove button next to their name
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Shared User Access Tests
|
|
|
|
func testSharedUserCanViewResidence() {
|
|
// Given: User is a shared user
|
|
logout()
|
|
login(username: "shareduser", password: "TestPass123!")
|
|
|
|
// Then: Shared residences should appear in list
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let residencesList = app.cells.count
|
|
XCTAssertTrue(residencesList > 0, "Shared user should see shared residences")
|
|
}
|
|
|
|
func testSharedUserCanCreateTasks() {
|
|
// Given: Shared user is viewing a shared residence
|
|
logout()
|
|
login(username: "shareduser", password: "TestPass123!")
|
|
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
// When: Shared user tries to create a task
|
|
let addButton = app.navigationBars.buttons.matching(identifier: "plus").firstMatch
|
|
XCTAssertTrue(addButton.exists, "Shared user should be able to add tasks")
|
|
|
|
if addButton.exists {
|
|
addButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
// Then: Add task form should be displayed
|
|
let titleField = app.textFields.firstMatch
|
|
XCTAssertTrue(titleField.exists, "Shared user should be able to create tasks")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testSharedUserCanEditTasks() {
|
|
// Given: Shared user is viewing tasks
|
|
logout()
|
|
login(username: "shareduser", password: "TestPass123!")
|
|
|
|
navigateToTab("Tasks")
|
|
wait(seconds: 2)
|
|
|
|
// When: Shared user tries to edit a task
|
|
let editButtons = app.buttons.matching(identifier: "pencil")
|
|
if editButtons.count > 0 {
|
|
// Then: Edit buttons should be available
|
|
XCTAssertTrue(editButtons.firstMatch.exists, "Shared user should be able to edit tasks")
|
|
}
|
|
}
|
|
|
|
func testUserCountDisplayed() {
|
|
// Given: Owner is viewing a residence
|
|
navigateToTab("Residences")
|
|
wait(seconds: 2)
|
|
|
|
let firstResidence = app.cells.firstMatch
|
|
if firstResidence.exists {
|
|
firstResidence.tap()
|
|
wait(seconds: 2)
|
|
|
|
// Then: User count should be visible somewhere on the screen
|
|
// This depends on your UI design - adjust as needed
|
|
let manageUsersButton = app.navigationBars.buttons.matching(identifier: "person.2").firstMatch
|
|
if manageUsersButton.exists {
|
|
manageUsersButton.tap()
|
|
wait(seconds: 1)
|
|
|
|
let userCountText = app.staticTexts.matching(NSPredicate(format: "label CONTAINS[c] 'Users'"))
|
|
XCTAssertTrue(userCountText.count > 0, "Should display user count")
|
|
}
|
|
}
|
|
}
|
|
}
|