Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ let package = Package(
.library(name: "Graphiti", targets: ["Graphiti"]),
],
dependencies: [
.package(url: "https://github.com/GraphQLSwift/GraphQL.git", from: "2.9.2"),
.package(url: "https://github.com/GraphQLSwift/GraphQL.git", from: "2.10.0"),
],
targets: [
.target(name: "Graphiti", dependencies: ["GraphQL"]),
Expand Down
12 changes: 9 additions & 3 deletions Sources/Graphiti/Input/Input.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ public final class Input<
Resolver,
Context
> {
let isOneOf: Bool
let fields: [InputFieldComponent<InputObjectType, Context>]

override func update(typeProvider: SchemaTypeProvider, coders _: Coders) throws {
let inputObjectType = try GraphQLInputObjectType(
name: name,
description: description,
fields: fields(typeProvider: typeProvider)
fields: fields(typeProvider: typeProvider),
isOneOf: isOneOf
)

try typeProvider.add(type: InputObjectType.self, as: inputObjectType)
Expand All @@ -38,8 +40,10 @@ public final class Input<
init(
type _: InputObjectType.Type,
name: String?,
isOneOf: Bool,
fields: [InputFieldComponent<InputObjectType, Context>]
) {
self.isOneOf = isOneOf
self.fields = fields
super.init(
name: name ?? Reflection.name(for: InputObjectType.self),
Expand All @@ -52,18 +56,20 @@ public extension Input {
convenience init(
_ type: InputObjectType.Type,
as name: String? = nil,
isOneOf: Bool = false,
@InputFieldComponentBuilder<InputObjectType, Context> _ fields: ()
-> InputFieldComponent<InputObjectType, Context>
) {
self.init(type: type, name: name, fields: [fields()])
self.init(type: type, name: name, isOneOf: isOneOf, fields: [fields()])
}

convenience init(
_ type: InputObjectType.Type,
as name: String? = nil,
isOneOf: Bool = false,
@InputFieldComponentBuilder<InputObjectType, Context> _ fields: ()
-> [InputFieldComponent<InputObjectType, Context>]
) {
self.init(type: type, name: name, fields: fields())
self.init(type: type, name: name, isOneOf: isOneOf, fields: fields())
}
}
6 changes: 6 additions & 0 deletions Sources/Graphiti/Scalar/Scalar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import OrderedCollections
/// you may provide your own serialize, parseValue, and parseLiteral implementations.
open class Scalar<Resolver, Context, ScalarType: Codable>: TypeComponent<Resolver, Context> {
// TODO: Change this no longer be an open class
let specifiedByURL: String?

override func update(typeProvider: SchemaTypeProvider, coders: Coders) throws {
let scalarType = try GraphQLScalarType(
name: name,
description: description,
specifiedByURL: specifiedByURL,
serialize: { value in
if let serialize = self.serialize {
return try serialize(value, coders)
Expand Down Expand Up @@ -70,10 +72,12 @@ open class Scalar<Resolver, Context, ScalarType: Codable>: TypeComponent<Resolve
init(
type _: ScalarType.Type,
name: String?,
specifiedBy: String? = nil,
serialize: ((Any, Coders) throws -> Map)? = nil,
parseValue: ((Map, Coders) throws -> Map)? = nil,
parseLiteral: ((GraphQL.Value, Coders) throws -> Map)? = nil
) {
specifiedByURL = specifiedBy
self.serialize = serialize
self.parseValue = parseValue
self.parseLiteral = parseLiteral
Expand All @@ -88,13 +92,15 @@ public extension Scalar {
convenience init(
_ type: ScalarType.Type,
as name: String? = nil,
specifiedBy: String? = nil,
serialize: ((Any, Coders) throws -> Map)? = nil,
parseValue: ((Map, Coders) throws -> Map)? = nil,
parseLiteral: ((GraphQL.Value, Coders) throws -> Map)? = nil
) {
self.init(
type: type,
name: name,
specifiedBy: specifiedBy,
serialize: serialize,
parseValue: parseValue,
parseLiteral: parseLiteral
Expand Down
85 changes: 85 additions & 0 deletions Tests/GraphitiTests/DirectiveTests/DirectiveTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,89 @@ class DirectiveTests: XCTestCase {

XCTAssertEqual(response, expected)
}

func testOneOfAcceptsGoodValue() throws {
try XCTAssertEqual(
OneOfAPI().execute(
request: """
query {
test(input: {a: "abc"}) {
a
b
}
}
""",
context: NoContext(),
on: group
).wait(),
GraphQLResult(
data: [
"test": [
"a": "abc",
"b": .null,
],
]
)
)
}

func testOneOfRejectsBadValue() throws {
try XCTAssertEqual(
OneOfAPI().execute(
request: """
query {
test(input: {a: "abc", b: 123}) {
a
b
}
}
""",
context: NoContext(),
on: group
).wait().errors[0].message,
#"OneOf Input Object "TestInputObject" must specify exactly one key."#
)
}

struct OneOfAPI: API {
struct TestObject: Codable {
let a: String?
let b: Int?
}

struct TestInputObject: Codable {
let a: String?
let b: Int?
}

struct TestArguments: Codable {
let input: TestInputObject
}

struct OneOfResolver {
func test(context _: NoContext, arguments: TestArguments) -> TestObject {
return TestObject(a: arguments.input.a, b: arguments.input.b)
}
}

let resolver = OneOfResolver()

let schema = try! Schema<OneOfResolver, NoContext> {
Type(TestObject.self) {
Field("a", at: \.a)
Field("b", at: \.b)
}

Input(TestInputObject.self, isOneOf: true) {
InputField("a", at: \.a)
InputField("b", at: \.b)
}

Query {
Field("test", at: OneOfResolver.test, as: TestObject.self) {
Argument("input", at: \.input)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ import XCTest
)
subscribers.append(subscriber)
}
return ConcurrentEventStream<T>.init(asyncStream)
return ConcurrentEventStream<T>(asyncStream)
}
}

Expand Down