import Foundation import Hummingbird import HummingbirdTesting import Testing @testable import DoxyLibrary @Suite("ArchiveController", .tags(.controller)) struct ArchiveControllerTests { // MARK: Properties private let decoder: JSONDecoder = .init() // MARK: Controller tests @Test(arguments: zip([[String].folderWithArchives, .folderWithNoArchives, .folderEmpty], [[String].listWithArchives, .listWithNoArchives, .listWithNoArchives])) func getArchives( with archivesInFolder: [String], expects archivesInList: [String] ) async throws { // GIVEN let fileService = FileServiceMock(items: archivesInFolder) let router = Router() ArchiveController(.Path.archivesFolder, fileService: fileService) .register(to: router) let app = Application(router: router) // WHEN // THEN try await app.test(.router) { client in try await client.execute(uri: .Path.archivesResource, method: .get) { response in let archiveList = try decoder.decode(ArchiveList.self, from: response.body) #expect(response.status == .ok) #expect(archiveList.archives == archivesInList) } } } @Test(arguments: zip([FileServiceError].errorFileService, [HTTPResponse.Status].errorResponse)) func getArchives( with errorInFolder: FileServiceError, expects errorResponse: HTTPResponse.Status ) async throws { // GIVEN let fileService = FileServiceMock(error: errorInFolder) let router = Router() ArchiveController(.Path.archivesFolder, fileService: fileService) .register(to: router) let app = Application(router: router) // WHEN // THEN try await app.test(.router) { client in try await client.execute(uri: .Path.archivesResource, method: .get) { response in #expect(response.status == errorResponse) } } } } // MARK: - Collection+String private extension Collection where Element == String { static var folderEmpty: [Element] {[]} static var folderWithArchives: [Element] {[ ".DS_Store", "SomeOtherArchive.doccarchive", "some-text.txt", "some-zipped-file.zip", "SomeArchive.doccarchive", "some-image.png", "AnotherArchive.doccarchive", "some-folder" ]} static var folderWithNoArchives: [Element] {[ ".DS_Store", "some-text.txt", "some-zipped-file.zip", "some-image.png", "some-folder" ]} static var listWithArchives: [Element] {[ "AnotherArchive", "SomeArchive", "SomeOtherArchive" ]} static var listWithNoArchives: [Element] {[]} } // MARK: - Collection+FileServiceError private extension Collection where Element == FileServiceError { static var errorFileService: [Element] {[ .folderPathEmpty, .folderNotFound, .folderNotDirectory, .other(NSError(domain: "", code: 0)) ]} } // MARK: - Collection+HTTPResponseStatus private extension Collection where Element == HTTPResponse.Status { static var errorResponse: [Element] {[ .unprocessableContent, .notFound, .unprocessableContent, .badRequest ]} } // MARK: - String+Constants private extension String { enum Path { static let archivesFolder: String = "/path/to/archives/folder" static let archivesResource: String = "/archives" } }