import Configuration import Foundation import Hummingbird import HummingbirdTesting import Logging import NIOCore import Testing @testable import Website @testable import WebsiteCore @Suite("App executable") struct AppTests { // MARK: Constants // Absolute path to the package's "Resources/Static" folder, derived from this // file's location so the static files resolve regardless of the working directory. private let staticFilesPath = URL(fileURLWithPath: #filePath) .deletingLastPathComponent() // Tests/App .deletingLastPathComponent() // Tests .deletingLastPathComponent() // package root .appendingPathComponent(.Path.staticResources) .path // MARK: Functional tests @Test func `landing page to be served at root`() async throws { let file: StaticFile = .indexHTML let app = try await application( reader: reader( staticFilesPath: staticFilesPath ) ) try await app.test(.router) { client in try await client.execute( uri: "/", method: .get ) { response in #expect(response.status == .ok) #expect(response.headers[.contentType] == file.contentType) #expect(response.body == data(of: file)) } } } @Test(arguments: StaticFile.allCases) func `static files to be served`( staticFile file: StaticFile ) async throws { let app = try await application( reader: reader( staticFilesPath: staticFilesPath ) ) try await app.test(.router) { client in try await client.execute( uri: "/\(file.relativePath)", method: .get ) { response in #expect(response.status == .ok) #expect(response.headers[.contentType] == file.contentType) } } } @Test func `error page to be served when not found`() async throws { let file: StaticFile = .errorHTML let app = try await application( reader: reader( staticFilesPath: staticFilesPath ) ) try await app.test(.router) { client in try await client.execute( uri: "/this-path-does-not-exist", method: .get ) { response in #expect(response.status == .notFound) #expect(response.headers[.contentType] == file.contentType) #expect(response.body == data(of: file)) } } } } // MARK: - Helpers private extension AppTests { // MARK: Methods func data( of file: StaticFile ) -> ByteBuffer { let url = URL(fileURLWithPath: file.path(relativeTo: staticFilesPath)) guard let data = try? Data(contentsOf: url) else { return ByteBuffer() } return ByteBuffer(bytes: data) } func reader( staticFilesPath: String ) -> ConfigReader { ConfigReader(providers: [ InMemoryProvider(values: [ .HTTP.host: .HTTP.host, .HTTP.port: .HTTP.port, .Log.level: .Log.level, .Path.staticFiles: .init(stringLiteral: staticFilesPath), ]) ]) } }