mirror of
https://codeberg.org/secana/ForgejoKit.git
synced 2026-06-16 05:13:53 -07:00
- Add Attachment model with isImage computed property - Add assets field to Issue, IssueComment, and PullRequest - Add multipart/form-data upload support to ForgejoClient - Add uploadIssueAttachment and uploadCommentAttachment to IssueService
134 lines
6.1 KiB
Swift
134 lines
6.1 KiB
Swift
@testable import ForgejoKit
|
|
import Testing
|
|
|
|
struct ErrorMappingTests {
|
|
@Test func `classifies HTTP status codes`() {
|
|
#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 `exposes service error status and category`() {
|
|
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 `maps authentication status codes`() {
|
|
#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 `exposes authentication status and category`() {
|
|
#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 `service error descriptions`() {
|
|
#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 `http error description uses forgejo message body`() {
|
|
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 `http error description falls back to raw body`() {
|
|
let error = ServiceError.httpError(statusCode: 500, message: "database unavailable")
|
|
|
|
#expect(error.errorDescription == "HTTP 500: database unavailable")
|
|
}
|
|
|
|
@Test func `http error description ignores whitespace only message`() {
|
|
let error = ServiceError.httpError(statusCode: 503, message: " \n ")
|
|
|
|
#expect(error.errorDescription == "HTTP error: 503")
|
|
}
|
|
|
|
@Test func `http error description falls back when JSON message field is empty`() {
|
|
let error = ServiceError.httpError(
|
|
statusCode: 422,
|
|
message: #"{"message":" "}"#,
|
|
)
|
|
|
|
#expect(error.errorDescription == "HTTP error: 422")
|
|
}
|
|
|
|
@Test func `http error description returns raw JSON when message field missing`() {
|
|
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 `collapse merge error maps 405 with empty body to not mergeable`() {
|
|
let collapsed = PullRequestService.collapseMergeError(
|
|
.httpError(statusCode: 405, message: ""),
|
|
)
|
|
#expect(collapsed == .notMergeable)
|
|
}
|
|
|
|
@Test func `collapse merge error maps 409 with empty body to merge conflict`() {
|
|
let collapsed = PullRequestService.collapseMergeError(
|
|
.httpError(statusCode: 409, message: " \n "),
|
|
)
|
|
#expect(collapsed == .mergeConflict)
|
|
}
|
|
|
|
@Test func `collapse merge error preserves 405 with body`() {
|
|
let original = ServiceError.httpError(
|
|
statusCode: 405,
|
|
message: #"{"message":"failing status checks"}"#,
|
|
)
|
|
#expect(PullRequestService.collapseMergeError(original) == original)
|
|
}
|
|
|
|
@Test func `collapse merge error preserves 409 with body`() {
|
|
let original = ServiceError.httpError(statusCode: 409, message: "conflict in README.md")
|
|
#expect(PullRequestService.collapseMergeError(original) == original)
|
|
}
|
|
|
|
@Test func `collapse merge error passes other status codes through`() {
|
|
let original = ServiceError.httpError(statusCode: 500, message: "")
|
|
#expect(PullRequestService.collapseMergeError(original) == original)
|
|
}
|
|
|
|
@Test func `collapse merge error passes non HTTP errors through`() {
|
|
#expect(PullRequestService.collapseMergeError(.invalidURL) == .invalidURL)
|
|
#expect(PullRequestService.collapseMergeError(.noActiveInstance) == .noActiveInstance)
|
|
}
|
|
}
|