import Testing @testable import bookstax @Suite("BookStackError – errorDescription") struct BookStackErrorTests { @Test("invalidURL has non-nil description mentioning https") func invalidURL() { let desc = BookStackError.invalidURL.errorDescription #expect(desc != nil) #expect(desc!.contains("https")) } @Test("notAuthenticated has non-nil description") func notAuthenticated() { let desc = BookStackError.notAuthenticated.errorDescription #expect(desc != nil) #expect(!desc!.isEmpty) } @Test("unauthorized mentions token") func unauthorized() { let desc = BookStackError.unauthorized.errorDescription #expect(desc != nil) #expect(desc!.lowercased().contains("token")) } @Test("forbidden mentions 403 or permission") func forbidden() { let desc = BookStackError.forbidden.errorDescription #expect(desc != nil) let lower = desc!.lowercased() #expect(lower.contains("403") || lower.contains("permission") || lower.contains("access")) } @Test("notFound includes resource name in description") func notFound() { let desc = BookStackError.notFound(resource: "MyPage").errorDescription #expect(desc != nil) #expect(desc!.contains("MyPage")) } @Test("httpError with message returns that message") func httpErrorWithMessage() { let desc = BookStackError.httpError(statusCode: 500, message: "Internal Server Error").errorDescription #expect(desc == "Internal Server Error") } @Test("httpError without message includes status code") func httpErrorWithoutMessage() { let desc = BookStackError.httpError(statusCode: 503, message: nil).errorDescription #expect(desc != nil) #expect(desc!.contains("503")) } @Test("decodingError includes detail string") func decodingError() { let desc = BookStackError.decodingError("keyNotFound").errorDescription #expect(desc != nil) #expect(desc!.contains("keyNotFound")) } @Test("networkUnavailable mentions cache or offline") func networkUnavailable() { let desc = BookStackError.networkUnavailable.errorDescription #expect(desc != nil) let lower = desc!.lowercased() #expect(lower.contains("cache") || lower.contains("offline") || lower.contains("internet")) } @Test("keychainError includes numeric status code") func keychainError() { let desc = BookStackError.keychainError(-25300).errorDescription #expect(desc != nil) #expect(desc!.contains("-25300")) } @Test("sslError mentions SSL or TLS") func sslError() { let desc = BookStackError.sslError.errorDescription #expect(desc != nil) let upper = desc!.uppercased() #expect(upper.contains("SSL") || upper.contains("TLS")) } @Test("timeout mentions timed out or server") func timeout() { let desc = BookStackError.timeout.errorDescription #expect(desc != nil) #expect(!desc!.isEmpty) } @Test("notReachable includes the host name") func notReachable() { let desc = BookStackError.notReachable(host: "wiki.company.com").errorDescription #expect(desc != nil) #expect(desc!.contains("wiki.company.com")) } @Test("notBookStack includes the host name") func notBookStack() { let desc = BookStackError.notBookStack(host: "example.com").errorDescription #expect(desc != nil) #expect(desc!.contains("example.com")) } @Test("unknown returns the provided message verbatim") func unknown() { let msg = "Something went very wrong" let desc = BookStackError.unknown(msg).errorDescription #expect(desc == msg) } @Test("All cases produce non-nil, non-empty descriptions") func allCasesHaveDescriptions() { let errors: [BookStackError] = [ .invalidURL, .notAuthenticated, .unauthorized, .forbidden, .notFound(resource: "X"), .httpError(statusCode: 400, message: nil), .decodingError("err"), .networkUnavailable, .keychainError(0), .sslError, .timeout, .notReachable(host: "host"), .notBookStack(host: "host"), .unknown("oops") ] for error in errors { let desc = error.errorDescription #expect(desc != nil, "nil description for \(error)") #expect(!desc!.isEmpty, "empty description for \(error)") } } }