Files
Kordant/iOS/KordantTests/WidgetDataTests.swift
Michael Freno e33ddf3002 feat: complete Tasks 21-28 — backend integration, security hardening, UI tests & CI
- 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
2026-06-02 15:01:38 -04:00

230 lines
8.2 KiB
Swift

import XCTest
@testable import Kordant
final class WidgetDataTests: XCTestCase {
// MARK: - Encoding / Decoding
func testWidgetDataEncodingDecoding() throws {
let original = WidgetData(
threatScore: 0.42,
recentAlerts: [
WidgetAlert(
id: "test-1",
title: "Test Alert",
message: "Test message",
severity: "high",
type: "breach",
createdAt: Date()
)
],
alertCount: 1,
unreadCount: 1,
criticalCount: 0,
exposureCount: 2,
lastUpdated: Date()
)
let encoded = try JSONEncoder().encode(original)
let decoded = try JSONDecoder().decode(WidgetData.self, from: encoded)
XCTAssertEqual(original, decoded)
XCTAssertEqual(decoded.threatScore, 0.42)
XCTAssertEqual(decoded.alertCount, 1)
XCTAssertEqual(decoded.unreadCount, 1)
XCTAssertEqual(decoded.criticalCount, 0)
XCTAssertEqual(decoded.exposureCount, 2)
XCTAssertEqual(decoded.recentAlerts.count, 1)
XCTAssertEqual(decoded.recentAlerts[0].id, "test-1")
XCTAssertEqual(decoded.recentAlerts[0].title, "Test Alert")
XCTAssertEqual(decoded.recentAlerts[0].severity, "high")
}
// MARK: - Threat Level
func testThreatLevelLow() {
let data = WidgetData(
threatScore: 0.15,
recentAlerts: [],
alertCount: 0,
unreadCount: 0,
criticalCount: 0,
exposureCount: 0,
lastUpdated: Date()
)
XCTAssertEqual(data.threatLevel, .low)
}
func testThreatLevelMedium() {
let data = WidgetData(
threatScore: 0.25,
recentAlerts: [],
alertCount: 0,
unreadCount: 0,
criticalCount: 0,
exposureCount: 0,
lastUpdated: Date()
)
XCTAssertEqual(data.threatLevel, .medium)
}
func testThreatLevelHigh() {
let data = WidgetData(
threatScore: 0.45,
recentAlerts: [],
alertCount: 0,
unreadCount: 0,
criticalCount: 0,
exposureCount: 0,
lastUpdated: Date()
)
XCTAssertEqual(data.threatLevel, .high)
}
func testThreatLevelCritical() {
let data = WidgetData(
threatScore: 0.72,
recentAlerts: [],
alertCount: 0,
unreadCount: 0,
criticalCount: 0,
exposureCount: 0,
lastUpdated: Date()
)
XCTAssertEqual(data.threatLevel, .critical)
}
func testThreatLevelBoundaries() {
// Exactly 0.2 is medium
let mediumLow = WidgetData(threatScore: 0.2, recentAlerts: [], alertCount: 0, unreadCount: 0, criticalCount: 0, exposureCount: 0, lastUpdated: Date())
XCTAssertEqual(mediumLow.threatLevel, .medium)
// Exactly 0.4 is high
let highLow = WidgetData(threatScore: 0.4, recentAlerts: [], alertCount: 0, unreadCount: 0, criticalCount: 0, exposureCount: 0, lastUpdated: Date())
XCTAssertEqual(highLow.threatLevel, .high)
// Exactly 0.7 is critical
let criticalLow = WidgetData(threatScore: 0.7, recentAlerts: [], alertCount: 0, unreadCount: 0, criticalCount: 0, exposureCount: 0, lastUpdated: Date())
XCTAssertEqual(criticalLow.threatLevel, .critical)
}
// MARK: - Threat Percentage
func testThreatPercentage() {
let data = WidgetData(threatScore: 0.35, recentAlerts: [], alertCount: 0, unreadCount: 0, criticalCount: 0, exposureCount: 0, lastUpdated: Date())
XCTAssertEqual(data.threatPercentage, 35)
let data2 = WidgetData(threatScore: 1.0, recentAlerts: [], alertCount: 0, unreadCount: 0, criticalCount: 0, exposureCount: 0, lastUpdated: Date())
XCTAssertEqual(data2.threatPercentage, 100)
let data3 = WidgetData(threatScore: 0.0, recentAlerts: [], alertCount: 0, unreadCount: 0, criticalCount: 0, exposureCount: 0, lastUpdated: Date())
XCTAssertEqual(data3.threatPercentage, 0)
}
// MARK: - WidgetAlert
func testWidgetAlertSeverityEnum() {
let critical = WidgetAlert(id: "1", title: "Test", message: "Msg", severity: "critical", type: "breach", createdAt: nil)
XCTAssertEqual(critical.severityEnum, .critical)
let high = WidgetAlert(id: "2", title: "Test", message: "Msg", severity: "high", type: "exposure", createdAt: nil)
XCTAssertEqual(high.severityEnum, .high)
let medium = WidgetAlert(id: "3", title: "Test", message: "Msg", severity: "medium", type: "voiceMatch", createdAt: nil)
XCTAssertEqual(medium.severityEnum, .medium)
let low = WidgetAlert(id: "4", title: "Test", message: "Msg", severity: "low", type: "removal", createdAt: nil)
XCTAssertEqual(low.severityEnum, .low)
// Unknown severity defaults to low
let unknown = WidgetAlert(id: "5", title: "Test", message: "Msg", severity: "unknown", type: "login", createdAt: nil)
XCTAssertEqual(unknown.severityEnum, .low)
}
func testWidgetAlertTypeEnum() {
let breach = WidgetAlert(id: "1", title: "Test", message: "Msg", severity: "low", type: "breach", createdAt: nil)
XCTAssertEqual(breach.typeEnum, .breach)
let exposure = WidgetAlert(id: "2", title: "Test", message: "Msg", severity: "low", type: "exposure", createdAt: nil)
XCTAssertEqual(exposure.typeEnum, .exposure)
}
func testWidgetAlertDeepLink() {
let alert = WidgetAlert(id: "abc-123", title: "Test", message: "Msg", severity: "high", type: "breach", createdAt: nil)
let url = alert.deepLink
XCTAssertEqual(url.absoluteString, "kordant://alerts/abc-123")
}
// MARK: - Placeholder & Unavailable
func testPlaceholderData() {
let placeholder = WidgetData.placeholder
XCTAssertEqual(placeholder.threatScore, 0.25)
XCTAssertEqual(placeholder.alertCount, 5)
XCTAssertEqual(placeholder.recentAlerts.count, 3)
}
func testUnavailableData() {
let unavailable = WidgetData.unavailable
XCTAssertEqual(unavailable.threatScore, 0)
XCTAssertEqual(unavailable.alertCount, 0)
XCTAssertEqual(unavailable.recentAlerts.count, 0)
}
func testPlaceholderAlerts() {
let alerts = WidgetAlert.placeholders
XCTAssertEqual(alerts.count, 3)
XCTAssertEqual(alerts[0].title, "Data Breach Detected")
XCTAssertEqual(alerts[0].severity, "critical")
XCTAssertEqual(alerts[1].severity, "high")
XCTAssertEqual(alerts[2].severity, "medium")
}
// MARK: - Severity Filter
func testSeverityFilterAll() {
let filter = AlertSeverityFilter.all
XCTAssertTrue(filter.matches(severity: "low"))
XCTAssertTrue(filter.matches(severity: "medium"))
XCTAssertTrue(filter.matches(severity: "high"))
XCTAssertTrue(filter.matches(severity: "critical"))
}
func testSeverityFilterCritical() {
let filter = AlertSeverityFilter.critical
XCTAssertFalse(filter.matches(severity: "low"))
XCTAssertFalse(filter.matches(severity: "medium"))
XCTAssertFalse(filter.matches(severity: "high"))
XCTAssertTrue(filter.matches(severity: "critical"))
}
func testSeverityFilterHigh() {
let filter = AlertSeverityFilter.high
XCTAssertFalse(filter.matches(severity: "low"))
XCTAssertFalse(filter.matches(severity: "medium"))
XCTAssertTrue(filter.matches(severity: "high"))
XCTAssertTrue(filter.matches(severity: "critical"))
}
// MARK: - Data Manager (integration)
func testWidgetDataManagerSaveAndLoad() {
let manager = WidgetDataManager.shared
let original = WidgetData.placeholder
// Clear any existing data
manager.clear()
XCTAssertNil(manager.load())
// Save and reload
manager.save(original)
let loaded = manager.load()
XCTAssertNotNil(loaded)
XCTAssertEqual(loaded, original)
XCTAssertEqual(loaded?.threatScore, 0.25)
// Clean up
manager.clear()
XCTAssertNil(manager.load())
}
}