diff --git a/Tests/AppTests/ErrorMiddlewareTests.swift b/Tests/AppTests/ErrorMiddlewareTests.swift index 53a628ed7..6e348145b 100644 --- a/Tests/AppTests/ErrorMiddlewareTests.swift +++ b/Tests/AppTests/ErrorMiddlewareTests.swift @@ -12,60 +12,63 @@ // See the License for the specific language governing permissions and // limitations under the License. -import XCTest - @testable import App import Dependencies +import Testing import Vapor -class ErrorMiddlewareTests: AppTestCase { - - override func setUpWithError() throws { - try super.setUpWithError() +@Suite struct ErrorMiddlewareTests { + func setup(_ app: Application) async throws { // set up some test routes app.get("ok") { _ in return "ok" } app.get("404") { req async throws -> Response in throw Abort(.notFound) } app.get("500") { req async throws -> Response in throw Abort(.internalServerError) } } - func test_custom_routes() throws { - // Test to ensure the test routes we've set up in setUpWithError are in effect - try app.test(.GET, "ok", afterResponse: { response in - XCTAssertEqual(response.status, .ok) - XCTAssertEqual(response.body.asString(), "ok") - }) + @Test func custom_routes() async throws { + try await withApp(setup) { app in + // Test to ensure the test routes we've set up in setUpWithError are in effect + try await app.test(.GET, "ok", afterResponse: { response async in + #expect(response.status == .ok) + #expect(response.body.asString() == "ok") + }) + } } - func test_html_error() throws { + @Test func html_error() async throws { // Test to ensure errors are converted to html error pages via the ErrorMiddleware - try withDependencies { + try await withDependencies { $0.environment.dbId = { nil } } operation: { - try app.test(.GET, "404", afterResponse: { response in - XCTAssertEqual(response.content.contentType, .html) - XCTAssert(response.body.asString().contains("404 - Not Found")) - }) + try await withApp(setup) { app in + try await app.test(.GET, "404", afterResponse: { response async in + #expect(response.content.contentType == .html) + #expect(response.body.asString().contains("404 - Not Found")) + }) + } } } - func test_status_code() throws { + @Test func status_code() async throws { // Ensure we're still reporting the actual status code even when serving html pages // (Status is important for Google ranking, see // https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/323) - try withDependencies { + try await withDependencies { $0.environment.dbId = { nil } } operation: { - try app.test(.GET, "404", afterResponse: { response in - XCTAssertEqual(response.status, .notFound) - XCTAssertEqual(response.content.contentType, .html) - }) - try app.test(.GET, "500", afterResponse: { response in - XCTAssertEqual(response.status, .internalServerError) - XCTAssertEqual(response.content.contentType, .html) - }) + try await withApp(setup) { app in + try await app.test(.GET, "404", afterResponse: { response async in + #expect(response.status == .notFound) + #expect(response.content.contentType == .html) + }) + try await app.test(.GET, "500", afterResponse: { response async in + #expect(response.status == .internalServerError) + #expect(response.content.contentType == .html) + }) + } } } diff --git a/Tests/AppTests/ErrorPageModelTests.swift b/Tests/AppTests/ErrorPageModelTests.swift index 40ed0c1d6..838e43320 100644 --- a/Tests/AppTests/ErrorPageModelTests.swift +++ b/Tests/AppTests/ErrorPageModelTests.swift @@ -14,11 +14,13 @@ @testable import App -import XCTVapor +import Testing +import Vapor -class ErrorPageModelTests: AppTestCase { - func test_500() throws { +@Suite struct ErrorPageModelTests { + + @Test func error_500() throws { // setup let error = Abort(.internalServerError) @@ -26,10 +28,10 @@ class ErrorPageModelTests: AppTestCase { let model = ErrorPage.Model(error) // validate - XCTAssertEqual(model.errorMessage, "500 - Internal Server Error") + #expect(model.errorMessage == "500 - Internal Server Error") } - func test_500_with_reason() throws { + @Test func error_500_with_reason() throws { // setup let error = Abort(.internalServerError, reason: "Reason") @@ -37,7 +39,7 @@ class ErrorPageModelTests: AppTestCase { let model = ErrorPage.Model(error) // validate - XCTAssertEqual(model.errorMessage, "500 - Internal Server Error - Reason") + #expect(model.errorMessage == "500 - Internal Server Error - Reason") } } diff --git a/Tests/AppTests/ErrorReportingTests.swift b/Tests/AppTests/ErrorReportingTests.swift index ea4f66a57..b7fa5e8d8 100644 --- a/Tests/AppTests/ErrorReportingTests.swift +++ b/Tests/AppTests/ErrorReportingTests.swift @@ -12,45 +12,53 @@ // See the License for the specific language governing permissions and // limitations under the License. +import Foundation + @testable import App import Dependencies -import XCTVapor +import Testing + +@Suite struct ErrorReportingTests { -class ErrorReportingTests: AppTestCase { + let capturingLogger = CapturingLogger() - func test_Analyze_recordError() async throws { - let pkg = try await savePackage(on: app.db, "1") - try await Analyze.recordError(database: app.db, - error: AppError.cacheDirectoryDoesNotExist(pkg.id, "path")) - do { - let pkg = try await XCTUnwrapAsync(try await Package.find(pkg.id, on: app.db)) - XCTAssertEqual(pkg.status, .cacheDirectoryDoesNotExist) - XCTAssertEqual(pkg.processingStage, .analysis) + @Test func Analyze_recordError() async throws { + try await withApp { app in + let pkg = try await savePackage(on: app.db, "1") + try await Analyze.recordError(database: app.db, + error: AppError.cacheDirectoryDoesNotExist(pkg.id, "path")) + do { + let pkg = try await XCTUnwrapAsync(try await Package.find(pkg.id, on: app.db)) + #expect(pkg.status == .cacheDirectoryDoesNotExist) + #expect(pkg.processingStage == .analysis) + } } } - func test_Ingestion_error_reporting() async throws { - // setup - try await Package(id: .id0, url: "1", processingStage: .reconciliation).save(on: app.db) + @Test func Ingestion_error_reporting() async throws { + try await withApp(logHandler: capturingLogger) { app in + // setup + try await Package(id: .id0, url: "1", processingStage: .reconciliation).save(on: app.db) - try await withDependencies { - $0.date.now = .now - $0.github.fetchMetadata = { @Sendable _, _ throws(Github.Error) in throw Github.Error.invalidURL("1") } - } operation: { - // MUT - try await Ingestion.ingest(client: app.client, database: app.db, mode: .limit(10)) - } + try await withDependencies { + $0.date.now = .now + $0.github.fetchMetadata = { @Sendable _, _ throws(Github.Error) in throw Github.Error.invalidURL("1") } + } operation: { + // MUT + try await Ingestion.ingest(client: app.client, database: app.db, mode: .limit(10)) + } - // validation - logger.logs.withValue { - XCTAssertEqual($0, [.init(level: .warning, - message: #"Ingestion.Error(\#(UUID.id0), invalidURL(1))"#)]) + // validation + capturingLogger.logs.withValue { + #expect($0 == [.init(level: .warning, + message: #"Ingestion.Error(\#(UUID.id0), invalidURL(1))"#)]) + } } } - func test_Analyzer_error_reporting() async throws { + @Test func Analyzer_error_reporting() async throws { try await withDependencies { $0.fileManager.fileExists = { @Sendable _ in true } $0.shell.run = { @Sendable cmd, _ in @@ -60,37 +68,39 @@ class ErrorReportingTests: AppTestCase { return "invalid" } } operation: { - // setup - try await Package(id: .id1, url: "1".asGithubUrl.url, processingStage: .ingestion).save(on: app.db) + try await withApp(logHandler: capturingLogger) { app in + // setup + try await Package(id: .id1, url: "1".asGithubUrl.url, processingStage: .ingestion).save(on: app.db) - // MUT - try await Analyze.analyze(client: app.client, - database: app.db, - mode: .limit(10)) + // MUT + try await Analyze.analyze(client: app.client, database: app.db, mode: .limit(10)) - // validation - logger.logs.withValue { - XCTAssertEqual($0, [ - .init(level: .critical, message: "updatePackages: unusually high error rate: 1/1 = 100.0%"), - .init(level: .warning, message: #"App.AppError.genericError(Optional(\#(UUID.id1)), "updateRepository: no repository")"#) - ]) + // validation + capturingLogger.logs.withValue { + #expect($0 == [ + .init(level: .critical, message: "updatePackages: unusually high error rate: 1/1 = 100.0%"), + .init(level: .warning, message: #"App.AppError.genericError(Optional(\#(UUID.id1)), "updateRepository: no repository")"#) + ]) + } } } } - func test_invalidPackageCachePath() async throws { + @Test func invalidPackageCachePath() async throws { try await withDependencies { $0.fileManager.fileExists = { @Sendable _ in true } } operation: { - // setup - try await savePackages(on: app.db, ["1", "2"], processingStage: .ingestion) + try await withApp { app in + // setup + try await savePackages(on: app.db, ["1", "2"], processingStage: .ingestion) - // MUT - try await Analyze.analyze(client: app.client, database: app.db, mode: .limit(10)) + // MUT + try await Analyze.analyze(client: app.client, database: app.db, mode: .limit(10)) - // validation - let packages = try await Package.query(on: app.db).sort(\.$url).all() - XCTAssertEqual(packages.map(\.status), [.invalidCachePath, .invalidCachePath]) + // validation + let packages = try await Package.query(on: app.db).sort(\.$url).all() + #expect(packages.map(\.status) == [.invalidCachePath, .invalidCachePath]) + } } } diff --git a/Tests/AppTests/FundingLinkTests.swift b/Tests/AppTests/FundingLinkTests.swift index 9d2d89eee..294613422 100644 --- a/Tests/AppTests/FundingLinkTests.swift +++ b/Tests/AppTests/FundingLinkTests.swift @@ -14,27 +14,26 @@ @testable import App -import Vapor -import XCTest +import Testing -class FundingLinkTests: XCTestCase { +@Suite struct FundingLinkTests { - func test_fundingLink_missingSchemeFix() async throws { + @Test func fundingLink_missingSchemeFix() async throws { // URL with both a scheme and a host. let ghFundingLink1 = Github.Metadata.FundingLinkNode(platform: .customUrl, url: "https://example.com") - let dbFundingLink1 = try XCTUnwrap(FundingLink(from: ghFundingLink1)) - XCTAssertEqual(dbFundingLink1.url, "https://example.com") + let dbFundingLink1 = try #require(FundingLink(from: ghFundingLink1)) + #expect(dbFundingLink1.url == "https://example.com") // URL with a host but no scheme. let ghFundingLink2 = Github.Metadata.FundingLinkNode(platform: .customUrl, url: "example.com") - let dbFundingLink2 = try XCTUnwrap(FundingLink(from: ghFundingLink2)) - XCTAssertEqual(dbFundingLink2.url, "https://example.com") + let dbFundingLink2 = try #require(FundingLink(from: ghFundingLink2)) + #expect(dbFundingLink2.url == "https://example.com") // URL with neither. let ghFundingLink3 = Github.Metadata.FundingLinkNode(platform: .customUrl, url: "!@£$%") let dbFundingLink3 = FundingLink(from: ghFundingLink3) - XCTAssertNil(dbFundingLink3) + #expect(dbFundingLink3 == nil) } }