mirror of
https://codeberg.org/secana/ForgejoKit.git
synced 2026-06-16 05:13:53 -07:00
134 lines
5.9 KiB
Swift
134 lines
5.9 KiB
Swift
@testable import ForgejoKit
|
|
import Testing
|
|
|
|
struct ErrorMappingTests {
|
|
@Test func classifiesHTTPStatusCodes() {
|
|
#expect(HTTPErrorCategory(statusCode: 401) == .authentication)
|
|
#expect(HTTPErrorCategory(statusCode: 403) == .permissionDenied)
|
|
#expect(HTTPErrorCategory(statusCode: 404) == .notFound)
|
|
#expect(HTTPErrorCategory(statusCode: 500) == .server)
|
|
#expect(HTTPErrorCategory(statusCode: 503) == .server)
|
|
#expect(HTTPErrorCategory(statusCode: 400) == .other)
|
|
}
|
|
|
|
@Test func exposesServiceErrorStatusAndCategory() {
|
|
let forbidden = ServiceError.httpError(statusCode: 403, message: "missing scope")
|
|
#expect(forbidden.httpStatusCode == 403)
|
|
#expect(forbidden.httpErrorCategory == .permissionDenied)
|
|
|
|
let serverError = ServiceError.httpError(statusCode: 502)
|
|
#expect(serverError.httpStatusCode == 502)
|
|
#expect(serverError.httpErrorCategory == .server)
|
|
|
|
#expect(ServiceError.invalidURL.httpStatusCode == nil)
|
|
#expect(ServiceError.invalidURL.httpErrorCategory == nil)
|
|
}
|
|
|
|
@Test func mapsAuthenticationStatusCodes() {
|
|
#expect(AuthenticationError.from(statusCode: 401) == .invalidCredentials)
|
|
#expect(AuthenticationError.from(statusCode: 401, body: "OTP required") == .otpRequired)
|
|
#expect(AuthenticationError.from(statusCode: 403) == .unknownError(statusCode: 403))
|
|
#expect(AuthenticationError.from(statusCode: 404) == .serverNotFound)
|
|
#expect(AuthenticationError.from(statusCode: 500) == .unknownError(statusCode: 500))
|
|
#expect(AuthenticationError.from(statusCode: 418) == .unknownError(statusCode: 418))
|
|
}
|
|
|
|
@Test func exposesAuthenticationStatusAndCategory() {
|
|
#expect(AuthenticationError.invalidCredentials.httpStatusCode == 401)
|
|
#expect(AuthenticationError.invalidCredentials.httpErrorCategory == .authentication)
|
|
#expect(AuthenticationError.serverNotFound.httpStatusCode == 404)
|
|
#expect(AuthenticationError.serverNotFound.httpErrorCategory == .notFound)
|
|
#expect(AuthenticationError.unknownError(statusCode: 403).httpStatusCode == 403)
|
|
#expect(AuthenticationError.unknownError(statusCode: 403).httpErrorCategory == .permissionDenied)
|
|
#expect(AuthenticationError.unknownError(statusCode: 502).httpErrorCategory == .server)
|
|
#expect(AuthenticationError.certificateError.httpStatusCode == nil)
|
|
#expect(AuthenticationError.certificateError.httpErrorCategory == nil)
|
|
}
|
|
|
|
// MARK: - ServiceError descriptions
|
|
|
|
@Test func serviceErrorDescriptions() {
|
|
#expect(ServiceError.noActiveInstance.errorDescription == "No active Forgejo instance")
|
|
#expect(ServiceError.invalidURL.errorDescription == "Invalid URL")
|
|
#expect(ServiceError.invalidResponse.errorDescription == "Invalid response from server")
|
|
#expect(ServiceError.httpError(statusCode: 404).errorDescription == "HTTP error: 404")
|
|
#expect(ServiceError.httpError(statusCode: 500).errorDescription == "HTTP error: 500")
|
|
#expect(ServiceError.decodingFailed(detail: "missing key").errorDescription == "Decoding failed: missing key")
|
|
}
|
|
|
|
@Test func httpErrorDescriptionUsesForgejoMessageBody() {
|
|
let error = ServiceError.httpError(
|
|
statusCode: 405,
|
|
message: #"{"message":"This pull request has failing status checks"}"#,
|
|
)
|
|
|
|
#expect(error.errorDescription == "HTTP 405: This pull request has failing status checks")
|
|
}
|
|
|
|
@Test func httpErrorDescriptionFallsBackToRawBody() {
|
|
let error = ServiceError.httpError(statusCode: 500, message: "database unavailable")
|
|
|
|
#expect(error.errorDescription == "HTTP 500: database unavailable")
|
|
}
|
|
|
|
@Test func httpErrorDescriptionIgnoresWhitespaceOnlyMessage() {
|
|
let error = ServiceError.httpError(statusCode: 503, message: " \n ")
|
|
|
|
#expect(error.errorDescription == "HTTP error: 503")
|
|
}
|
|
|
|
@Test func httpErrorDescriptionFallsBackWhenJSONMessageFieldIsEmpty() {
|
|
let error = ServiceError.httpError(
|
|
statusCode: 422,
|
|
message: #"{"message":" "}"#,
|
|
)
|
|
|
|
#expect(error.errorDescription == "HTTP error: 422")
|
|
}
|
|
|
|
@Test func httpErrorDescriptionReturnsRawJSONWhenMessageFieldMissing() {
|
|
let raw = #"{"errors":["bad request"]}"#
|
|
let error = ServiceError.httpError(statusCode: 400, message: raw)
|
|
|
|
#expect(error.errorDescription == "HTTP 400: \(raw)")
|
|
}
|
|
|
|
// MARK: - Merge error collapsing
|
|
|
|
@Test func collapseMergeErrorMaps405WithEmptyBodyToNotMergeable() {
|
|
let collapsed = PullRequestService.collapseMergeError(
|
|
.httpError(statusCode: 405, message: ""),
|
|
)
|
|
#expect(collapsed == .notMergeable)
|
|
}
|
|
|
|
@Test func collapseMergeErrorMaps409WithEmptyBodyToMergeConflict() {
|
|
let collapsed = PullRequestService.collapseMergeError(
|
|
.httpError(statusCode: 409, message: " \n "),
|
|
)
|
|
#expect(collapsed == .mergeConflict)
|
|
}
|
|
|
|
@Test func collapseMergeErrorPreserves405WithBody() {
|
|
let original = ServiceError.httpError(
|
|
statusCode: 405,
|
|
message: #"{"message":"failing status checks"}"#,
|
|
)
|
|
#expect(PullRequestService.collapseMergeError(original) == original)
|
|
}
|
|
|
|
@Test func collapseMergeErrorPreserves409WithBody() {
|
|
let original = ServiceError.httpError(statusCode: 409, message: "conflict in README.md")
|
|
#expect(PullRequestService.collapseMergeError(original) == original)
|
|
}
|
|
|
|
@Test func collapseMergeErrorPassesOtherStatusCodesThrough() {
|
|
let original = ServiceError.httpError(statusCode: 500, message: "")
|
|
#expect(PullRequestService.collapseMergeError(original) == original)
|
|
}
|
|
|
|
@Test func collapseMergeErrorPassesNonHTTPErrorsThrough() {
|
|
#expect(PullRequestService.collapseMergeError(.invalidURL) == .invalidURL)
|
|
#expect(PullRequestService.collapseMergeError(.noActiveInstance) == .noActiveInstance)
|
|
}
|
|
}
|