Improved upon the "listArchives(_: context: )" function for the ArchiveController controller in the library target.
This commit is contained in:
parent
dbb7aeda1b
commit
a14d388321
@ -1,6 +1,6 @@
|
|||||||
import Hummingbird
|
import Hummingbird
|
||||||
|
|
||||||
/// A controller that handles
|
/// A controller type that provides information about the *DocC* archives containers.
|
||||||
struct ArchiveController<Context: RequestContext> {
|
struct ArchiveController<Context: RequestContext> {
|
||||||
|
|
||||||
// MARK: Properties
|
// MARK: Properties
|
||||||
@ -12,8 +12,8 @@ struct ArchiveController<Context: RequestContext> {
|
|||||||
|
|
||||||
/// Initialises this controller.
|
/// Initialises this controller.
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - folderArchives: <#folderArchives description#>
|
/// - folderArchives: A folder in the file system where the *DocC* archive contained are located.
|
||||||
/// - fileService: <#fileService description#>
|
/// - fileService: A service that interfaces with the local file system.
|
||||||
init(
|
init(
|
||||||
_ folderArchives: String,
|
_ folderArchives: String,
|
||||||
fileService: any FileServicing = FileService()
|
fileService: any FileServicing = FileService()
|
||||||
@ -27,7 +27,7 @@ struct ArchiveController<Context: RequestContext> {
|
|||||||
/// Registers the controller to a given router.
|
/// Registers the controller to a given router.
|
||||||
/// - Parameter router: A router to register this controller to.
|
/// - Parameter router: A router to register this controller to.
|
||||||
func register(to router: Router<Context>) {
|
func register(to router: Router<Context>) {
|
||||||
router.get(.archives, use: listAllArchives)
|
router.get(.archives, use: listArchives)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -38,16 +38,26 @@ private extension ArchiveController {
|
|||||||
|
|
||||||
// MARK: Functions
|
// MARK: Functions
|
||||||
|
|
||||||
@Sendable func listAllArchives(
|
@Sendable func listArchives(
|
||||||
_ request: Request,
|
_ request: Request,
|
||||||
context: Context
|
context: Context
|
||||||
) async throws -> ArchiveList {
|
) async throws (HTTPError) -> ArchiveList {
|
||||||
let archives = try await fileService
|
do {
|
||||||
|
let nameArchives = try await fileService
|
||||||
.listItems(in: folderArchives)
|
.listItems(in: folderArchives)
|
||||||
.filter { $0.hasSuffix(.suffixArchive) }
|
.filter { $0.hasSuffix(.suffixArchive) }
|
||||||
|
.map { $0.dropLast(String.suffixArchive.count) }
|
||||||
|
.map(String.init)
|
||||||
.sorted { $0 < $1 }
|
.sorted { $0 < $1 }
|
||||||
|
|
||||||
return .init(archives)
|
return .init(nameArchives)
|
||||||
|
} catch .folderNotFound {
|
||||||
|
throw .init(.notFound)
|
||||||
|
} catch .folderPathEmpty, .folderNotDirectory {
|
||||||
|
throw .init(.unprocessableContent)
|
||||||
|
} catch {
|
||||||
|
throw .init(.badRequest)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/// A type that services access to information from the local file system.
|
/// A type that interfaces with the local file system.
|
||||||
protocol FileServicing: Sendable {
|
protocol FileServicing: Sendable {
|
||||||
|
|
||||||
// MARK: Functions
|
// MARK: Functions
|
||||||
|
|
||||||
/// Lists the names of items located at a given folder. path
|
/// Lists the names of items located at a given folder path. in the local file system.
|
||||||
/// - Parameter folder: A path to a folder that could be found in the local file system.
|
/// - Parameter folder: A path to a folder that could be found in the local file system.
|
||||||
/// - Returns: A list of names related to the items retrieved from a given folder path.
|
/// - Returns: A list of names related to the items retrieved from a given folder path.
|
||||||
/// - Throws: A ``FileServiceError`` error type in case any error happens while retrieving the list.
|
/// - Throws: A ``FileServiceError`` error type in case any error happens while retrieving the list.
|
||||||
|
@ -12,12 +12,19 @@ struct ArchiveControllerTests {
|
|||||||
|
|
||||||
private let decoder: JSONDecoder = .init()
|
private let decoder: JSONDecoder = .init()
|
||||||
|
|
||||||
@Test func xxx() async throws {
|
// 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
|
// GIVEN
|
||||||
let fileService = FileServiceMock(items: ["SomeArchive.doccarchive", "some-file.txt"])
|
let fileService = FileServiceMock(items: archivesInFolder)
|
||||||
let router = Router()
|
let router = Router()
|
||||||
|
|
||||||
ArchiveController("/path/to/archives/folder", fileService: fileService)
|
ArchiveController(.Path.archivesFolder, fileService: fileService)
|
||||||
.register(to: router)
|
.register(to: router)
|
||||||
|
|
||||||
let app = Application(router: router)
|
let app = Application(router: router)
|
||||||
@ -25,21 +32,26 @@ struct ArchiveControllerTests {
|
|||||||
// WHEN
|
// WHEN
|
||||||
// THEN
|
// THEN
|
||||||
try await app.test(.router) { client in
|
try await app.test(.router) { client in
|
||||||
try await client.execute(uri: "/archives", method: .get) { response in
|
try await client.execute(uri: .Path.archivesResource, method: .get) { response in
|
||||||
let archiveList = try decoder.decode(ArchiveList.self, from: response.body)
|
let archiveList = try decoder.decode(ArchiveList.self, from: response.body)
|
||||||
|
|
||||||
#expect(response.status == .ok)
|
#expect(response.status == .ok)
|
||||||
#expect(archiveList.archives == ["SomeArchive.doccarchive"])
|
#expect(archiveList.archives == archivesInList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test func yyy() async throws {
|
@Test(arguments: zip([FileServiceError].errorFileService,
|
||||||
|
[HTTPResponse.Status].errorResponse))
|
||||||
|
func getArchives(
|
||||||
|
with errorInFolder: FileServiceError,
|
||||||
|
expects errorResponse: HTTPResponse.Status
|
||||||
|
) async throws {
|
||||||
// GIVEN
|
// GIVEN
|
||||||
let fileService = FileServiceMock(error: .folderNotFound)
|
let fileService = FileServiceMock(error: errorInFolder)
|
||||||
let router = Router()
|
let router = Router()
|
||||||
|
|
||||||
ArchiveController("/path/to/archives/folder", fileService: fileService)
|
ArchiveController(.Path.archivesFolder, fileService: fileService)
|
||||||
.register(to: router)
|
.register(to: router)
|
||||||
|
|
||||||
let app = Application(router: router)
|
let app = Application(router: router)
|
||||||
@ -47,10 +59,71 @@ struct ArchiveControllerTests {
|
|||||||
// WHEN
|
// WHEN
|
||||||
// THEN
|
// THEN
|
||||||
try await app.test(.router) { client in
|
try await app.test(.router) { client in
|
||||||
try await client.execute(uri: "/archives", method: .get) { response in
|
try await client.execute(uri: .Path.archivesResource, method: .get) { response in
|
||||||
#expect(response.status == .ok)
|
#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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@ struct AppBuilderTests {
|
|||||||
|
|
||||||
private let appBuilder = AppBuilder(
|
private let appBuilder = AppBuilder(
|
||||||
appName: "DoxyTest",
|
appName: "DoxyTest",
|
||||||
archivesFolder: "Resources/Archives/Test"
|
folderArchives: "Resources/Archives/Test"
|
||||||
)
|
)
|
||||||
private let arguments = TestArguments()
|
private let arguments = TestArguments()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user