import Foundation import Testing import ShotdeckCore @Test func transportDefaultsToAirDropWhenUnset() throws { let suite = try makeTransportDefaultsSuite() defer { tearDownTransportSuite(suite) } #expect(TransportSettings.transport(defaults: suite.defaults) == .airDrop) } @Test func setTransportRoundTrips() throws { let suite = try makeTransportDefaultsSuite() defer { tearDownTransportSuite(suite) } TransportSettings.setTransport(.oneDrive, defaults: suite.defaults) #expect(TransportSettings.transport(defaults: suite.defaults) == .oneDrive) TransportSettings.setTransport(.airDrop, defaults: suite.defaults) #expect(TransportSettings.transport(defaults: suite.defaults) == .airDrop) } @Test func garbageStoredTransportFallsBackToAirDrop() throws { let suite = try makeTransportDefaultsSuite() defer { tearDownTransportSuite(suite) } suite.defaults.set("not-a-real-transport", forKey: TransportSettings.transportDefaultsKey) #expect(TransportSettings.transport(defaults: suite.defaults) == .airDrop) } @Test func oneDriveFolderStoreAndReset() throws { let suite = try makeTransportDefaultsSuite() defer { tearDownTransportSuite(suite) } let folder = try makeTransportTemporaryDirectory(prefix: "shotdeck-onedrive-folder") defer { try? FileManager.default.removeItem(at: folder) } #expect(TransportSettings.storedOneDriveFolderPath(defaults: suite.defaults) == nil) TransportSettings.setOneDriveFolder(folder, defaults: suite.defaults) #expect(TransportSettings.storedOneDriveFolderPath(defaults: suite.defaults) == folder.path) TransportSettings.resetOneDriveFolder(defaults: suite.defaults) #expect(TransportSettings.storedOneDriveFolderPath(defaults: suite.defaults) == nil) } @Test func effectiveFoldersForAirDropMatchesFolderSettings() throws { let suite = try makeTransportDefaultsSuite() defer { tearDownTransportSuite(suite) } let outbox = try makeTransportTemporaryDirectory(prefix: "shotdeck-effective-outbox") defer { try? FileManager.default.removeItem(at: outbox) } FolderSettings.setOutbox(outbox, defaults: suite.defaults) let effective = TransportSettings.effectiveFolders(defaults: suite.defaults) let expected = FolderSettings.resolve(defaults: suite.defaults) #expect(effective.transport == .airDrop) #expect(effective.outbox.path == expected.outbox.path) #expect(effective.watch.path == expected.watch.path) } @Test func effectiveFoldersForOneDriveWithAResolvableFolderUsesItForBoth() throws { let suite = try makeTransportDefaultsSuite() defer { tearDownTransportSuite(suite) } let folder = try makeTransportTemporaryDirectory(prefix: "shotdeck-effective-onedrive") defer { try? FileManager.default.removeItem(at: folder) } TransportSettings.setTransport(.oneDrive, defaults: suite.defaults) TransportSettings.setOneDriveFolder(folder, defaults: suite.defaults) let effective = TransportSettings.effectiveFolders(defaults: suite.defaults) #expect(effective.transport == .oneDrive) #expect(effective.outbox.path == folder.path) #expect(effective.watch.path == folder.path) #expect(effective.outbox.path == effective.watch.path) } @Test func oneDriveFolderUnavailableErrorDescriptionContainsThePath() throws { let path = "/Users/example/Library/CloudStorage/OneDrive-Example/Redline" let error = ShotdeckError.oneDriveFolderUnavailable(path: path) let description = try #require(error.errorDescription) #expect(!description.isEmpty) #expect(description.contains(path)) } struct TransportDefaultsSuite { let name: String let defaults: UserDefaults } func makeTransportDefaultsSuite() throws -> TransportDefaultsSuite { let name = "shotdeck-transport-test-\(UUID().uuidString)" let defaults = try #require(UserDefaults(suiteName: name)) defaults.removePersistentDomain(forName: name) return TransportDefaultsSuite(name: name, defaults: defaults) } func tearDownTransportSuite(_ suite: TransportDefaultsSuite) { suite.defaults.removePersistentDomain(forName: suite.name) } func makeTransportTemporaryDirectory(prefix: String) throws -> URL { let url = FileManager.default.temporaryDirectory .appendingPathComponent("\(prefix)-\(UUID().uuidString)", isDirectory: true) try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) return url }