import Hummingbird import HummingbirdTesting import Testing @testable import AppLibrary @Suite("DocCMiddleware", .tags(.middleware)) struct DoccMiddlewareTests { @Test(arguments: zip([String].urisRedirect, [String].pathsRedirect)) func redirects( from uri: String, to path: String ) async throws { // GIVEN let router = Router.test() let app = Application(router: router) // WHEN // THEN try await app.test(.router) { client in try await client.execute(uri: uri, method: .get) { response in #expect(response.status == .seeOther) #expect(response.headers[.location] == path) } } } @Test(arguments: zip([String].urisServes, [String].identifiersServes)) func servesFile( for uri: String, with identifier: String ) async throws { // GIVEN var provider = FileProviderMock() provider.setFile(identifier: identifier) let router = Router.test(assetProvider: provider) let app = Application(router: router) // WHEN // THEN try await app.test(.router) { client in try await client.execute(uri: uri, method: .get) { response in #expect(response.status == .ok) #expect(response.body == ByteBuffer(string: identifier)) } } } @Test(arguments: zip([String].urisInvalid, [HTTPResponse.Status].statusesInvalid)) func throwError( for uri: String, with status: HTTPResponse.Status ) async throws { // GIVEN let router = Router.test() let app = Application(router: router) // WHEN // THEN try await app.test(.router) { client in try await client.execute(uri: uri, method: .get) { response in #expect(response.status == status) } } } } // MARK: - Router+Constants private extension Router { // MARK: Functions static func test(assetProvider: some FileProvider = FileProviderMock()) -> Router { let router = Router() router.addMiddleware { DocCMiddleware(assetProvider: assetProvider) } return router } } // MARK: - Collection+String private extension Collection where Element == String { // MARK: Computed static var identifiersServes: [String] {[ "/SomeArchive.doccarchive/documentation/somearchive/index.html", "/SomeArchive.doccarchive/tutorials/somearchive/index.html", "/SomeArchive.doccarchive/favicon.ico", "/SomeArchive.doccarchive/favicon.svg", "/SomeArchive.doccarchive/theme-settings.json", "/SomeArchive.doccarchive/data/documentation/somearchive.json", "/SomeArchive.doccarchive/css/some-css-file.css", "/SomeArchive.doccarchive/data/some-data-file.bin", "/SomeArchive.doccarchive/downloads/some-download-file", "/SomeArchive.doccarchive/images/some-image-file.jpg", "/SomeArchive.doccarchive/img/some-image-file.png", "/SomeArchive.doccarchive/index/some-index-file", "/SomeArchive.doccarchive/js/some-js-file.js", "/SomeArchive.doccarchive/videos/some-video-file.mp4", ]} static var pathsRedirect: [String] {[ "/archives/SomeArchive/documentation", "/archives/SomeArchive/documentation/", "/archives/SomeArchive/tutorials/", ]} static var urisInvalid: [String] {[ "", "some-path", "some/uri/path", "../", "/../", "/archives", "/archives/SomeArchive/favicon.ico", "/archives/SomeArchive/favicon.svg", "/archives/SomeArchive/theme-settings.json", "/archives/SomeArchive/data/documentation.json", "/archives/SomeArchive/css/some-css-file.css", "/archives/SomeArchive/data/some-data-file.bin", "/archives/SomeArchive/downloads/some-download-file", "/archives/SomeArchive/images/some-image-file.jpg", "/archives/SomeArchive/img/some-image-file.png", "/archives/SomeArchive/index/some-index-file", "/archives/SomeArchive/js/some-js-file.js", "/archives/SomeArchive/videos/some-video-file.mp4", "/archives/SomeArchive/index.html", "/archives/SomeArchive/xxx", "/archives/SomeArchive/xxx/index.html" ]} static var urisRedirect: [String] {[ "/archives/SomeArchive/", "/archives/SomeArchive/documentation", "/archives/SomeArchive/tutorials", ]} static var urisServes: [String] {[ "/archives/SomeArchive/documentation/", "/archives/SomeArchive/tutorials/", "/archives/SomeArchive/favicon.ico", "/archives/SomeArchive/favicon.svg", "/archives/SomeArchive/theme-settings.json", "/archives/SomeArchive/data/documentation.json", "/archives/SomeArchive/css/some-css-file.css", "/archives/SomeArchive/data/some-data-file.bin", "/archives/SomeArchive/downloads/some-download-file", "/archives/SomeArchive/images/some-image-file.jpg", "/archives/SomeArchive/img/some-image-file.png", "/archives/SomeArchive/index/some-index-file", "/archives/SomeArchive/js/some-js-file.js", "/archives/SomeArchive/videos/some-video-file.mp4", ]} } // MARK: - Collection+HTTPResponse.Status private extension Collection where Element == HTTPResponse.Status { // MARK: Computed static var statusesInvalid: [HTTPResponse.Status] {[ .notFound, .badRequest, .badRequest, .badRequest, .badRequest, .notFound, .notFound, .notFound, .notFound, .notFound, .notFound, .notFound, .notFound, .notFound, .notFound, .notFound, .notFound, .notFound, .notImplemented, .notImplemented, .notImplemented ]} }