From f89efc8c5ebcec3e73bd1100cc524f2fbd20fe01 Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Mon, 16 Dec 2024 19:00:42 -0500 Subject: [PATCH] feat: Adds file-client tests. --- Package.swift | 4 ++ Sources/FileClient/FileClient.swift | 47 +++++++------ Tests/FileClientTests/FileClientTests.swift | 67 +++++++++++++++++++ Tests/VaultClientTests/VaultClientTests.swift | 4 +- 4 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 Tests/FileClientTests/FileClientTests.swift diff --git a/Package.swift b/Package.swift index a484696..84702cd 100644 --- a/Package.swift +++ b/Package.swift @@ -91,6 +91,10 @@ let package = Package( .product(name: "DependenciesMacros", package: "swift-dependencies") ] ), + .testTarget( + name: "FileClientTests", + dependencies: ["FileClient", "TestSupport"] + ), .target( name: "PandocClient", dependencies: [ diff --git a/Sources/FileClient/FileClient.swift b/Sources/FileClient/FileClient.swift index c533b6b..021f285 100644 --- a/Sources/FileClient/FileClient.swift +++ b/Sources/FileClient/FileClient.swift @@ -14,11 +14,15 @@ public struct FileClient: Sendable { public var copy: @Sendable (URL, URL) async throws -> Void public var createDirectory: @Sendable (URL) async throws -> Void public var fileExists: @Sendable (URL) -> Bool = { _ in true } - public var findVaultFileInCurrentDirectory: @Sendable () async throws -> URL? + public var findVaultFile: @Sendable (URL) async throws -> URL? public var homeDirectory: @Sendable () -> URL = { URL(filePath: "~/") } public var isDirectory: @Sendable (URL) async throws -> Bool public var load: @Sendable (URL) async throws -> Data public var write: @Sendable (Data, URL) async throws -> Void + + public func findVaultFileInCurrentDirectory() async throws -> URL? { + try await findVaultFile(URL(filePath: "./")) + } } extension FileClient: DependencyKey { @@ -32,8 +36,8 @@ extension FileClient: DependencyKey { try await manager.creatDirectory($0) } fileExists: { url in manager.fileExists(at: url) - } findVaultFileInCurrentDirectory: { - try await manager.findVaultFileInCurrentDirectory() + } findVaultFile: { + try await manager.findVaultFile(in: $0) } homeDirectory: { manager.homeDirectory() } isDirectory: { @@ -62,26 +66,27 @@ struct LiveFileClient: Sendable { manager.fileExists(atPath: url.cleanFilePath) } - func findVaultFileInCurrentDirectory() async throws -> URL? { - let urls = try manager.contentsOfDirectory( - at: URL(filePath: "./"), - includingPropertiesForKeys: nil - ) + func findVaultFile(in url: URL) async throws -> URL? { + guard isDirectory(url) else { return nil } + let urls = try manager.contentsOfDirectory(at: url, includingPropertiesForKeys: nil) - // Check the current directory - if let vault = urls.firstVaultFile { return vault } + guard let vault = urls.firstVaultFile else { + // check subfolders, 1 layer deep. + let subfolders = urls.filter { isDirectory($0) } + for folder in subfolders { + let vault = try manager.contentsOfDirectory( + at: folder, + includingPropertiesForKeys: nil + ) + .firstVaultFile - let subfolders = urls.filter { isDirectory($0) } - - for folder in subfolders { - let files = try manager.contentsOfDirectory( - at: folder, - includingPropertiesForKeys: nil - ) - if let vault = files.firstVaultFile { return vault } + if let vault { return vault } + } + // Didn't find a file. + return nil } - return nil + return vault } func homeDirectory() -> URL { @@ -114,6 +119,8 @@ private extension Array where Element == URL { public extension URL { var cleanFilePath: String { - absoluteString.replacing("file://", with: "") + absoluteString + .replacing("file://", with: "") + .replacing("/private", with: "") } } diff --git a/Tests/FileClientTests/FileClientTests.swift b/Tests/FileClientTests/FileClientTests.swift new file mode 100644 index 0000000..29a298c --- /dev/null +++ b/Tests/FileClientTests/FileClientTests.swift @@ -0,0 +1,67 @@ +import FileClient +import Foundation +import Testing +import TestSupport + +@Suite("FileClientTests") +struct FileClientTests { + + @Test + func createDirectory() async throws { + try await withTemporaryDirectory { url in + let fileClient = FileClient.liveValue + let tempDir = url.appending(path: "temp") + try await fileClient.createDirectory(tempDir) + let isDirectory = try await fileClient.isDirectory(tempDir) + #expect(isDirectory) + } + } + + @Test(arguments: ["vault.yml", "vault.yaml"]) + func findVaultFile(fileName: String) async throws { + try await withTemporaryDirectory { url in + let fileClient = FileClient.liveValue + + let vaultFilePath = url.appending(path: fileName) + try FileManager.default.createFile(atPath: vaultFilePath.cleanFilePath, contents: nil) + let output = try await fileClient.findVaultFile(url)! + + #expect(output.cleanFilePath == vaultFilePath.cleanFilePath) + + let nilWhenFileNotDirectory = try await fileClient.findVaultFile(vaultFilePath) + #expect(nilWhenFileNotDirectory == nil) + } + } + + @Test(arguments: ["vault.yml", "vault.yaml"]) + func findVaultFileNestedInSubfolder(fileName: String) async throws { + try await withTemporaryDirectory { url in + + let fileClient = FileClient.liveValue + let subDir = url.appending(path: "sub") + + try await fileClient.createDirectory(subDir) + + let vaultFilePath = subDir.appending(path: fileName) + try FileManager.default.createFile(atPath: vaultFilePath.cleanFilePath, contents: nil) + let output = try await fileClient.findVaultFile(url)! + + #expect(output.cleanFilePath == vaultFilePath.cleanFilePath) + } + } + + @Test + func findVaultFileReturnsNil() async throws { + try await withTemporaryDirectory { url in + + let fileClient = FileClient.liveValue + let subDir = url.appending(path: "sub") + + try await fileClient.createDirectory(subDir) + + let output = try await fileClient.findVaultFile(url) + + #expect(output == nil) + } + } +} diff --git a/Tests/VaultClientTests/VaultClientTests.swift b/Tests/VaultClientTests/VaultClientTests.swift index 62cde73..8ecbd4f 100644 --- a/Tests/VaultClientTests/VaultClientTests.swift +++ b/Tests/VaultClientTests/VaultClientTests.swift @@ -14,7 +14,7 @@ struct VaultClientTests: TestCase { func decrypt(input: TestOptions) async throws { try await withCapturingCommandClient("decrypt") { $0.configurationClient = .mock(input.configuration) - $0.fileClient.findVaultFileInCurrentDirectory = { URL(filePath: "/vault.yml") } + $0.fileClient.findVaultFile = { _ in URL(filePath: "/vault.yml") } $0.vaultClient = .liveValue } run: { @Dependency(\.vaultClient) var vaultClient @@ -45,7 +45,7 @@ struct VaultClientTests: TestCase { func encrypt(input: TestOptions) async throws { try await withCapturingCommandClient("decrypt") { $0.configurationClient = .mock(input.configuration) - $0.fileClient.findVaultFileInCurrentDirectory = { URL(filePath: "/vault.yml") } + $0.fileClient.findVaultFile = { _ in URL(filePath: "/vault.yml") } $0.vaultClient = .liveValue } run: { @Dependency(\.vaultClient) var vaultClient