Skip to content

Commit

Permalink
Merge pull request #24 from abidon/feature/preserve-query-fields-order
Browse files Browse the repository at this point in the history
Ordering fields as in GQL query
  • Loading branch information
alexsteinerde authored Jan 9, 2024
2 parents e17518f + dba110d commit 8179cae
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 1 deletion.
14 changes: 13 additions & 1 deletion Sources/GraphQLKit/Graphiti+Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,16 @@ enum GraphQLResolveError: Swift.Error {
case noQueryFound
}

extension GraphQLResult: Content { }
extension GraphQLResult: Content {
public func encodeResponse(for request: Request) -> EventLoopFuture<Response> {
return request.eventLoop.submit {
Response(
status: .ok,
headers: [
"Content-Type": "application/json"
],
body: .init(data: try GraphQLJSONEncoder().encode(self))
)
}
}
}
115 changes: 115 additions & 0 deletions Tests/GraphQLKitTests/GraphQLKitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ final class GraphQLKitTests: XCTestCase {
}
}

struct Address: Content {
public var number: Int
public var streetName: String
public var additionalStreetName: String?
public var city: String
public var postalCode: String
public var country: String
}

struct Person: Content {
public var firstName: String
public var lastName: String
public var age: UInt
public var address: Address
}

struct ProtectedResolver {
func test(store: Request, _: NoArguments) throws -> String {
_ = try store.auth.require(SomeBearerAuthenticator.User.self)
Expand All @@ -48,6 +64,16 @@ final class GraphQLKitTests: XCTestCase {
func number(store: Request, _: NoArguments) -> Int {
42
}

func person(store: Request, _: NoArguments) throws -> Person {
return Person(firstName: "John", lastName: "Appleseed", age: 42, address: Address(
number: 767,
streetName: "Fifth Avenue",
city: "New York",
postalCode: "NY 10153",
country: "United States"
))
}
}

let protectedSchema = try! Schema<ProtectedResolver, Request> {
Expand All @@ -58,9 +84,28 @@ final class GraphQLKitTests: XCTestCase {
}

let schema = try! Schema<Resolver, Request> {
Scalar(UInt.self)

Type(Address.self) {
Field("additionalStreetName", at: \Address.additionalStreetName)
Field("city", at: \Address.city)
Field("country", at: \Address.country)
Field("number", at: \Address.number)
Field("postalCode", at: \Address.postalCode)
Field("streetName", at: \Address.streetName)
}

Type(Person.self) {
Field("address", at: \Person.address)
Field("age", at: \Person.age)
Field("firstName", at: \Person.firstName)
Field("lastName", at: \Person.lastName)
}

Query {
Field("test", at: Resolver.test)
Field("number", at: Resolver.number)
Field("person", at: Resolver.person)
}
}

Expand Down Expand Up @@ -232,6 +277,76 @@ final class GraphQLKitTests: XCTestCase {
}
}

func testFieldsOrder() throws {
let query1Request = QueryRequest(query: // this query returns fields in arbitrary order
"""
query {
person {
firstName
lastName
age
address {
number
streetName
city
postalCode
country
}
}
}
""", operationName: nil, variables: nil)
let query2Request = QueryRequest(query: // this query will return all fields in alphabetical order
"""
query {
person {
address {
city
country
number
postalCode
streetName
}
age
firstName
lastName
}
}
""", operationName: nil, variables: nil)
let data1 = String(data: try! JSONEncoder().encode(query1Request), encoding: .utf8)!
let data2 = String(data: try! JSONEncoder().encode(query2Request), encoding: .utf8)!

let app = Application(.testing)
defer { app.shutdown() }

app.register(graphQLSchema: schema, withResolver: Resolver())

var body1 = ByteBufferAllocator().buffer(capacity: 0)
body1.writeString(data1)
var headers1 = HTTPHeaders()
headers1.replaceOrAdd(name: .contentLength, value: body1.readableBytes.description)
headers1.contentType = .json

var body2 = ByteBufferAllocator().buffer(capacity: 0)
body2.writeString(data2)
var headers2 = HTTPHeaders()
headers2.replaceOrAdd(name: .contentLength, value: body2.readableBytes.description)
headers2.contentType = .json

try app.testable().test(.POST, "/graphql", headers: headers1, body: body1) { res in
XCTAssertEqual(res.status, .ok)
var res = res
let expected = #"{"data":{"person":{"firstName":"John","lastName":"Appleseed","age":42,"address":{"number":767,"streetName":"Fifth Avenue","city":"New York","postalCode":"NY 10153","country":"United States"}}}}"#
XCTAssertEqual(res.body.readString(length: expected.count), expected)
}

try app.testable().test(.POST, "/graphql", headers: headers2, body: body2) { res in
XCTAssertEqual(res.status, .ok)
var res = res
let expected = #"{"data":{"person":{"address":{"city":"New York","country":"United States","number":767,"postalCode":"NY 10153","streetName":"Fifth Avenue"},"age":42,"firstName":"John","lastName":"Appleseed"}}}"#
XCTAssertEqual(res.body.readString(length: expected.count), expected)
}
}

func testEnum() throws {
enum TodoState: String, Codable, CaseIterable {
case open
Expand Down

0 comments on commit 8179cae

Please sign in to comment.