diff --git a/Sources/Apollo/GraphQLExecutor.swift b/Sources/Apollo/GraphQLExecutor.swift index ac7e83b803..1d4b2b684b 100644 --- a/Sources/Apollo/GraphQLExecutor.swift +++ b/Sources/Apollo/GraphQLExecutor.swift @@ -286,7 +286,7 @@ final class GraphQLExecutor { } case let .typeCase(typeCase): - #warning("Write extensive tests for this.") + #warning("Write extensive tests for this. Multiple merged sibling type cases.") if let runtimeType = runtimeType, runtimeType._canBeConverted(to: typeCase.typeCondition) { try groupFields(typeCase.selectionSet.selections, forRuntimeType: runtimeType, @@ -390,10 +390,18 @@ final class GraphQLExecutor { elementFieldInfo.cachePath.append(indexSegment) } - return self.complete(fields: elementFieldInfo, - withValue: element, - asType: innerType, - accumulator: accumulator) + return self + .complete(fields: elementFieldInfo, + withValue: element, + asType: innerType, + accumulator: accumulator) + .mapError { error in + if !(error is GraphQLResultError) { + return GraphQLResultError(path: elementFieldInfo.responsePath, underlying: error) + } else { + return error + } + } } return lazilyEvaluateAll(completedArray).map { diff --git a/Sources/ApolloAPI/CodegenV1/GraphQLEnum.swift b/Sources/ApolloAPI/CodegenV1/GraphQLEnum.swift index b1895ee047..6ef3e7b22e 100644 --- a/Sources/ApolloAPI/CodegenV1/GraphQLEnum.swift +++ b/Sources/ApolloAPI/CodegenV1/GraphQLEnum.swift @@ -52,7 +52,7 @@ where T: RawRepresentable & CaseIterable, T.RawValue == String { extension GraphQLEnum: CustomScalarType { public init(jsonValue: JSONValue) throws { guard let stringData = jsonValue as? String else { - throw CacheError.Reason.unrecognizedCacheData(jsonValue, forType: Self.self) + throw JSONDecodingError.couldNotConvert(value: jsonValue, to: String.self) } self.init(rawValue: stringData) } diff --git a/Sources/ApolloAPI/ScalarTypes.swift b/Sources/ApolloAPI/ScalarTypes.swift index 5a3d311f4b..8a36a09cdb 100644 --- a/Sources/ApolloAPI/ScalarTypes.swift +++ b/Sources/ApolloAPI/ScalarTypes.swift @@ -21,6 +21,7 @@ extension ScalarType { public var asInputValue: InputValue { .scalar(self) } } +#warning("TODO: do we really need to have both scalar and custom scalar?") public protocol CustomScalarType: AnyScalarType, JSONDecodable, @@ -36,5 +37,7 @@ extension CustomScalarType { try Self.init(jsonValue: cacheData) } - @inlinable public static var asOutputType: Selection.Field.OutputType { .customScalar(self) } + @inlinable public static var asOutputType: Selection.Field.OutputType { + .nonNull(.customScalar(self)) + } } diff --git a/Tests/ApolloTests/GraphQLExecutor_SelectionSetMapper_FromResponse_Tests.swift b/Tests/ApolloTests/GraphQLExecutor_SelectionSetMapper_FromResponse_Tests.swift index 3e1a75f2a3..7c197c7ab5 100644 --- a/Tests/ApolloTests/GraphQLExecutor_SelectionSetMapper_FromResponse_Tests.swift +++ b/Tests/ApolloTests/GraphQLExecutor_SelectionSetMapper_FromResponse_Tests.swift @@ -137,7 +137,7 @@ class GraphQLExecutor_SelectionSetMapper_FromResponse_Tests: XCTestCase { class GivenSelectionSet: MockSelectionSet { override class var selections: [Selection] { [Selection.field("name", String?.self)] } } - let object: JSONObject = ["name": "Luke Skywalker"] + let object: JSONObject = [:] // when XCTAssertThrowsError(try readValues(GivenSelectionSet.self, from: object)) { (error) in @@ -257,7 +257,9 @@ class GraphQLExecutor_SelectionSetMapper_FromResponse_Tests: XCTestCase { func test__nonnull_enum__givenDataHasNullValueForField_throwsNullValueError() { // given class GivenSelectionSet: MockSelectionSet { - override class var selections: [Selection] { [Selection.field("size", GraphQLEnum.self)] } + override class var selections: [Selection] {[ + Selection.field("size", GraphQLEnum.self) + ]} } let object: JSONObject = ["size": NSNull()] @@ -419,16 +421,15 @@ class GraphQLExecutor_SelectionSetMapper_FromResponse_Tests: XCTestCase { class GivenSelectionSet: MockSelectionSet { override class var selections: [Selection] { [Selection.field("favorites", [String].self)] } } - let object: JSONObject = ["favorites": [10, 20.0, 30]] + let object: JSONObject = ["favorites": [10.0, 20.0, 30]] // when XCTAssertThrowsError(try readValues(GivenSelectionSet.self, from: object)) { (error) in // then if let error = error as? GraphQLResultError, case JSONDecodingError.couldNotConvert(let value, let expectedType) = error.underlying { - XCTAssertEqual(error.path, ["favorites", "1"]) - #warning("Does this need the index 1 path?") - XCTAssertEqual(value as? Double, 4.0) + XCTAssertEqual(error.path, ["favorites", "0"]) + XCTAssertEqual(value as? Double, 10.0) XCTAssertTrue(expectedType == String.self) } else { XCTFail("Unexpected error: \(error)") @@ -518,15 +519,14 @@ class GraphQLExecutor_SelectionSetMapper_FromResponse_Tests: XCTestCase { class GivenSelectionSet: MockSelectionSet { override class var selections: [Selection] { [Selection.field("favorites", [String]?.self)] } } - let object: JSONObject = ["favorites": [10, 20.0, 30]] + let object: JSONObject = ["favorites": [4.0, 20.0, 30]] // when XCTAssertThrowsError(try readValues(GivenSelectionSet.self, from: object)) { (error) in // then if let error = error as? GraphQLResultError, case JSONDecodingError.couldNotConvert(let value, let expectedType) = error.underlying { - XCTAssertEqual(error.path, ["favorites", "1"]) - #warning("Does this need the index 1 path?") + XCTAssertEqual(error.path, ["favorites", "0"]) XCTAssertEqual(value as? Double, 4.0) XCTAssertTrue(expectedType == String.self) } else {