import XCTest @testable import LCEssentials private struct SamplePayload: Encodable, Sendable { let name: String let age: Int } final class HTTPBodyTests: XCTestCase { // MARK: - JSONBody func testJSONBodyEncodesPayloadAndContentType() throws { let payload = SamplePayload(name: "loverde", age: 3) let (data, contentType) = try JSONBody(payload).encoded() XCTAssertEqual(contentType, "application/json; charset=UTF-8") let decoded = try JSONDecoder().decode([String: AnyDecodable].self, from: data) XCTAssertEqual(decoded["name"]?.value as? String, "loverde") XCTAssertEqual(decoded["age"]?.value as? Int, 3) } func testJSONBodyFactory() throws { let (data, _) = try jsonBody(SamplePayload(name: "x", age: 1)).encoded() XCTAssertFalse(data.isEmpty) } // MARK: - FormURLEncodedBody func testFormURLEncodedEncodesPairsAndPercentEscapes() throws { let (data, contentType) = try FormURLEncodedBody(["a": "1", "b": "two words"]).encoded() XCTAssertEqual(contentType, "application/x-www-form-urlencoded; charset=UTF-8") let pairs = Set(String(data: data, encoding: .utf8)!.split(separator: "&").map(String.init)) XCTAssertEqual(pairs, ["a=1", "b=two%20words"]) } func testFormURLEncodedEscapesReservedCharactersInsteadOfDropping() throws { let (data, _) = try FormURLEncodedBody(["q": "a&b=c"]).encoded() let body = String(data: data, encoding: .utf8)! XCTAssertEqual(body, "q=a%26b%3Dc") } } /// Minimal type-erased decoder for asserting JSON shape in tests. struct AnyDecodable: Decodable { let value: Any init(from decoder: Decoder) throws { let c = try decoder.singleValueContainer() if let i = try? c.decode(Int.self) { value = i } else if let s = try? c.decode(String.self) { value = s } else if let b = try? c.decode(Bool.self) { value = b } else if let d = try? c.decode(Double.self) { value = d } else { value = "" } } }