import Foundation import Testing @testable import Kanban /// **Where app-side state lives** (`AppStateHome`; 02-architecture.md § Per-board app state, /// "App-wide state has the same home"; 12-editions.md ▸ App-side state, re-ruled 2026-07-30 — one /// app, one sandbox, one home). /// /// Two claims, and they are the only two this type makes: the three file stores are neighbours under /// one directory the app can actually create, and a **unit-test host never resolves to the real /// one**. The second is not a nicety — the test host *is* the app, so `KanbanApp.init()` runs for /// real on every test launch, and a home that pointed at the developer's own state would have the /// host's launch sweep collecting real staged clipboard trees and its recents refresh rewriting real /// records. There is no injection point in `App.init` to fix that from outside. @MainActor @Suite("App state home") struct AppStateHomeTests { @Test("Every app-side store resolves under one state directory, and it is creatable") func stateDirectoryIsOneHomeAndAlwaysUsable() throws { let home = AppStateHome.directory // The registry, the clipboard's staging store and the template store are one another's // neighbours by design, and each names the home rather than spelling a path — so this is the // assertion that keeps them moving together the day the home moves. #expect(BoardRegistry.defaultStorageURL.deletingLastPathComponent() == home) #expect(ClipboardStore.defaultStagingRoot.deletingLastPathComponent() == home) #expect(TemplateEngine.userStore.deletingLastPathComponent() == home) // And it is a directory the app can actually create, which is the one property that has to // hold whichever side of the test-host redirect this is running on. try FileManager.default.createDirectory(at: home, withIntermediateDirectories: true) #expect(FileManager.default.fileExists(atPath: home.path)) } @Test("A unit-test host never resolves to the real Application Support home") func aTestHostIsRedirected() { // This suite is running, so this *is* a test host — and the point of the check is that the // two defaults every launch reaches for (the registry file, the staging root) cannot land in // the home the developer's own running copy uses. #expect(AppStateHome.isUnitTestHost) #expect(AppStateHome.directory == AppStateHome.unitTestDirectory) #expect(AppStateHome.directory != AppStateHome.productionDirectory) } @Test("The production home is Application Support itself, with no bundle-id subfolder appended") func productionHomeHasNoBundleIDSubfolder() { // The sandbox already scopes `Application Support` to this app — that container path is the // one place the bundle id belongs — so a subfolder appended *inside* it would name the app // twice. The last component is therefore the check: what this type adds is nothing. #expect(AppStateHome.productionDirectory.lastPathComponent == "Application Support") } }