- Add Apple Sign-In backend (JWKS verification, account linking, session management) - Implement push notification deep linking with NotificationDeepLinkRouter - Add jailbreak detection, runtime integrity monitoring, secure enclave service - Implement OAuth social login, token refresh, and secure logout flows - Add image caching (memory/disk), optimizer, upload queue, async semaphore - Implement notification analytics, type preferences, and category setup - Expand UI test suite with UITestBase, accessibility, auth flow, performance tests - Add CI pipeline for iOS UI tests (3 device sizes) and performance benchmarks - Restructure Xcode project to manual groups with KordantWidgets target - Add SwiftLint, Swift Collections/Algorithms/GoogleSignIn dependencies - Update project.yml for XcodeGen with new targets and configurations
130 lines
4.8 KiB
Swift
130 lines
4.8 KiB
Swift
import XCTest
|
|
|
|
/// UI tests for the dashboard: widgets, alerts, threat score, navigation.
|
|
final class DashboardUITests: UITestBase {
|
|
override class var scenario: UITestScenario { .populatedDashboard }
|
|
|
|
// MARK: - Dashboard Loads with Widgets
|
|
|
|
/// Verify the dashboard loads with all widget sections
|
|
func testDashboardLoadsWithWidgets() {
|
|
// Navigate to Dashboard tab (should be default)
|
|
navigateToTab(.dashboard)
|
|
|
|
// Verify key dashboard elements exist
|
|
XCTAssertTrue(app.navigationBars["Dashboard"].waitForExistence(timeout: 5),
|
|
"Dashboard navigation bar should exist")
|
|
|
|
// Threat score section
|
|
let threatScoreLabel = text("Threat Score")
|
|
XCTAssertTrue(threatScoreLabel.waitForExistence(timeout: 3),
|
|
"Threat Score label should be visible")
|
|
XCTAssertTrue(text("Alerts").exists, "Alerts stat badge should be visible")
|
|
XCTAssertTrue(text("Exposures").exists, "Exposures stat badge should be visible")
|
|
XCTAssertTrue(text("Watched").exists, "Watched stat badge should be visible")
|
|
|
|
// Recent Alerts section
|
|
XCTAssertTrue(text("Recent Alerts").waitForExistence(timeout: 3),
|
|
"Recent Alerts section should be visible")
|
|
|
|
// Services section
|
|
XCTAssertTrue(text("Services").exists, "Services section should be visible")
|
|
|
|
// Quick Actions section
|
|
XCTAssertTrue(text("Quick Actions").exists, "Quick Actions section should be visible")
|
|
|
|
captureScreen(name: "DashboardWithWidgets")
|
|
}
|
|
|
|
// MARK: - Alert Tap Opens Detail View
|
|
|
|
/// Verify tapping an alert navigates to the detail view
|
|
func testTapAlertOpensDetailView() {
|
|
navigateToTab(.dashboard)
|
|
|
|
// Wait for alerts to load
|
|
let alertTitle = text("Data Exposure Detected")
|
|
guard alertTitle.waitForExistence(timeout: 5) else {
|
|
XCTFail("Expected alert 'Data Exposure Detected' not found")
|
|
return
|
|
}
|
|
|
|
// Tap the alert (it's inside a NavigationLink)
|
|
alertTitle.tap()
|
|
|
|
// Should navigate to alert detail (the navigation bar title changes)
|
|
let detailExists = app.navigationBars.element(boundBy: 0).waitForExistence(timeout: 3)
|
|
XCTAssertTrue(detailExists, "Alert detail view should open")
|
|
|
|
captureScreen(name: "AlertDetail")
|
|
}
|
|
|
|
// MARK: - Threat Score Display
|
|
|
|
/// Verify threat score displays and updates correctly
|
|
func testThreatScoreUpdatesCorrectly() {
|
|
navigateToTab(.dashboard)
|
|
|
|
// With populatedDashboard scenario, we have mock alerts and exposures
|
|
// The threat score should be visible
|
|
let scoreExists = app.staticTexts.matching(NSPredicate(format: "label MATCHES '\\\\d+'")).element.exists
|
|
XCTAssertTrue(scoreExists || app.staticTexts["0"].exists || app.staticTexts["100"].exists,
|
|
"Threat score number should be visible")
|
|
}
|
|
|
|
// MARK: - Services Section on Dashboard
|
|
|
|
/// Verify the services grid is visible on dashboard
|
|
func testDashboardShowsServiceSummaries() {
|
|
navigateToTab(.dashboard)
|
|
|
|
// The services grid should show all 5 service names
|
|
let serviceNames = ["DarkWatch", "VoicePrint", "SpamShield", "HomeTitle", "RemoveBrokers"]
|
|
for name in serviceNames {
|
|
XCTAssertTrue(text(name).exists, "Service '\(name)' should be visible on dashboard")
|
|
}
|
|
}
|
|
|
|
// MARK: - Quick Actions
|
|
|
|
/// Verify quick action buttons are present
|
|
func testQuickActionsAreVisible() {
|
|
navigateToTab(.dashboard)
|
|
|
|
// Scroll down to make sure Quick Actions are visible
|
|
scrollDown()
|
|
|
|
let quickActions = ["Scan", "Alerts", "Profile", "Settings"]
|
|
for action in quickActions {
|
|
XCTAssertTrue(text(action).exists, "Quick action '\(action)' should be visible")
|
|
}
|
|
}
|
|
|
|
// MARK: - Dashboard Tab Navigation
|
|
|
|
/// Verify tab bar navigation works from dashboard
|
|
func testTabNavigationFromDashboard() {
|
|
navigateToTab(.dashboard)
|
|
|
|
// Navigate to Services tab
|
|
navigateToTab(.services)
|
|
XCTAssertTrue(app.navigationBars["Services"].waitForExistence(timeout: 3),
|
|
"Services screen should appear")
|
|
|
|
// Navigate back to Dashboard
|
|
navigateToTab(.dashboard)
|
|
XCTAssertTrue(app.navigationBars["Dashboard"].waitForExistence(timeout: 3),
|
|
"Dashboard should appear after switching back")
|
|
|
|
// Navigate to Alerts tab
|
|
navigateToTab(.alerts)
|
|
XCTAssertTrue(app.navigationBars["Alerts"].waitForExistence(timeout: 3),
|
|
"Alerts screen should appear")
|
|
|
|
// Navigate to Settings tab
|
|
navigateToTab(.settings)
|
|
XCTAssertTrue(app.navigationBars["Settings"].waitForExistence(timeout: 3),
|
|
"Settings screen should appear")
|
|
}
|
|
}
|