import XCTest @testable import AirAcceptCore final class AirAcceptCoreTests: XCTestCase { func testDefaultConfigAcceptsMatchedAirPlayRequests() { let config = AirAcceptConfig() XCTAssertEqual(config.pollIntervalMilliseconds, 2_500) } func testMatchesEnglishAirPlayPrompt() { let candidate = PromptCandidate( hostProcess: "com.apple.AirPlayUIAgent", texts: ["John's iPhone would like to AirPlay to this Mac."], buttonTitles: ["Decline", "Accept"] ) let match = AirPlayPromptMatcher.match(candidate) XCTAssertEqual(match?.deviceName, "John's iPhone") XCTAssertEqual(match?.acceptButtonTitle, "Accept") XCTAssertEqual(match?.declineButtonTitle, "Decline") } func testMatchesQuotedTraditionalChinesePrompt() { let candidate = PromptCandidate( hostProcess: "com.apple.AirPlayUIAgent", texts: ["「客廳 iPad」想要使用 AirPlay 連線到這台 Mac。"], buttonTitles: ["拒絕", "接受"] ) let match = AirPlayPromptMatcher.match(candidate) XCTAssertEqual(match?.deviceName, "客廳 iPad") XCTAssertEqual(match?.acceptButtonTitle, "接受") XCTAssertEqual(match?.declineButtonTitle, "拒絕") } func testRejectsNonAirPlayAcceptDeclineDialog() { let candidate = PromptCandidate( hostProcess: "com.apple.SecurityAgent", texts: ["A system change requires approval."], buttonTitles: ["Decline", "Accept"] ) XCTAssertNil(AirPlayPromptMatcher.match(candidate)) } func testMatchesAirPlayPromptWithoutDeclineButton() { let candidate = PromptCandidate( hostProcess: "com.apple.AirPlayUIAgent", texts: ["John's iPhone would like to AirPlay to this Mac."], buttonTitles: ["Accept"] ) let match = AirPlayPromptMatcher.match(candidate) XCTAssertEqual(match?.deviceName, "John's iPhone") XCTAssertEqual(match?.acceptButtonTitle, "Accept") XCTAssertNil(match?.declineButtonTitle) } func testRejectsGenericAirPlayTextWithoutConnectionRequest() { let candidate = PromptCandidate( hostProcess: "com.apple.AirPlayUIAgent", texts: ["AirPlay settings are available on this Mac."], buttonTitles: ["Accept"] ) XCTAssertNil(AirPlayPromptMatcher.match(candidate)) } func testConfigStoreCreatesDefaultConfig() throws { let directory = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) let url = directory.appendingPathComponent("config.json") let store = ConfigStore(configURL: url) let config = try store.loadOrCreate() XCTAssertEqual(config, AirAcceptConfig()) XCTAssertTrue(FileManager.default.fileExists(atPath: url.path)) } func testConfigStoreRemovesLegacyKeys() throws { let directory = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) let url = directory.appendingPathComponent("config.json") try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) try Data(""" { "dry_run": false, "fallback_click_visible_airplay_banner": true, "poll_interval_ms": 2500 } """.utf8).write(to: url) let store = ConfigStore(configURL: url) let config = try store.loadOrCreate() let rewrittenConfig = try String(contentsOf: url, encoding: .utf8) XCTAssertEqual(config, AirAcceptConfig()) XCTAssertFalse(rewrittenConfig.contains("dry_run")) XCTAssertFalse(rewrittenConfig.contains("fallback_click_visible_airplay_banner")) XCTAssertTrue(rewrittenConfig.contains("poll_interval_ms")) } }