Files
honeyDueKMP/iosApp/CaseraUITests/PageObjects/LoginScreen.swift
Trey t 7444f73b46 Close all 25 codex audit findings across KMP, iOS, and Android
Remediate all P0-S priority findings from cross-platform architecture audit:
- Harden token storage with EncryptedSharedPreferences (Android) and Keychain (iOS)
- Add SSL pinning and certificate validation to API clients
- Fix subscription cache race conditions and add thread-safe access
- Add input validation for document uploads and file type restrictions
- Refactor DocumentApi to use proper multipart upload flow
- Add rate limiting awareness and retry logic to API layer
- Harden subscription tier enforcement in SubscriptionHelper
- Add biometric prompt for sensitive actions (Login, Onboarding)
- Fix notification permission handling and device registration
- Add UI test infrastructure (page objects, fixtures, smoke tests)
- Add CI workflow for mobile builds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:15:34 -06:00

87 lines
2.8 KiB
Swift

import XCTest
/// Page object for the login screen.
///
/// Uses accessibility identifiers from `AccessibilityIdentifiers.Authentication`
/// to locate elements. Provides typed actions for login flow interactions.
class LoginScreen: BaseScreen {
// MARK: - Elements
var emailField: XCUIElement {
app.textFields[AccessibilityIdentifiers.Authentication.usernameField]
}
var passwordField: XCUIElement {
// Password field may be a SecureTextField or regular TextField depending on visibility toggle
let secure = app.secureTextFields[AccessibilityIdentifiers.Authentication.passwordField]
if secure.exists { return secure }
return app.textFields[AccessibilityIdentifiers.Authentication.passwordField]
}
var loginButton: XCUIElement {
app.buttons[AccessibilityIdentifiers.Authentication.loginButton]
}
var appleSignInButton: XCUIElement {
app.buttons[AccessibilityIdentifiers.Authentication.appleSignInButton]
}
var signUpButton: XCUIElement {
app.buttons[AccessibilityIdentifiers.Authentication.signUpButton]
}
var forgotPasswordButton: XCUIElement {
app.buttons[AccessibilityIdentifiers.Authentication.forgotPasswordButton]
}
var passwordVisibilityToggle: XCUIElement {
app.buttons[AccessibilityIdentifiers.Authentication.passwordVisibilityToggle]
}
var welcomeText: XCUIElement {
app.staticTexts["Welcome Back"]
}
override var isDisplayed: Bool {
emailField.waitForExistence(timeout: timeout)
}
// MARK: - Actions
/// Logs in with the provided credentials and returns a MainTabScreen.
/// Waits for the email field to appear before typing.
@discardableResult
func login(email: String, password: String) -> MainTabScreen {
waitForElement(emailField).tap()
emailField.typeText(email)
let pwField = passwordField
pwField.tap()
pwField.typeText(password)
loginButton.tap()
return MainTabScreen(app: app)
}
/// Taps the sign up / register link and returns a RegisterScreen.
@discardableResult
func tapSignUp() -> RegisterScreen {
waitForElement(signUpButton).tap()
return RegisterScreen(app: app)
}
/// Taps the forgot password link.
func tapForgotPassword() {
waitForElement(forgotPasswordButton).tap()
}
/// Toggles password visibility and returns whether the password is now visible.
@discardableResult
func togglePasswordVisibility() -> Bool {
waitForElement(passwordVisibilityToggle).tap()
// If a regular text field with the password identifier exists, password is visible
return app.textFields[AccessibilityIdentifiers.Authentication.passwordField].exists
}
}