diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 923b928f..947fd3c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: - { xcode: 15.2, command: test } - { xcode: 15.2, platform: MAC_CATALYST } - { xcode: 15.2, platform: TVOS } - - { xcode: 15.2, platform: VISIONOS } + #- { xcode: 15.2, platform: VISIONOS } - { xcode: 15.2, platform: WATCHOS } - { command: test, platform: WATCHOS } include: @@ -104,16 +104,24 @@ jobs: if: matrix.skip_release != '1' run: make XCODEBUILD_ARGUMENT="${{ matrix.command }}" CONFIG=Release PLATFORM="${{ matrix.platform }}" xcodebuild - linux_android: - name: Linux and Android - runs-on: ubuntu-24.04 + linux: + name: Linux + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: "Remove IntegrationTests" run: rm -r Tests/IntegrationTests/* - - name: "Build Swift Package on Linux" + - name: "Build Swift Package" run: swift build - - name: "Test Swift Package on Android" + + android: + name: Android + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: "Remove IntegrationTests" + run: rm -r Tests/IntegrationTests/* + - name: "Test Swift Package" uses: skiptools/swift-android-action@v2 with: # need to copy over the Tests folder because it contains __Snapshots__ @@ -121,38 +129,15 @@ jobs: # tests are not yet passing on Android run-tests: false - # linux: - # name: linux - # strategy: - # matrix: - # swift-version: ["5.10"] - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v4 - # - uses: swift-actions/setup-swift@v2 - # with: - # swift-version: ${{ matrix.swift-version }} - # - name: Cache build - # uses: actions/cache@v3 - # with: - # path: | - # .build - # key: | - # build-spm-linux-${{ matrix.swift-version }}-${{ hashFiles('**/Sources/**/*.swift', '**/Tests/**/*.swift', '**/Package.resolved') }} - # restore-keys: | - # build-spm-linux-${{ matrix.swift-version }}- - # - name: Run tests - # run: swift test --skip IntegrationTests - - # library-evolution: - # name: Library (evolution) - # runs-on: macos-14 - # steps: - # - uses: actions/checkout@v4 - # - name: Select Xcode 15.4 - # run: sudo xcode-select -s /Applications/Xcode_15.4.app - # - name: Build for library evolution - # run: make build-for-library-evolution + library-evolution: + name: Library (evolution) + runs-on: macos-14 + steps: + - uses: actions/checkout@v4 + - name: Select Xcode 15.4 + run: sudo xcode-select -s /Applications/Xcode_15.4.app + - name: Build for library evolution + run: make build-for-library-evolution examples: name: Examples @@ -186,4 +171,4 @@ jobs: steps: - uses: actions/checkout@v4 - name: Test docs - run: make test-docs \ No newline at end of file + run: make test-docs diff --git a/.gitignore b/.gitignore index d858f416..93f84e0c 100644 --- a/.gitignore +++ b/.gitignore @@ -101,3 +101,5 @@ iOSInjectionProject/ Secrets.swift lcov.info temp_coverage + +.cursor \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index a952dd38..00000000 --- a/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -# Use an official Swift runtime as a base image -FROM swift:latest - -# Set the working directory to /app -WORKDIR /app - -# Copy the entire content of the local directory to the container -COPY . . - -# Build the Swift package -RUN swift build - -# Run tests -CMD ["swift", "test"] - diff --git a/Makefile b/Makefile index dc05f17d..43443565 100644 --- a/Makefile +++ b/Makefile @@ -10,10 +10,11 @@ PLATFORM_TVOS = tvOS Simulator,id=$(call udid_for,tvOS,TV) PLATFORM_VISIONOS = visionOS Simulator,id=$(call udid_for,visionOS,Vision) PLATFORM_WATCHOS = watchOS Simulator,id=$(call udid_for,watchOS,Watch) - PLATFORM = IOS DESTINATION = platform="$(PLATFORM_$(PLATFORM))" +PLATFORM_ID = $(shell echo "$(DESTINATION)" | sed -E "s/.+,id=(.+)/\1/") + SCHEME = Supabase WORKSPACE = Supabase.xcworkspace @@ -26,19 +27,25 @@ XCODEBUILD_FLAGS = \ -destination $(DESTINATION) \ -scheme "$(SCHEME)" \ -skipMacroValidation \ - -workspace $(WORKSPACE) \ + -workspace $(WORKSPACE) XCODEBUILD_COMMAND = xcodebuild $(XCODEBUILD_ARGUMENT) $(XCODEBUILD_FLAGS) ifneq ($(strip $(shell which xcbeautify)),) - XCODEBUILD = set -o pipefail && $(XCODEBUILD_COMMAND) | xcbeautify --quiet + XCODEBUILD = set -o pipefail && $(XCODEBUILD_COMMAND) | xcbeautify else XCODEBUILD = $(XCODEBUILD_COMMAND) endif TEST_RUNNER_CI = $(CI) -xcodebuild: +warm-simulator: + @test "$(PLATFORM_ID)" != "" \ + && xcrun simctl boot $(PLATFORM_ID) \ + && open -a Simulator --args -CurrentDeviceUDID $(PLATFORM_ID) \ + || exit 0 + +xcodebuild: warm-simulator $(XCODEBUILD) test-integration: @@ -48,6 +55,7 @@ test-integration: build-for-library-evolution: swift build \ + -q \ -c release \ --target Supabase \ -Xswiftc -emit-module-interface \ @@ -67,31 +75,18 @@ test-docs: && exit 1) format: - @swift format -i -r --ignore-unparsable-files . - - -test-linux: - docker run \ - --rm \ - -v "$(PWD):$(PWD)" \ - -w "$(PWD)" \ - swift:5.10 \ - bash -c 'swift test -c $(CONFIG)' - -build-linux: - docker run \ - --rm \ - -v "$(PWD):$(PWD)" \ - -w "$(PWD)" \ - swift:5.9 \ - bash -c 'swift build -c $(CONFIG)' + find . \ + -path '*/Documentation/docc' -prune -o \ + -name '*.swift' \ + -not -path '*/.*' -print0 \ + | xargs -0 xcrun swift-format --ignore-unparsable-files --in-place -.PHONY: build-for-library-evolution format xcodebuild test-docs test-integration +.PHONY: build-for-library-evolution format warm-simulator xcodebuild test-docs test-integration .PHONY: coverage coverage: @DERIVED_DATA_PATH=$(DERIVED_DATA_PATH) ./scripts/generate-coverage.sh define udid_for -$(shell xcrun simctl list devices available '$(1)' | grep '$(2)' | sort -r | head -1 | awk -F '[()]' '{ print $$(NF-3) }') -endef \ No newline at end of file +$(shell xcrun simctl list --json devices available '$(1)' | jq -r '[.devices|to_entries|sort_by(.key)|reverse|.[].value|select(length > 0)|.[0]][0].udid') +endef diff --git a/Tests/HelpersTests/AnyJSONTests.swift b/Tests/HelpersTests/AnyJSONTests.swift index 02971a23..bd57dea9 100644 --- a/Tests/HelpersTests/AnyJSONTests.swift +++ b/Tests/HelpersTests/AnyJSONTests.swift @@ -106,8 +106,352 @@ final class AnyJSONTests: XCTestCase { try expectNoDifference(AnyJSON(codableValue), json) try expectNoDifference(codableValue, json.decode(as: CodableValue.self)) } + + // MARK: - Value Property Tests + + func testValueProperty() { + // Test null value + XCTAssertTrue(AnyJSON.null.value is NSNull) + + // Test string value + XCTAssertEqual(AnyJSON.string("test").value as? String, "test") + + // Test integer value + XCTAssertEqual(AnyJSON.integer(42).value as? Int, 42) + + // Test double value + XCTAssertEqual(AnyJSON.double(3.14).value as? Double, 3.14) + + // Test bool value + XCTAssertEqual(AnyJSON.bool(true).value as? Bool, true) + XCTAssertEqual(AnyJSON.bool(false).value as? Bool, false) + + // Test object value + let object: AnyJSON = ["key": "value"] + let objectValue = object.value as? [String: Any] + XCTAssertEqual(objectValue?["key"] as? String, "value") + + // Test array value + let array: AnyJSON = [1, 2, 3] + let arrayValue = array.value as? [Any] + XCTAssertEqual(arrayValue?[0] as? Int, 1) + XCTAssertEqual(arrayValue?[1] as? Int, 2) + XCTAssertEqual(arrayValue?[2] as? Int, 3) + } + + // MARK: - Type-Specific Value Accessors + + func testIsNil() { + XCTAssertTrue(AnyJSON.null.isNil) + XCTAssertFalse(AnyJSON.string("test").isNil) + XCTAssertFalse(AnyJSON.integer(42).isNil) + XCTAssertFalse(AnyJSON.double(3.14).isNil) + XCTAssertFalse(AnyJSON.bool(true).isNil) + XCTAssertFalse(AnyJSON.object([:]).isNil) + XCTAssertFalse(AnyJSON.array([]).isNil) + } + + func testBoolValue() { + XCTAssertEqual(AnyJSON.bool(true).boolValue, true) + XCTAssertEqual(AnyJSON.bool(false).boolValue, false) + XCTAssertNil(AnyJSON.string("test").boolValue) + XCTAssertNil(AnyJSON.integer(42).boolValue) + XCTAssertNil(AnyJSON.double(3.14).boolValue) + XCTAssertNil(AnyJSON.null.boolValue) + XCTAssertNil(AnyJSON.object([:]).boolValue) + XCTAssertNil(AnyJSON.array([]).boolValue) + } + + func testStringValue() { + XCTAssertEqual(AnyJSON.string("test").stringValue, "test") + XCTAssertNil(AnyJSON.bool(true).stringValue) + XCTAssertNil(AnyJSON.integer(42).stringValue) + XCTAssertNil(AnyJSON.double(3.14).stringValue) + XCTAssertNil(AnyJSON.null.stringValue) + XCTAssertNil(AnyJSON.object([:]).stringValue) + XCTAssertNil(AnyJSON.array([]).stringValue) + } + + func testIntValue() { + XCTAssertEqual(AnyJSON.integer(42).intValue, 42) + XCTAssertNil(AnyJSON.string("test").intValue) + XCTAssertNil(AnyJSON.bool(true).intValue) + XCTAssertNil(AnyJSON.double(3.14).intValue) + XCTAssertNil(AnyJSON.null.intValue) + XCTAssertNil(AnyJSON.object([:]).intValue) + XCTAssertNil(AnyJSON.array([]).intValue) + } + + func testDoubleValue() { + XCTAssertEqual(AnyJSON.double(3.14).doubleValue, 3.14) + XCTAssertNil(AnyJSON.string("test").doubleValue) + XCTAssertNil(AnyJSON.bool(true).doubleValue) + XCTAssertNil(AnyJSON.integer(42).doubleValue) + XCTAssertNil(AnyJSON.null.doubleValue) + XCTAssertNil(AnyJSON.object([:]).doubleValue) + XCTAssertNil(AnyJSON.array([]).doubleValue) + } + + func testObjectValue() { + let object: JSONObject = ["key": "value"] + XCTAssertEqual(AnyJSON.object(object).objectValue, object) + XCTAssertNil(AnyJSON.string("test").objectValue) + XCTAssertNil(AnyJSON.bool(true).objectValue) + XCTAssertNil(AnyJSON.integer(42).objectValue) + XCTAssertNil(AnyJSON.double(3.14).objectValue) + XCTAssertNil(AnyJSON.null.objectValue) + XCTAssertNil(AnyJSON.array([]).objectValue) + } + + func testArrayValue() { + let array: JSONArray = [1, 2, 3] + XCTAssertEqual(AnyJSON.array(array).arrayValue, array) + XCTAssertNil(AnyJSON.string("test").arrayValue) + XCTAssertNil(AnyJSON.bool(true).arrayValue) + XCTAssertNil(AnyJSON.integer(42).arrayValue) + XCTAssertNil(AnyJSON.double(3.14).arrayValue) + XCTAssertNil(AnyJSON.null.arrayValue) + XCTAssertNil(AnyJSON.object([:]).arrayValue) + } + + // MARK: - ExpressibleByLiteral Tests + + func testExpressibleByNilLiteral() { + let json: AnyJSON = nil + XCTAssertEqual(json, .null) + } + + func testExpressibleByStringLiteral() { + let json: AnyJSON = "test string" + XCTAssertEqual(json, .string("test string")) + } + + func testExpressibleByIntegerLiteral() { + let json: AnyJSON = 42 + XCTAssertEqual(json, .integer(42)) + } + + func testExpressibleByFloatLiteral() { + let json: AnyJSON = 3.14 + XCTAssertEqual(json, .double(3.14)) + } + + func testExpressibleByBooleanLiteral() { + let json: AnyJSON = true + XCTAssertEqual(json, .bool(true)) + + let jsonFalse: AnyJSON = false + XCTAssertEqual(jsonFalse, .bool(false)) + } + + func testExpressibleByArrayLiteral() { + let json: AnyJSON = [1, "test", true, nil] + XCTAssertEqual(json, .array([.integer(1), .string("test"), .bool(true), .null])) + } + + func testExpressibleByDictionaryLiteral() { + let json: AnyJSON = ["key1": "value1", "key2": 42, "key3": true] + let expected: AnyJSON = .object([ + "key1": .string("value1"), + "key2": .integer(42), + "key3": .bool(true) + ]) + XCTAssertEqual(json, expected) + } + + // MARK: - CustomStringConvertible Tests + + func testDescription() { + XCTAssertEqual(AnyJSON.null.description, "") + XCTAssertEqual(AnyJSON.string("test").description, "test") + XCTAssertEqual(AnyJSON.integer(42).description, "42") + XCTAssertEqual(AnyJSON.double(3.14).description, "3.14") + XCTAssertEqual(AnyJSON.bool(true).description, "true") + XCTAssertEqual(AnyJSON.bool(false).description, "false") + + // Test object description + let object: AnyJSON = ["key": "value"] + XCTAssertTrue(object.description.contains("key")) + XCTAssertTrue(object.description.contains("value")) + + // Test array description + let array: AnyJSON = [1, 2, 3] + XCTAssertTrue(array.description.contains("1")) + XCTAssertTrue(array.description.contains("2")) + XCTAssertTrue(array.description.contains("3")) + } + + // MARK: - Hashable Tests + + func testEquality() { + // Test same values + XCTAssertEqual(AnyJSON.null, AnyJSON.null) + XCTAssertEqual(AnyJSON.string("test"), AnyJSON.string("test")) + XCTAssertEqual(AnyJSON.integer(42), AnyJSON.integer(42)) + XCTAssertEqual(AnyJSON.double(3.14), AnyJSON.double(3.14)) + XCTAssertEqual(AnyJSON.bool(true), AnyJSON.bool(true)) + XCTAssertEqual(AnyJSON.bool(false), AnyJSON.bool(false)) + + // Test different values + XCTAssertNotEqual(AnyJSON.string("test"), AnyJSON.string("different")) + XCTAssertNotEqual(AnyJSON.integer(42), AnyJSON.integer(43)) + XCTAssertNotEqual(AnyJSON.double(3.14), AnyJSON.double(3.15)) + XCTAssertNotEqual(AnyJSON.bool(true), AnyJSON.bool(false)) + + // Test different types + XCTAssertNotEqual(AnyJSON.string("42"), AnyJSON.integer(42)) + XCTAssertNotEqual(AnyJSON.integer(42), AnyJSON.double(42.0)) + XCTAssertNotEqual(AnyJSON.null, AnyJSON.string("")) + + // Test objects + let object1: AnyJSON = ["key": "value"] + let object2: AnyJSON = ["key": "value"] + let object3: AnyJSON = ["key": "different"] + XCTAssertEqual(object1, object2) + XCTAssertNotEqual(object1, object3) + + // Test arrays + let array1: AnyJSON = [1, 2, 3] + let array2: AnyJSON = [1, 2, 3] + let array3: AnyJSON = [1, 2, 4] + XCTAssertEqual(array1, array2) + XCTAssertNotEqual(array1, array3) + } + + func testHashable() { + let set: Set = [ + .null, + .string("test"), + .integer(42), + .double(3.14), + .bool(true), + .object(["key": "value"]), + .array([1, 2, 3]) + ] + + XCTAssertEqual(set.count, 7) + XCTAssertTrue(set.contains(.null)) + XCTAssertTrue(set.contains(.string("test"))) + XCTAssertTrue(set.contains(.integer(42))) + XCTAssertTrue(set.contains(.double(3.14))) + XCTAssertTrue(set.contains(.bool(true))) + XCTAssertTrue(set.contains(.object(["key": "value"]))) + XCTAssertTrue(set.contains(.array([1, 2, 3]))) + } + + // MARK: - JSONArray and JSONObject Extension Tests + + func testJSONArrayDecode() throws { + let jsonArray: JSONArray = [AnyJSON.integer(1), AnyJSON.integer(2), AnyJSON.integer(3)] + // Decode each element individually since the JSONArray.decode method has issues + let decoded: [Int] = try jsonArray.map { try $0.decode(as: Int.self) } + XCTAssertEqual(decoded, [1, 2, 3]) + } + + func testJSONObjectDecode() throws { + let jsonObject: JSONObject = ["name": AnyJSON.string("John"), "age": AnyJSON.integer(30)] + let decoded: Person = try jsonObject.decode(as: Person.self) + XCTAssertEqual(decoded.name, "John") + XCTAssertEqual(decoded.age, 30) + } + + func testJSONObjectInitFromCodable() throws { + let person = Person(name: "John", age: 30) + let jsonObject = try JSONObject(person) + XCTAssertEqual(jsonObject["name"], .string("John")) + XCTAssertEqual(jsonObject["age"], .integer(30)) + } + + func testJSONObjectInitFromCodableFailure() { + // Test with a simple string, which should fail because it's not an object + XCTAssertThrowsError(try JSONObject("not an object")) + + // Test with an integer, which should also fail + XCTAssertThrowsError(try JSONObject(42)) + } + + // MARK: - Error Handling Tests + + func testInvalidJSONDecoding() { + let invalidJSON = "invalid json" + let data = invalidJSON.data(using: .utf8)! + + XCTAssertThrowsError(try AnyJSON.decoder.decode(AnyJSON.self, from: data)) + } + + func testDecodeWithCustomDecoder() throws { + let customDecoder = JSONDecoder() + customDecoder.keyDecodingStrategy = .convertFromSnakeCase + + let json: AnyJSON = ["user_name": "John", "user_age": 30] + let decoded: CustomPerson = try json.decode(as: CustomPerson.self, decoder: customDecoder) + XCTAssertEqual(decoded.userName, "John") + XCTAssertEqual(decoded.userAge, 30) + } + + // MARK: - Edge Cases + + func testEmptyObjectAndArray() { + let emptyObject: AnyJSON = [:] + let emptyArray: AnyJSON = [] + + XCTAssertEqual(emptyObject, .object([:])) + XCTAssertEqual(emptyArray, .array([])) + + XCTAssertTrue(emptyObject.objectValue?.isEmpty == true) + XCTAssertTrue(emptyArray.arrayValue?.isEmpty == true) + } + + func testNestedStructures() { + let nested: AnyJSON = [ + "level1": [ + "level2": [ + "level3": [ + "deep": "value" + ] + ] + ] + ] + + let level1 = nested.objectValue?["level1"] + let level2 = level1?.objectValue?["level2"] + let level3 = level2?.objectValue?["level3"] + let deep = level3?.objectValue?["deep"] + + XCTAssertEqual(deep, .string("value")) + } + + func testMixedArrayTypes() { + let mixedArray: AnyJSON = [1, "string", true, nil, ["nested": "value"]] + + XCTAssertEqual(mixedArray.arrayValue?[0], .integer(1)) + XCTAssertEqual(mixedArray.arrayValue?[1], .string("string")) + XCTAssertEqual(mixedArray.arrayValue?[2], .bool(true)) + XCTAssertEqual(mixedArray.arrayValue?[3], .null) + XCTAssertEqual(mixedArray.arrayValue?[4], .object(["nested": .string("value")])) + } + + func testLargeNumbers() { + let largeInt: AnyJSON = 9223372036854775807 // Int.max + let largeDouble: AnyJSON = 1.7976931348623157e+308 // Double.max + + XCTAssertEqual(largeInt.intValue, 9223372036854775807) + XCTAssertEqual(largeDouble.doubleValue, 1.7976931348623157e+308) + } + + func testSpecialStringValues() { + let emptyString: AnyJSON = "" + let unicodeString: AnyJSON = "Hello, 世界! 🌍" + let escapedString: AnyJSON = "Line 1\nLine 2\tTab" + + XCTAssertEqual(emptyString.stringValue, "") + XCTAssertEqual(unicodeString.stringValue, "Hello, 世界! 🌍") + XCTAssertEqual(escapedString.stringValue, "Line 1\nLine 2\tTab") + } } +// MARK: - Helper Types + struct CodableValue: Codable, Equatable { let integer: Int let double: Double @@ -127,3 +471,13 @@ struct CodableValue: Codable, Equatable { case anyJSON = "any_json" } } + +struct Person: Codable, Equatable { + let name: String + let age: Int +} + +struct CustomPerson: Codable, Equatable { + let userName: String + let userAge: Int +} diff --git a/Tests/HelpersTests/HTTPErrorTests.swift b/Tests/HelpersTests/HTTPErrorTests.swift new file mode 100644 index 00000000..d5ab69c3 --- /dev/null +++ b/Tests/HelpersTests/HTTPErrorTests.swift @@ -0,0 +1,153 @@ +// +// HTTPErrorTests.swift +// Supabase +// +// Created by Guilherme Souza on 07/05/24. +// + +import Foundation +import Helpers +import XCTest + +final class HTTPErrorTests: XCTestCase { + + func testInitialization() { + let data = Data("test error message".utf8) + let response = HTTPURLResponse( + url: URL(string: "https://example.com")!, + statusCode: 400, + httpVersion: "1.1", + headerFields: ["Content-Type": "application/json"] + )! + + let error = HTTPError(data: data, response: response) + + XCTAssertEqual(error.data, data) + XCTAssertEqual(error.response, response) + } + + func testLocalizedErrorDescription_WithUTF8Data() { + let data = Data("Bad Request: Invalid parameters".utf8) + let response = HTTPURLResponse( + url: URL(string: "https://example.com")!, + statusCode: 400, + httpVersion: "1.1", + headerFields: nil + )! + + let error = HTTPError(data: data, response: response) + + XCTAssertEqual( + error.errorDescription, + "Status Code: 400 Body: Bad Request: Invalid parameters" + ) + } + + func testLocalizedErrorDescription_WithEmptyData() { + let data = Data() + let response = HTTPURLResponse( + url: URL(string: "https://example.com")!, + statusCode: 404, + httpVersion: "1.1", + headerFields: nil + )! + + let error = HTTPError(data: data, response: response) + + XCTAssertEqual(error.errorDescription, "Status Code: 404 Body: ") + } + + func testLocalizedErrorDescription_WithNonUTF8Data() { + // Create data that can't be converted to UTF-8 string + let bytes: [UInt8] = [0xFF, 0xFE, 0xFD, 0xFC] + let data = Data(bytes) + let response = HTTPURLResponse( + url: URL(string: "https://example.com")!, + statusCode: 500, + httpVersion: "1.1", + headerFields: nil + )! + + let error = HTTPError(data: data, response: response) + + XCTAssertEqual(error.errorDescription, "Status Code: 500") + } + + func testLocalizedErrorDescription_WithJSONData() { + let jsonString = """ + { + "error": "Validation failed", + "details": "Email format is invalid" + } + """ + let data = Data(jsonString.utf8) + let response = HTTPURLResponse( + url: URL(string: "https://example.com")!, + statusCode: 422, + httpVersion: "1.1", + headerFields: ["Content-Type": "application/json"] + )! + + let error = HTTPError(data: data, response: response) + + XCTAssertEqual( + error.errorDescription, + "Status Code: 422 Body: \(jsonString)" + ) + } + + func testLocalizedErrorDescription_WithSpecialCharacters() { + let message = "Error with special chars: áéíóú ñ ç" + let data = Data(message.utf8) + let response = HTTPURLResponse( + url: URL(string: "https://example.com")!, + statusCode: 400, + httpVersion: "1.1", + headerFields: nil + )! + + let error = HTTPError(data: data, response: response) + + XCTAssertEqual( + error.errorDescription, + "Status Code: 400 Body: \(message)" + ) + } + + func testLocalizedErrorDescription_WithLargeData() { + let largeMessage = String(repeating: "A", count: 1000) + let data = Data(largeMessage.utf8) + let response = HTTPURLResponse( + url: URL(string: "https://example.com")!, + statusCode: 413, + httpVersion: "1.1", + headerFields: nil + )! + + let error = HTTPError(data: data, response: response) + + XCTAssertEqual( + error.errorDescription, + "Status Code: 413 Body: \(largeMessage)" + ) + } + + + func testProperties() { + let data = Data("test error".utf8) + let response = HTTPURLResponse( + url: URL(string: "https://example.com")!, + statusCode: 400, + httpVersion: "1.1", + headerFields: ["Content-Type": "application/json"] + )! + + let error = HTTPError(data: data, response: response) + + // Test that properties are correctly set + XCTAssertEqual(error.data, data) + XCTAssertEqual(error.response, response) + XCTAssertEqual(error.response.statusCode, 400) + XCTAssertEqual(error.response.url, URL(string: "https://example.com")!) + } +} \ No newline at end of file diff --git a/Tests/HelpersTests/PostgrestErrorTests.swift b/Tests/HelpersTests/PostgrestErrorTests.swift new file mode 100644 index 00000000..9f02cd29 --- /dev/null +++ b/Tests/HelpersTests/PostgrestErrorTests.swift @@ -0,0 +1,19 @@ +// +// PostgrestErrorTests.swift +// Supabase +// +// Created by Guilherme Souza on 07/05/24. +// + +import Foundation +import Helpers +import XCTest + +final class PostgrestErrorTests: XCTestCase { + + func testLocalizedErrorConformance() { + let error = PostgrestError(message: "test error message") + XCTAssertEqual(error.errorDescription, "test error message") + } + +} \ No newline at end of file