diff --git a/Library/Sources/Internal/Controllers/ArchiveController.swift b/Library/Sources/Internal/Controllers/ArchiveController.swift index b5f6b69..606ef99 100644 --- a/Library/Sources/Internal/Controllers/ArchiveController.swift +++ b/Library/Sources/Internal/Controllers/ArchiveController.swift @@ -1,11 +1,33 @@ import Hummingbird +/// A controller that handles struct ArchiveController { + // MARK: Properties + + private let fileService: any FileServicing + private let folderArchives: String + + // MARK: Initialisers + + /// Initialises this controller. + /// - Parameters: + /// - folderArchives: <#folderArchives description#> + /// - fileService: <#fileService description#> + init( + _ folderArchives: String, + fileService: any FileServicing = FileService() + ) { + self.folderArchives = folderArchives + self.fileService = fileService + } + // MARK: Functions + /// Registers the controller to a given router. + /// - Parameter router: A router to register this controller to. func register(to router: Router) { - router.get("archives", use: listAllArchives) + router.get(.archives, use: listAllArchives) } } @@ -19,8 +41,25 @@ private extension ArchiveController { @Sendable func listAllArchives( _ request: Request, context: Context - ) async throws -> HTTPResponse.Status { - .ok + ) async throws -> ArchiveList { + let archives = try await fileService + .listItems(in: folderArchives) + .filter { $0.hasSuffix(.suffixArchive) } + .sorted { $0 < $1 } + + return .init(archives) } } + +// MARK: - RouterPath+Constants + +private extension RouterPath { + static let archives: RouterPath = .init("archives") +} + +// MARK: - String+Constants + +private extension String { + static let suffixArchive: String = ".doccarchive" +} diff --git a/Test/Sources/Cases/Internal/Controllers/ArchiveControllerTests.swift b/Test/Sources/Cases/Internal/Controllers/ArchiveControllerTests.swift new file mode 100644 index 0000000..9c7d351 --- /dev/null +++ b/Test/Sources/Cases/Internal/Controllers/ArchiveControllerTests.swift @@ -0,0 +1,56 @@ +import Foundation +import Hummingbird +import HummingbirdTesting +import Testing + +@testable import DoxyLibrary + +@Suite("ArchiveController", .tags(.controller)) +struct ArchiveControllerTests { + + // MARK: Properties + + private let decoder: JSONDecoder = .init() + + @Test func xxx() async throws { + // GIVEN + let fileService = FileServiceMock(items: ["SomeArchive.doccarchive", "some-file.txt"]) + let router = Router() + + ArchiveController("/path/to/archives/folder", fileService: fileService) + .register(to: router) + + let app = Application(router: router) + + // WHEN + // THEN + try await app.test(.router) { client in + try await client.execute(uri: "/archives", method: .get) { response in + let archiveList = try decoder.decode(ArchiveList.self, from: response.body) + + #expect(response.status == .ok) + #expect(archiveList.archives == ["SomeArchive.doccarchive"]) + } + } + } + + @Test func yyy() async throws { + // GIVEN + let fileService = FileServiceMock(error: .folderNotFound) + let router = Router() + + ArchiveController("/path/to/archives/folder", fileService: fileService) + .register(to: router) + + let app = Application(router: router) + + // WHEN + // THEN + try await app.test(.router) { client in + try await client.execute(uri: "/archives", method: .get) { response in + #expect(response.status == .ok) + } + } + } + +} diff --git a/Test/Sources/Helpers/Extensions/Tag+Definitions.swift b/Test/Sources/Helpers/Extensions/Tag+Definitions.swift index f7ec925..d6b8635 100644 --- a/Test/Sources/Helpers/Extensions/Tag+Definitions.swift +++ b/Test/Sources/Helpers/Extensions/Tag+Definitions.swift @@ -5,6 +5,7 @@ extension Tag { // MARK: Constants @Tag static var builder: Tag + @Tag static var controller: Tag @Tag static var enumeration: Tag @Tag static var middleware: Tag @Tag static var provider: Tag diff --git a/Test/Sources/Helpers/Mocks/FileServiceMock.swift b/Test/Sources/Helpers/Mocks/FileServiceMock.swift new file mode 100644 index 0000000..21caa85 --- /dev/null +++ b/Test/Sources/Helpers/Mocks/FileServiceMock.swift @@ -0,0 +1,36 @@ +@testable import DoxyLibrary + +struct FileServiceMock { + + // MARK: Properties + + private let error: FileServiceError? + private let items: [String] + + // MARK: Initialisers + + init( + items: [String] = [], + error: FileServiceError? = nil + ) { + self.error = error + self.items = items + } + +} + +// MARK: - FileServicing + +extension FileServiceMock: FileServicing { + + // MARK: Functions + + func listItems(in folder: String) async throws(FileServiceError) -> [String] { + if let error { + throw error + } + + return items + } + +}