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>
This commit is contained in:
120
iosApp/CaseraUITests/CriticalPath/SmokeTests.swift
Normal file
120
iosApp/CaseraUITests/CriticalPath/SmokeTests.swift
Normal file
@@ -0,0 +1,120 @@
|
||||
import XCTest
|
||||
|
||||
/// Smoke tests - run on every PR. Must complete in <2 minutes.
|
||||
///
|
||||
/// Tests that the app launches successfully, the auth screen renders correctly,
|
||||
/// and core navigation is functional. These are the minimum-viability tests
|
||||
/// that must pass before any PR can merge.
|
||||
final class SmokeTests: XCTestCase {
|
||||
var app: XCUIApplication!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
continueAfterFailure = false
|
||||
app = TestLaunchConfig.launchApp()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
app = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
// MARK: - App Launch
|
||||
|
||||
func testAppLaunches() {
|
||||
// App should show either login screen or main tab view
|
||||
let loginScreen = LoginScreen(app: app)
|
||||
let mainScreen = MainTabScreen(app: app)
|
||||
|
||||
let loginAppeared = loginScreen.emailField.waitForExistence(timeout: 15)
|
||||
let mainAppeared = mainScreen.residencesTab.waitForExistence(timeout: 5)
|
||||
|
||||
XCTAssertTrue(loginAppeared || mainAppeared, "App should show login or main screen on launch")
|
||||
}
|
||||
|
||||
// MARK: - Login Screen Elements
|
||||
|
||||
func testLoginScreenElements() {
|
||||
let login = LoginScreen(app: app)
|
||||
guard login.emailField.waitForExistence(timeout: 15) else {
|
||||
// Already logged in, skip this test
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertTrue(login.emailField.exists, "Email field should exist")
|
||||
XCTAssertTrue(login.passwordField.exists, "Password field should exist")
|
||||
XCTAssertTrue(login.loginButton.exists, "Login button should exist")
|
||||
}
|
||||
|
||||
// MARK: - Login Flow
|
||||
|
||||
func testLoginWithExistingCredentials() {
|
||||
let login = LoginScreen(app: app)
|
||||
guard login.emailField.waitForExistence(timeout: 15) else {
|
||||
// Already on main screen - verify tabs
|
||||
let main = MainTabScreen(app: app)
|
||||
XCTAssertTrue(main.isDisplayed, "Main tabs should be visible")
|
||||
return
|
||||
}
|
||||
|
||||
// Login with the known test user
|
||||
let user = TestFixtures.TestUser.existing
|
||||
login.login(email: user.email, password: user.password)
|
||||
|
||||
let main = MainTabScreen(app: app)
|
||||
XCTAssertTrue(main.residencesTab.waitForExistence(timeout: 15), "Should navigate to main screen after login")
|
||||
}
|
||||
|
||||
// MARK: - Tab Navigation
|
||||
|
||||
func testMainTabsExistAfterLogin() {
|
||||
let login = LoginScreen(app: app)
|
||||
if login.emailField.waitForExistence(timeout: 15) {
|
||||
// Need to login first
|
||||
let user = TestFixtures.TestUser.existing
|
||||
login.login(email: user.email, password: user.password)
|
||||
}
|
||||
|
||||
let main = MainTabScreen(app: app)
|
||||
guard main.residencesTab.waitForExistence(timeout: 15) else {
|
||||
XCTFail("Main screen did not appear")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertTrue(main.residencesTab.exists, "Residences tab should exist")
|
||||
XCTAssertTrue(main.tasksTab.exists, "Tasks tab should exist")
|
||||
XCTAssertTrue(main.contractorsTab.exists, "Contractors tab should exist")
|
||||
XCTAssertTrue(main.documentsTab.exists, "Documents tab should exist")
|
||||
XCTAssertTrue(main.profileTab.exists, "Profile tab should exist")
|
||||
}
|
||||
|
||||
func testTabNavigation() {
|
||||
let login = LoginScreen(app: app)
|
||||
if login.emailField.waitForExistence(timeout: 15) {
|
||||
let user = TestFixtures.TestUser.existing
|
||||
login.login(email: user.email, password: user.password)
|
||||
}
|
||||
|
||||
let main = MainTabScreen(app: app)
|
||||
guard main.residencesTab.waitForExistence(timeout: 15) else {
|
||||
XCTFail("Main screen did not appear")
|
||||
return
|
||||
}
|
||||
|
||||
// Navigate through each tab and verify selection
|
||||
main.goToTasks()
|
||||
XCTAssertTrue(main.tasksTab.isSelected, "Tasks tab should be selected")
|
||||
|
||||
main.goToContractors()
|
||||
XCTAssertTrue(main.contractorsTab.isSelected, "Contractors tab should be selected")
|
||||
|
||||
main.goToDocuments()
|
||||
XCTAssertTrue(main.documentsTab.isSelected, "Documents tab should be selected")
|
||||
|
||||
main.goToProfile()
|
||||
XCTAssertTrue(main.profileTab.isSelected, "Profile tab should be selected")
|
||||
|
||||
main.goToResidences()
|
||||
XCTAssertTrue(main.residencesTab.isSelected, "Residences tab should be selected")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user