169 lines
6.2 KiB
Swift
169 lines
6.2 KiB
Swift
import Foundation
|
|
import Testing
|
|
import ShotdeckCore
|
|
|
|
@Test
|
|
func resolveWithoutStoredKeysReturnsDesktopAndDownloads() throws {
|
|
let suite = try makeDefaultsSuite()
|
|
defer { tearDown(suite) }
|
|
|
|
let resolved = FolderSettings.resolve(defaults: suite.defaults)
|
|
let expectedOutbox = try #require(
|
|
FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first
|
|
)
|
|
let expectedWatch = try #require(
|
|
FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first
|
|
)
|
|
|
|
#expect(resolved.outbox.path == expectedOutbox.path)
|
|
#expect(resolved.watch.path == expectedWatch.path)
|
|
}
|
|
|
|
@Test
|
|
func setOutboxToAnExistingDirectoryIsReturnedByResolve() throws {
|
|
let suite = try makeDefaultsSuite()
|
|
defer { tearDown(suite) }
|
|
let outbox = try makeTemporaryDirectory(prefix: "shotdeck-outbox-set")
|
|
defer { try? FileManager.default.removeItem(at: outbox) }
|
|
|
|
FolderSettings.setOutbox(outbox, defaults: suite.defaults)
|
|
let resolved = FolderSettings.resolve(defaults: suite.defaults)
|
|
let expectedWatch = try #require(
|
|
FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first
|
|
)
|
|
|
|
#expect(resolved.outbox.path == outbox.path)
|
|
#expect(resolved.watch.path == expectedWatch.path)
|
|
#expect(FolderSettings.storedOutboxPath(defaults: suite.defaults) == outbox.path)
|
|
}
|
|
|
|
@Test
|
|
func resolveFallsBackWhenTheStoredOutboxDirectoryIsGone() throws {
|
|
let suite = try makeDefaultsSuite()
|
|
defer { tearDown(suite) }
|
|
let outbox = try makeTemporaryDirectory(prefix: "shotdeck-outbox-gone")
|
|
|
|
FolderSettings.setOutbox(outbox, defaults: suite.defaults)
|
|
try FileManager.default.removeItem(at: outbox)
|
|
|
|
let resolved = FolderSettings.resolve(defaults: suite.defaults)
|
|
let expectedOutbox = try #require(
|
|
FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first
|
|
)
|
|
#expect(resolved.outbox.path == expectedOutbox.path)
|
|
}
|
|
|
|
@Test
|
|
func setWatchFolderMirrorsOutboxOverrideAndFallbackIndependently() throws {
|
|
let suite = try makeDefaultsSuite()
|
|
defer { tearDown(suite) }
|
|
let watch = try makeTemporaryDirectory(prefix: "shotdeck-watch-set")
|
|
let expectedOutbox = try #require(
|
|
FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first
|
|
)
|
|
|
|
FolderSettings.setWatchFolder(watch, defaults: suite.defaults)
|
|
let withOverride = FolderSettings.resolve(defaults: suite.defaults)
|
|
#expect(withOverride.watch.path == watch.path)
|
|
#expect(withOverride.outbox.path == expectedOutbox.path)
|
|
|
|
try FileManager.default.removeItem(at: watch)
|
|
let afterDelete = FolderSettings.resolve(defaults: suite.defaults)
|
|
let expectedWatch = try #require(
|
|
FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first
|
|
)
|
|
#expect(afterDelete.watch.path == expectedWatch.path)
|
|
#expect(afterDelete.outbox.path == expectedOutbox.path)
|
|
}
|
|
|
|
@Test
|
|
func resetOutboxClearsTheOverride() throws {
|
|
let suite = try makeDefaultsSuite()
|
|
defer { tearDown(suite) }
|
|
let outbox = try makeTemporaryDirectory(prefix: "shotdeck-outbox-reset")
|
|
defer { try? FileManager.default.removeItem(at: outbox) }
|
|
|
|
FolderSettings.setOutbox(outbox, defaults: suite.defaults)
|
|
FolderSettings.resetOutbox(defaults: suite.defaults)
|
|
|
|
let resolved = FolderSettings.resolve(defaults: suite.defaults)
|
|
let expectedOutbox = try #require(
|
|
FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first
|
|
)
|
|
#expect(resolved.outbox.path == expectedOutbox.path)
|
|
#expect(FolderSettings.storedOutboxPath(defaults: suite.defaults) == nil)
|
|
}
|
|
|
|
@Test
|
|
func resolvedAppSupportPathsUsesTheOutboxOverrideAndCreatesSpoolArchive() throws {
|
|
let suite = try makeDefaultsSuite()
|
|
defer { tearDown(suite) }
|
|
let root = try makeTemporaryDirectory(prefix: "shotdeck-paths-root")
|
|
let outbox = try makeTemporaryDirectory(prefix: "shotdeck-paths-outbox")
|
|
defer {
|
|
try? FileManager.default.removeItem(at: root)
|
|
try? FileManager.default.removeItem(at: outbox)
|
|
}
|
|
|
|
FolderSettings.setOutbox(outbox, defaults: suite.defaults)
|
|
let paths = try FolderSettings.resolvedAppSupportPaths(root: root, defaults: suite.defaults)
|
|
|
|
#expect(paths.outbox.path == outbox.path)
|
|
#expect(directoryExists(paths.spool))
|
|
#expect(directoryExists(paths.archive))
|
|
#expect(paths.spool.deletingLastPathComponent().path == root.path)
|
|
#expect(paths.archive.deletingLastPathComponent().path == root.path)
|
|
}
|
|
|
|
@Test
|
|
func userDefaultsSuitesDoNotLeakFolderOverrides() throws {
|
|
let suiteA = try makeDefaultsSuite()
|
|
let suiteB = try makeDefaultsSuite()
|
|
defer {
|
|
tearDown(suiteA)
|
|
tearDown(suiteB)
|
|
}
|
|
let outbox = try makeTemporaryDirectory(prefix: "shotdeck-suite-a-outbox")
|
|
defer { try? FileManager.default.removeItem(at: outbox) }
|
|
|
|
FolderSettings.setOutbox(outbox, defaults: suiteA.defaults)
|
|
|
|
let resolvedA = FolderSettings.resolve(defaults: suiteA.defaults)
|
|
let resolvedB = FolderSettings.resolve(defaults: suiteB.defaults)
|
|
let expectedOutbox = try #require(
|
|
FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first
|
|
)
|
|
|
|
#expect(resolvedA.outbox.path == outbox.path)
|
|
#expect(resolvedB.outbox.path == expectedOutbox.path)
|
|
}
|
|
|
|
private struct DefaultsSuite {
|
|
let name: String
|
|
let defaults: UserDefaults
|
|
}
|
|
|
|
private func makeDefaultsSuite() throws -> DefaultsSuite {
|
|
let name = "shotdeck-test-\(UUID().uuidString)"
|
|
let defaults = try #require(UserDefaults(suiteName: name))
|
|
defaults.removePersistentDomain(forName: name)
|
|
return DefaultsSuite(name: name, defaults: defaults)
|
|
}
|
|
|
|
private func tearDown(_ suite: DefaultsSuite) {
|
|
suite.defaults.removePersistentDomain(forName: suite.name)
|
|
}
|
|
|
|
private func makeTemporaryDirectory(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
|
|
}
|
|
|
|
private func directoryExists(_ url: URL) -> Bool {
|
|
var isDirectory: ObjCBool = false
|
|
let exists = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory)
|
|
return exists && isDirectory.boolValue
|
|
}
|