From 7d0ad3461ad117f92c260c50fc96c56e6ad90576 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sat, 11 Jan 2025 03:24:22 +0100 Subject: [PATCH] Implemented the "exists(at: )" function for the FileService service in the module target. --- Sources/Library/Protocols/FileServicing.swift | 18 +++++- Sources/Library/Services/FileService.swift | 38 ++++++++++--- Tests/Library/Services/FileServiceTests.swift | 57 +++++++++++++++++-- 3 files changed, 98 insertions(+), 15 deletions(-) diff --git a/Sources/Library/Protocols/FileServicing.swift b/Sources/Library/Protocols/FileServicing.swift index 55dc203..cff10db 100644 --- a/Sources/Library/Protocols/FileServicing.swift +++ b/Sources/Library/Protocols/FileServicing.swift @@ -1,9 +1,23 @@ import Foundation -protocol FileServicing { +public protocol FileServicing { - // MARK: Properties + // MARK: Computed var currentFolder: URL { get async } + // MARK: Functions + + func exists(at url: URL) async throws (FileServiceError) -> Bool + +} + +// MARK: - Errors + +public enum FileServiceError: Error, Equatable { + case folderNotCreated + case folderNotDeleted + case urlAlreadyExists + case urlNotExists + case urlNotFileURL } diff --git a/Sources/Library/Services/FileService.swift b/Sources/Library/Services/FileService.swift index a81b2ce..4c164e7 100644 --- a/Sources/Library/Services/FileService.swift +++ b/Sources/Library/Services/FileService.swift @@ -1,6 +1,6 @@ import Foundation -struct FileService: FileServicing { +public struct FileService: FileServicing { // MARK: Properties @@ -8,19 +8,41 @@ struct FileService: FileServicing { // MARK: Initialisers - init(fileManager: FileManager = .default) { + public init(fileManager: FileManager = .default) { self.fileManager = fileManager } // MARK: Computed - var currentFolder: URL { + public var currentFolder: URL { get async { - if #available(macOS 13.0, *) { - .init(filePath: fileManager.currentDirectoryPath) - } else { - .init(fileURLWithPath: fileManager.currentDirectoryPath) - } + .init(at: fileManager.currentDirectoryPath) + } + } + + public func exists(at url: URL) async throws (FileServiceError) -> Bool { + guard url.isFileURL else { + throw FileServiceError.urlNotFileURL + } + + let filePath = getPath(for: url) + + return fileManager.fileExists(atPath: filePath) + } + +} + +// MARK: - Helpers + +private extension FileService { + + // MARK: Functions + + func getPath(for url: URL) -> String { + if #available(macOS 13.0, *) { + return url.path() + } else { + return url.path } } diff --git a/Tests/Library/Services/FileServiceTests.swift b/Tests/Library/Services/FileServiceTests.swift index 01878a2..7dde431 100644 --- a/Tests/Library/Services/FileServiceTests.swift +++ b/Tests/Library/Services/FileServiceTests.swift @@ -1,22 +1,69 @@ +import Foundation import Testing @testable import ColibriLibrary struct FileServiceTests { + + // MARK: Properties + + private let service: FileServicing + + // MARK: Initialisers + + init() { + self.service = FileService() + } // MARK: Properties tests - @Test("Test the file service provides a current folder URL") - func currentFolder() async { + @Test func currentFolder() async { // GIVEN - let service = FileService() - // WHEN let url = await service.currentFolder // THEN - #expect(url.path() == "/private/tmp") + #expect(url == .someExistingFolder) #expect(url.isFileURL == true) } + // GIVEN + // WHEN + // THEN + } + + @Test(arguments: zip([URL.someExistingFolder, .someExistingFile, .someNonExistingFolder, .someNonExistingFile], + [true, true, false, false])) + func exists( + with url: URL, + expects outcome: Bool + ) async throws { + // GIVEN + // WHEN + let result = try await service.exists(at: url) + + // THEN + #expect(result == outcome) + } + + @Test func existsThrows() async throws { + // GIVEN + let url = URL.someRandomURL + + // WHEN + // THEN + await #expect(throws: FileServiceError.urlNotFileURL) { + try await service.exists(at: url) + } + } } + +// MARK: - URL+Constants + +private extension URL { + static let someExistingFolder = URL(at: "/private/tmp") + static let someExistingFile = URL(at: "/etc/null") + static let someNonExistingFolder = URL(at: "/some/random/folder") + static let someNonExistingFile = URL(at: "/some/random/file.ext") + static let someRandomURL = URL(string: "https://some.random.url")! +}