181 lines
5.7 KiB
Swift
181 lines
5.7 KiB
Swift
import XCTest
|
|
|
|
/// Helper extensions and utilities for UI tests
|
|
extension XCUIApplication {
|
|
/// Launch the app and reset to initial state
|
|
func launchAndReset() {
|
|
launchArguments = ["--uitesting"]
|
|
launch()
|
|
}
|
|
|
|
/// Clear all text from a text field
|
|
func clearText(in textField: XCUIElement) {
|
|
textField.tap()
|
|
textField.press(forDuration: 1.2)
|
|
menuItems["Select All"].tap()
|
|
textField.typeText(XCUIKeyboardKey.delete.rawValue)
|
|
}
|
|
}
|
|
|
|
/// Base test class with common setup and teardown
|
|
class BaseUITest: XCTestCase {
|
|
var app: XCUIApplication!
|
|
|
|
override func setUp() {
|
|
super.setUp()
|
|
continueAfterFailure = false
|
|
app = XCUIApplication()
|
|
app.launchAndReset()
|
|
}
|
|
|
|
override func tearDown() {
|
|
app = nil
|
|
super.tearDown()
|
|
}
|
|
|
|
// MARK: - Authentication Helpers
|
|
|
|
func login(username: String, password: String) {
|
|
let usernameField = app.textFields["Username"]
|
|
let passwordField = app.secureTextFields["Password"]
|
|
let loginButton = app.buttons["Login"]
|
|
|
|
if usernameField.exists {
|
|
usernameField.tap()
|
|
usernameField.typeText(username)
|
|
}
|
|
|
|
if passwordField.exists {
|
|
passwordField.tap()
|
|
passwordField.typeText(password)
|
|
}
|
|
|
|
if loginButton.exists {
|
|
loginButton.tap()
|
|
}
|
|
}
|
|
|
|
func logout() {
|
|
let profileTab = app.tabBars.buttons["Profile"]
|
|
profileTab.tap()
|
|
|
|
let logoutButton = app.buttons["Log Out"]
|
|
XCTAssertTrue(logoutButton.waitForExistence(timeout: 5))
|
|
logoutButton.tap()
|
|
}
|
|
|
|
func register(username: String, email: String, password: String, firstName: String = "", lastName: String = "") {
|
|
let signUpButton = app.buttons["Sign Up"]
|
|
XCTAssertTrue(signUpButton.waitForExistence(timeout: 3))
|
|
signUpButton.tap()
|
|
|
|
let usernameField = app.textFields["Username"]
|
|
let emailField = app.textFields["Email"]
|
|
let passwordField = app.secureTextFields["Password"]
|
|
let registerButton = app.buttons["Register"]
|
|
|
|
usernameField.tap()
|
|
usernameField.typeText(username)
|
|
|
|
emailField.tap()
|
|
emailField.typeText(email)
|
|
|
|
passwordField.tap()
|
|
passwordField.typeText(password)
|
|
|
|
if !firstName.isEmpty {
|
|
let firstNameField = app.textFields["First Name"]
|
|
firstNameField.tap()
|
|
firstNameField.typeText(firstName)
|
|
}
|
|
|
|
if !lastName.isEmpty {
|
|
let lastNameField = app.textFields["Last Name"]
|
|
lastNameField.tap()
|
|
lastNameField.typeText(lastName)
|
|
}
|
|
|
|
registerButton.tap()
|
|
}
|
|
|
|
// MARK: - Navigation Helpers
|
|
|
|
func navigateToTab(_ tabName: String) {
|
|
let tab = app.tabBars.buttons[tabName]
|
|
XCTAssertTrue(tab.waitForExistence(timeout: 3))
|
|
tab.tap()
|
|
}
|
|
|
|
func navigateBack() {
|
|
app.navigationBars.buttons.element(boundBy: 0).tap()
|
|
}
|
|
|
|
// MARK: - Assertion Helpers
|
|
|
|
func assertElementExists(_ identifier: String, timeout: TimeInterval = 5) {
|
|
let element = app.descendants(matching: .any).matching(identifier: identifier).firstMatch
|
|
XCTAssertTrue(element.waitForExistence(timeout: timeout), "Element '\(identifier)' does not exist")
|
|
}
|
|
|
|
func assertElementDoesNotExist(_ identifier: String, timeout: TimeInterval = 2) {
|
|
let element = app.descendants(matching: .any).matching(identifier: identifier).firstMatch
|
|
XCTAssertFalse(element.waitForExistence(timeout: timeout), "Element '\(identifier)' should not exist")
|
|
}
|
|
|
|
func assertNavigatedTo(title: String, timeout: TimeInterval = 5) {
|
|
let navigationBar = app.navigationBars[title]
|
|
XCTAssertTrue(navigationBar.waitForExistence(timeout: timeout), "Did not navigate to '\(title)'")
|
|
}
|
|
|
|
// MARK: - Wait Helpers
|
|
|
|
func wait(seconds: TimeInterval) {
|
|
Thread.sleep(forTimeInterval: seconds)
|
|
}
|
|
|
|
func waitForElementToAppear(_ element: XCUIElement, timeout: TimeInterval = 5) -> Bool {
|
|
return element.waitForExistence(timeout: timeout)
|
|
}
|
|
|
|
func waitForElementToDisappear(_ element: XCUIElement, timeout: TimeInterval = 5) -> Bool {
|
|
let predicate = NSPredicate(format: "exists == false")
|
|
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: element)
|
|
let result = XCTWaiter.wait(for: [expectation], timeout: timeout)
|
|
return result == .completed
|
|
}
|
|
}
|
|
|
|
/// Identifiers for UI elements (for better testability)
|
|
struct Identifiers {
|
|
struct Authentication {
|
|
static let usernameField = "UsernameField"
|
|
static let passwordField = "PasswordField"
|
|
static let loginButton = "LoginButton"
|
|
static let registerButton = "RegisterButton"
|
|
static let logoutButton = "LogoutButton"
|
|
}
|
|
|
|
struct Residence {
|
|
static let addButton = "AddResidenceButton"
|
|
static let editButton = "EditResidenceButton"
|
|
static let deleteButton = "DeleteResidenceButton"
|
|
static let nameField = "ResidenceNameField"
|
|
static let addressField = "ResidenceAddressField"
|
|
}
|
|
|
|
struct Task {
|
|
static let addButton = "AddTaskButton"
|
|
static let completeButton = "CompleteTaskButton"
|
|
static let editButton = "EditTaskButton"
|
|
static let titleField = "TaskTitleField"
|
|
static let descriptionField = "TaskDescriptionField"
|
|
}
|
|
|
|
struct MultiUser {
|
|
static let manageUsersButton = "ManageUsersButton"
|
|
static let generateCodeButton = "GenerateCodeButton"
|
|
static let joinButton = "JoinResidenceButton"
|
|
static let shareCodeField = "ShareCodeField"
|
|
}
|
|
}
|