@testable import Hermes import XCTest final class HermesTests: XCTestCase { override func setUp() { super.setUp() configureHermes() } private func configureHermes() { let defaultHeaders = ["Custom-Header": "HeaderValue"] let decodingStrategy = JSONDecoder.KeyDecodingStrategy.convertFromSnakeCase let config = HermesConfiguration(defaultHeaders: defaultHeaders, decodingStrategy: decodingStrategy) Hermes.shared.configure(config) } func testGetRequest() async throws { let queryParams = [URLQueryItem(name: "foo", value: "bar")] let resource = Resource(url: URL(string: "https://httpbin.org/get")!, method: .get(queryParams), modelType: GetResponse.self) let getResponse = try await Hermes.shared.load(resource) XCTAssertEqual(getResponse.url, "https://httpbin.org/get?foo=bar") XCTAssertEqual(getResponse.args.count, 1) XCTAssertGreaterThan(getResponse.headers.count, 0) } func testPostRequest() async throws { let postDatas = try? JSONEncoder().encode(["foo": "bar"]) let resource = Resource(url: URL(string: "https://httpbin.org/post")!, method: .post(postDatas), modelType: PostResponse.self) let postResponse = try await Hermes.shared.load(resource) XCTAssertEqual(postResponse.url, "https://httpbin.org/post") XCTAssertEqual(postResponse.args.count, 0) XCTAssertNotNil(postResponse.json) XCTAssertEqual(postResponse.json?.count, 1) XCTAssertGreaterThan(postResponse.headers.count, 0) } func testPutRequest() async throws { let postDatas = try? JSONEncoder().encode(["foo": "bar"]) let resource = Resource(url: URL(string: "https://httpbin.org/put")!, method: .put(postDatas), modelType: PostResponse.self) let putResponse = try await Hermes.shared.load(resource) XCTAssertEqual(putResponse.url, "https://httpbin.org/put") XCTAssertEqual(putResponse.args.count, 0) XCTAssertNotNil(putResponse.json) XCTAssertEqual(putResponse.json?.count, 1) XCTAssertGreaterThan(putResponse.headers.count, 0) } func testPatchRequest() async throws { let postDatas = try? JSONEncoder().encode(["foo": "bar"]) let resource = Resource(url: URL(string: "https://httpbin.org/patch")!, method: .patch(postDatas), modelType: PostResponse.self) let patchResponse = try await Hermes.shared.load(resource) XCTAssertEqual(patchResponse.url, "https://httpbin.org/patch") XCTAssertEqual(patchResponse.args.count, 0) XCTAssertNotNil(patchResponse.json) XCTAssertEqual(patchResponse.json?.count, 1) XCTAssertGreaterThan(patchResponse.headers.count, 0) } func testDeleteRequest() async throws { let resource = Resource(url: URL(string: "https://httpbin.org/delete")!, method: .delete, modelType: PostResponse.self) let deleteResponse = try await Hermes.shared.load(resource) XCTAssertEqual(deleteResponse.url, "https://httpbin.org/delete") XCTAssertEqual(deleteResponse.args.count, 0) XCTAssertNil(deleteResponse.json) XCTAssertGreaterThan(deleteResponse.headers.count, 0) } func testNotFound() async throws { let resource = Resource(url: URL(string: "https://httpbin.org/status/404")!, method: .get(), modelType: GetResponse.self) do { let _ = try await Hermes.shared.load(resource) XCTFail("Expected to throw NetworkError.notFound") } catch NetworkError.notFound { XCTAssert(true) } catch { XCTFail("Unexpected error: \(error)") } } func testServerError() async throws { let resource = Resource(url: URL(string: "https://httpbin.org/status/500")!, method: .get(), modelType: GetResponse.self) do { let _ = try await Hermes.shared.load(resource) XCTFail("Expected to throw NetworkError.serverError") } catch NetworkError.serverError(_) { XCTAssert(true) } catch { XCTFail("Unexpected error: \(error)") } } func testDecodeError() async throws { let resource = Resource(url: URL(string: "https://httpbin.org/get")!, method: .get(), modelType: DummyResponse.self) do { let _ = try await Hermes.shared.load(resource) XCTFail("Expected to throw NetworkError.decodingError") } catch NetworkError.decodingError { XCTAssert(true) } catch { XCTFail("Unexpected error: \(error)") } } } struct GetResponse: Codable { let args: [String: String] let headers: [String: String] let origin: String let url: String } struct PostResponse: Codable { let args: [String: String] let data: String let files: [String: String] let form: [String: String] let headers: [String: String] let json: [String: String]? let origin: String let url: String } struct DummyResponse: Codable { let dumb: Int let dumber: Double }