// Test-only executable. Receives an isolated fixture credential over stdin. import AppKit import SwiftUI import RastrilloApple import CalendarKit struct Input: Decodable { let origin: URL; let credential: NativeSession; let output: String } @main struct Review { @MainActor static func main() async throws { let input = try JSONDecoder().decode(Input.self, from: FileHandle.standardInput.readDataToEndOfFile()) guard input.origin.host == "127.0.0.1" else { fatalError("Review accepts only an isolated loopback fixture") } let app = NSApplication.shared app.setActivationPolicy(.accessory) let client = NativeHTTP(origin: input.origin, credential: input.credential) let model = CalendarModel() model.date = ISO8601DateFormatter().date(from: "2026-10-24T12:00:00Z")!; await model.load(client) guard model.error.isEmpty else { fatalError("Fixture failed: " + model.error) } let menu = ProcessInfo.processInfo.environment["NATIVE_REVIEW_MENU"] == "1" let view = NSHostingView(rootView: Group { if menu { CalendarMenuView(client: client, model: model) } else { CalendarWorkspace(client: client, model: model, signOut: {}) } }.preferredColorScheme(.light).tint(Color(red: 0.76, green: 0.2, blue: 0.3))) let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: menu ? 380 : 1100, height: menu ? 640 : 800), styleMask: [.titled, .closable, .resizable], backing: .buffered, defer: false) window.appearance = NSAppearance(named: .aqua) window.contentView = view window.center() window.orderFrontRegardless() try await Task.sleep(for: .seconds(2)) func capture(_ output: String) throws { let capture = Process() capture.executableURL = URL(fileURLWithPath: "/usr/sbin/screencapture") capture.arguments = ["-x", "-o", "-l", String(window.windowNumber), output] try capture.run() capture.waitUntilExit() guard capture.terminationStatus == 0 else { fatalError("Window capture failed") } } try capture(input.output) if menu && ProcessInfo.processInfo.environment["NATIVE_REVIEW_DAY_SEQUENCE"] == "1" { // Exercise the same published selection updated by the month buttons, // without reloading: timed day -> all-day event -> empty day. guard model.dayEvents(model.date).contains(where: { !$0.all_day }) else { fatalError("Missing timed fixture") } model.date = model.calendar.date(byAdding: .day, value: 1, to: model.date)! try await Task.sleep(for: .seconds(1)) guard model.dayEvents(model.date).contains(where: { $0.all_day }) else { fatalError("Missing all-day fixture") } try capture(input.output + ".all-day.png") model.date = model.calendar.date(byAdding: .day, value: 1, to: model.date)! try await Task.sleep(for: .seconds(1)) guard model.dayEvents(model.date).isEmpty else { fatalError("Empty day retained events") } try capture(input.output + ".empty.png") } } }