diff --git a/Package.resolved b/Package.resolved index 21093ae..ec9a040 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/GraphQLSwift/GraphQL.git", "state" : { - "revision" : "eedec2bbfcfd0c10c2eaee8ac2f91bde5af28b8c", - "version" : "4.0.0" + "revision" : "1e71c9a6a13d977ab452f723738e2b8665ddecd0", + "version" : "4.0.2" } }, { @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-collections", "state" : { - "revision" : "8c0c0a8b49e080e54e5e328cc552821ff07cd341", - "version" : "1.2.1" + "revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e", + "version" : "1.3.0" } } ], diff --git a/Sources/Graphiti/Field/Field/Field.swift b/Sources/Graphiti/Field/Field/Field.swift index 8ad50a8..9664e76 100644 --- a/Sources/Graphiti/Field/Field/Field.swift +++ b/Sources/Graphiti/Field/Field/Field.swift @@ -151,6 +151,4 @@ public extension Field where Arguments == NoArguments { } // We must conform KeyPath to unchecked sendable to allow keypath-based resolvers. -// Despite the warning, we cannot add `@retroactive` and keep Swift 5 support. -// Remove when support transitions to Swift 6. -extension KeyPath: @unchecked Sendable {} +extension KeyPath: @retroactive @unchecked Sendable {} diff --git a/Tests/GraphitiTests/ConnectionTests.swift b/Tests/GraphitiTests/ConnectionTests.swift index bba4498..0a892e1 100644 --- a/Tests/GraphitiTests/ConnectionTests.swift +++ b/Tests/GraphitiTests/ConnectionTests.swift @@ -1,8 +1,8 @@ import Foundation import Graphiti -import XCTest +import Testing -class ConnectionTests: XCTestCase { +struct ConnectionTests { struct Comment: Identifiable { let id: Int let message: String @@ -40,7 +40,7 @@ class ConnectionTests: XCTestCase { } /// Test that connection objects work as expected - func testConnection() async throws { + @Test func connection() async throws { let result = try await schema.execute( request: """ { @@ -64,48 +64,48 @@ class ConnectionTests: XCTestCase { resolver: .init(), context: NoContext() ) - XCTAssertEqual( - result, - .init( - data: [ - "comments": [ - "edges": [ - [ - "cursor": "MQ==", - "node": [ - "id": 1, - "message": "Hello", + #expect( + result == + .init( + data: [ + "comments": [ + "edges": [ + [ + "cursor": "MQ==", + "node": [ + "id": 1, + "message": "Hello", + ], ], - ], - [ - "cursor": "Mg==", - "node": [ - "id": 2, - "message": "What's up?", + [ + "cursor": "Mg==", + "node": [ + "id": 2, + "message": "What's up?", + ], ], - ], - [ - "cursor": "Mw==", - "node": [ - "id": 3, - "message": "Goodbye", + [ + "cursor": "Mw==", + "node": [ + "id": 3, + "message": "Goodbye", + ], ], ], + "pageInfo": [ + "hasPreviousPage": false, + "hasNextPage": false, + "startCursor": "MQ==", + "endCursor": "Mw==", + ], ], - "pageInfo": [ - "hasPreviousPage": false, - "hasNextPage": false, - "startCursor": "MQ==", - "endCursor": "Mw==", - ], - ], - ] - ) + ] + ) ) } /// Test that `first` argument works as intended - func testFirst() async throws { + @Test func first() async throws { let result = try await schema.execute( request: """ { @@ -128,33 +128,33 @@ class ConnectionTests: XCTestCase { resolver: .init(), context: NoContext() ) - XCTAssertEqual( - result, - .init( - data: [ - "comments": [ - "edges": [ - [ - "node": [ - "id": 1, - "message": "Hello", + #expect( + result == + .init( + data: [ + "comments": [ + "edges": [ + [ + "node": [ + "id": 1, + "message": "Hello", + ], ], ], + "pageInfo": [ + "hasPreviousPage": false, + "hasNextPage": true, + "startCursor": "MQ==", + "endCursor": "MQ==", + ], ], - "pageInfo": [ - "hasPreviousPage": false, - "hasNextPage": true, - "startCursor": "MQ==", - "endCursor": "MQ==", - ], - ], - ] - ) + ] + ) ) } /// Test that `after` argument works as intended - func testAfter() async throws { + @Test func after() async throws { let result = try await schema.execute( request: """ { @@ -177,39 +177,39 @@ class ConnectionTests: XCTestCase { resolver: .init(), context: NoContext() ) - XCTAssertEqual( - result, - .init( - data: [ - "comments": [ - "edges": [ - [ - "node": [ - "id": 2, - "message": "What's up?", + #expect( + result == + .init( + data: [ + "comments": [ + "edges": [ + [ + "node": [ + "id": 2, + "message": "What's up?", + ], ], - ], - [ - "node": [ - "id": 3, - "message": "Goodbye", + [ + "node": [ + "id": 3, + "message": "Goodbye", + ], ], ], + "pageInfo": [ + "hasPreviousPage": false, + "hasNextPage": false, + "startCursor": "Mg==", + "endCursor": "Mw==", + ], ], - "pageInfo": [ - "hasPreviousPage": false, - "hasNextPage": false, - "startCursor": "Mg==", - "endCursor": "Mw==", - ], - ], - ] - ) + ] + ) ) } /// Test that mixing `first` and `after` arguments works as intended - func testFirstAfter() async throws { + @Test func firstAfter() async throws { let result = try await schema.execute( request: """ { @@ -232,33 +232,33 @@ class ConnectionTests: XCTestCase { resolver: .init(), context: NoContext() ) - XCTAssertEqual( - result, - .init( - data: [ - "comments": [ - "edges": [ - [ - "node": [ - "id": 2, - "message": "What's up?", + #expect( + result == + .init( + data: [ + "comments": [ + "edges": [ + [ + "node": [ + "id": 2, + "message": "What's up?", + ], ], ], + "pageInfo": [ + "hasPreviousPage": false, + "hasNextPage": true, + "startCursor": "Mg==", + "endCursor": "Mg==", + ], ], - "pageInfo": [ - "hasPreviousPage": false, - "hasNextPage": true, - "startCursor": "Mg==", - "endCursor": "Mg==", - ], - ], - ] - ) + ] + ) ) } /// Test that `last` argument works as intended - func testLast() async throws { + @Test func last() async throws { let result = try await schema.execute( request: """ { @@ -281,33 +281,33 @@ class ConnectionTests: XCTestCase { resolver: .init(), context: NoContext() ) - XCTAssertEqual( - result, - .init( - data: [ - "comments": [ - "edges": [ - [ - "node": [ - "id": 3, - "message": "Goodbye", + #expect( + result == + .init( + data: [ + "comments": [ + "edges": [ + [ + "node": [ + "id": 3, + "message": "Goodbye", + ], ], ], + "pageInfo": [ + "hasPreviousPage": true, + "hasNextPage": false, + "startCursor": "Mw==", + "endCursor": "Mw==", + ], ], - "pageInfo": [ - "hasPreviousPage": true, - "hasNextPage": false, - "startCursor": "Mw==", - "endCursor": "Mw==", - ], - ], - ] - ) + ] + ) ) } /// Test that `before` argument works as intended - func testBefore() async throws { + @Test func before() async throws { let result = try await schema.execute( request: """ { @@ -330,39 +330,39 @@ class ConnectionTests: XCTestCase { resolver: .init(), context: NoContext() ) - XCTAssertEqual( - result, - .init( - data: [ - "comments": [ - "edges": [ - [ - "node": [ - "id": 1, - "message": "Hello", + #expect( + result == + .init( + data: [ + "comments": [ + "edges": [ + [ + "node": [ + "id": 1, + "message": "Hello", + ], ], - ], - [ - "node": [ - "id": 2, - "message": "What's up?", + [ + "node": [ + "id": 2, + "message": "What's up?", + ], ], ], + "pageInfo": [ + "hasPreviousPage": false, + "hasNextPage": false, + "startCursor": "MQ==", + "endCursor": "Mg==", + ], ], - "pageInfo": [ - "hasPreviousPage": false, - "hasNextPage": false, - "startCursor": "MQ==", - "endCursor": "Mg==", - ], - ], - ] - ) + ] + ) ) } /// Test that mixing `last` with `before` argument works as intended - func testLastBefore() async throws { + @Test func lastBefore() async throws { let result = try await schema.execute( request: """ { @@ -385,33 +385,33 @@ class ConnectionTests: XCTestCase { resolver: .init(), context: NoContext() ) - XCTAssertEqual( - result, - .init( - data: [ - "comments": [ - "edges": [ - [ - "node": [ - "id": 2, - "message": "What's up?", + #expect( + result == + .init( + data: [ + "comments": [ + "edges": [ + [ + "node": [ + "id": 2, + "message": "What's up?", + ], ], ], + "pageInfo": [ + "hasPreviousPage": true, + "hasNextPage": false, + "startCursor": "Mg==", + "endCursor": "Mg==", + ], ], - "pageInfo": [ - "hasPreviousPage": true, - "hasNextPage": false, - "startCursor": "Mg==", - "endCursor": "Mg==", - ], - ], - ] - ) + ] + ) ) } /// Test that mixing `after` with `before` argument works as intended - func testAfterBefore() async throws { + @Test func afterBefore() async throws { let result = try await schema.execute( request: """ { @@ -434,33 +434,33 @@ class ConnectionTests: XCTestCase { resolver: .init(), context: NoContext() ) - XCTAssertEqual( - result, - .init( - data: [ - "comments": [ - "edges": [ - [ - "node": [ - "id": 2, - "message": "What's up?", + #expect( + result == + .init( + data: [ + "comments": [ + "edges": [ + [ + "node": [ + "id": 2, + "message": "What's up?", + ], ], ], + "pageInfo": [ + "hasPreviousPage": false, + "hasNextPage": false, + "startCursor": "Mg==", + "endCursor": "Mg==", + ], ], - "pageInfo": [ - "hasPreviousPage": false, - "hasNextPage": false, - "startCursor": "Mg==", - "endCursor": "Mg==", - ], - ], - ] - ) + ] + ) ) } /// Test that adjusting names using `as` works - func testNaming() async throws { + @Test func naming() async throws { struct ChatObject: Codable { func messages( context _: NoContext, @@ -524,30 +524,30 @@ class ConnectionTests: XCTestCase { resolver: .init(), context: NoContext() ) - XCTAssertEqual( - result, - .init( - data: [ - "chatObject": [ - "messages": [ - "edges": [ - [ - "node": [ - "id": 1, - "text": "a", + #expect( + result == + .init( + data: [ + "chatObject": [ + "messages": [ + "edges": [ + [ + "node": [ + "id": 1, + "text": "a", + ], ], - ], - [ - "node": [ - "id": 2, - "text": "b", + [ + "node": [ + "id": 2, + "text": "b", + ], ], ], ], ], - ], - ] - ) + ] + ) ) } } diff --git a/Tests/GraphitiTests/DefaultValueTests.swift b/Tests/GraphitiTests/DefaultValueTests.swift index 81f11c5..203890d 100644 --- a/Tests/GraphitiTests/DefaultValueTests.swift +++ b/Tests/GraphitiTests/DefaultValueTests.swift @@ -1,9 +1,9 @@ import Graphiti import GraphQL -import XCTest +import Testing -class DefaultValueTests: XCTestCase { - func testBoolDefault() async throws { +struct DefaultValueTests { + @Test func boolDefault() async throws { let result = try await DefaultValueAPI().execute( request: """ { @@ -12,13 +12,13 @@ class DefaultValueTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - .init(data: ["bool": true]) + #expect( + result == + .init(data: ["bool": true]) ) } - func testIntDefault() async throws { + @Test func intDefault() async throws { let result = try await DefaultValueAPI().execute( request: """ { @@ -27,13 +27,13 @@ class DefaultValueTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - .init(data: ["int": 1]) + #expect( + result == + .init(data: ["int": 1]) ) } - func testFloatDefault() async throws { + @Test func floatDefault() async throws { let result = try await DefaultValueAPI().execute( request: """ { @@ -42,13 +42,13 @@ class DefaultValueTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - .init(data: ["float": 1.1]) + #expect( + result == + .init(data: ["float": 1.1]) ) } - func testStringDefault() async throws { + @Test func stringDefault() async throws { let result = try await DefaultValueAPI().execute( request: """ { @@ -57,13 +57,13 @@ class DefaultValueTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - .init(data: ["string": "hello"]) + #expect( + result == + .init(data: ["string": "hello"]) ) } - func testEnumDefault() async throws { + @Test func enumDefault() async throws { let result = try await DefaultValueAPI().execute( request: """ { @@ -72,13 +72,13 @@ class DefaultValueTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - .init(data: ["enum": "valueA"]) + #expect( + result == + .init(data: ["enum": "valueA"]) ) } - func testArrayDefault() async throws { + @Test func arrayDefault() async throws { let result = try await DefaultValueAPI().execute( request: """ { @@ -87,13 +87,13 @@ class DefaultValueTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - .init(data: ["array": ["a", "b", "c"]]) + #expect( + result == + .init(data: ["array": ["a", "b", "c"]]) ) } - func testInputDefault() async throws { + @Test func inputDefault() async throws { // Test input object argument default var result = try await DefaultValueAPI().execute( request: """ @@ -110,18 +110,18 @@ class DefaultValueTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - .init(data: [ - "input": [ - "bool": true, - "int": 1, - "float": 1.1, - "string": "hello", - "enum": "valueA", - "array": ["a", "b", "c"], - ], - ]) + #expect( + result == + .init(data: [ + "input": [ + "bool": true, + "int": 1, + "float": 1.1, + "string": "hello", + "enum": "valueA", + "array": ["a", "b", "c"], + ], + ]) ) // Test input object field defaults @@ -140,18 +140,18 @@ class DefaultValueTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - .init(data: [ - "input": [ - "bool": true, - "int": 1, - "float": 1.1, - "string": "hello", - "enum": "valueA", - "array": ["a", "b", "c"], - ], - ]) + #expect( + result == + .init(data: [ + "input": [ + "bool": true, + "int": 1, + "float": 1.1, + "string": "hello", + "enum": "valueA", + "array": ["a", "b", "c"], + ], + ]) ) } } diff --git a/Tests/GraphitiTests/DirectiveTests/DirectiveTests.swift b/Tests/GraphitiTests/DirectiveTests/DirectiveTests.swift index 5df7d38..de83c44 100644 --- a/Tests/GraphitiTests/DirectiveTests/DirectiveTests.swift +++ b/Tests/GraphitiTests/DirectiveTests/DirectiveTests.swift @@ -1,11 +1,11 @@ @testable import Graphiti import GraphQL -import XCTest +import Testing -class DirectiveTests: XCTestCase { +struct DirectiveTests { private let api = StarWarsAPI() - func testSkip() async throws { + @Test func skip() async throws { let query = """ query FetchHeroNameWithSkip($skipName: Boolean!) { hero { @@ -33,10 +33,10 @@ class DirectiveTests: XCTestCase { ] ) - XCTAssertEqual(response, expected) + #expect(response == expected) } - func testInclude() async throws { + @Test func include() async throws { let query = """ query FetchHeroNameWithSkip($includeName: Boolean!) { hero { @@ -64,10 +64,10 @@ class DirectiveTests: XCTestCase { ] ) - XCTAssertEqual(response, expected) + #expect(response == expected) } - func testOneOfAcceptsGoodValue() async throws { + @Test func oneOfAcceptsGoodValue() async throws { let result = try await OneOfAPI().execute( request: """ query { @@ -79,20 +79,20 @@ class DirectiveTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "test": [ - "a": "abc", - "b": .null, - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "test": [ + "a": "abc", + "b": .null, + ], + ] + ) ) } - func testOneOfRejectsBadValue() async throws { + @Test func oneOfRejectsBadValue() async throws { let result = try await OneOfAPI().execute( request: """ query { @@ -104,9 +104,9 @@ class DirectiveTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result.errors[0].message, - #"OneOf Input Object "TestInputObject" must specify exactly one key."# + #expect( + result.errors[0].message == + #"OneOf Input Object "TestInputObject" must specify exactly one key."# ) } diff --git a/Tests/GraphitiTests/FederationTests/FederationOnlySchemaTests.swift b/Tests/GraphitiTests/FederationTests/FederationOnlySchemaTests.swift index 8eeec7f..9a6b5b2 100644 --- a/Tests/GraphitiTests/FederationTests/FederationOnlySchemaTests.swift +++ b/Tests/GraphitiTests/FederationTests/FederationOnlySchemaTests.swift @@ -1,10 +1,10 @@ import Foundation import Graphiti import GraphQL -import XCTest +import Testing -final class FederationOnlySchemaTests: XCTestCase { - private var api: FederationOnlyAPI! +struct FederationOnlySchemaTests { + private var api: FederationOnlyAPI struct Profile: Codable { let name: String @@ -51,7 +51,7 @@ final class FederationOnlySchemaTests: XCTestCase { } """ - override func setUpWithError() throws { + init() throws { let schema = try SchemaBuilder(FederationOnlyResolver.self, NoContext.self) .setFederatedSDL(to: Self.federatedSDL) .add { @@ -72,10 +72,6 @@ final class FederationOnlySchemaTests: XCTestCase { api = FederationOnlyAPI(resolver: FederationOnlyResolver(), schema: schema) } - override func tearDownWithError() throws { - api = nil - } - func execute(request: String, variables: [String: Map] = [:]) async throws -> GraphQLResult { try await api.execute( request: request, @@ -84,7 +80,7 @@ final class FederationOnlySchemaTests: XCTestCase { ) } - func testUserFederationSimple() async throws { + @Test func userFederationSimple() async throws { let representations: [String: Map] = [ "representations": [ ["__typename": "User", "id": "1234"], @@ -103,19 +99,19 @@ final class FederationOnlySchemaTests: XCTestCase { """ let result = try await execute(request: query, variables: representations) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "_entities": [ - [ - "id": "1234", + #expect( + result == + GraphQLResult(data: [ + "_entities": [ + [ + "id": "1234", + ], ], - ], - ]) + ]) ) } - func testUserFederationNested() async throws { + @Test func userFederationNested() async throws { let representations: [String: Map] = [ "representations": [ ["__typename": "User", "id": "1234"], @@ -135,23 +131,23 @@ final class FederationOnlySchemaTests: XCTestCase { """ let result = try await execute(request: query, variables: representations) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "_entities": [ - [ - "id": "1234", - "profile": [ - "name": "User 1234", - "email": "1234@example.com", + #expect( + result == + GraphQLResult(data: [ + "_entities": [ + [ + "id": "1234", + "profile": [ + "name": "User 1234", + "email": "1234@example.com", + ], ], ], - ], - ]) + ]) ) } - func testUserFederationNestedOptional() async throws { + @Test func userFederationNestedOptional() async throws { let representations: [String: Map] = [ "representations": [ ["__typename": "User", "id": "1"], @@ -171,19 +167,19 @@ final class FederationOnlySchemaTests: XCTestCase { """ let result = try await execute(request: query, variables: representations) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "_entities": [ - [ - "id": "1", - "profile": [ - "name": "User 1", - "email": .null, + #expect( + result == + GraphQLResult(data: [ + "_entities": [ + [ + "id": "1", + "profile": [ + "name": "User 1", + "email": .null, + ], ], ], - ], - ]) + ]) ) } } diff --git a/Tests/GraphitiTests/FederationTests/FederationTests.swift b/Tests/GraphitiTests/FederationTests/FederationTests.swift index 14f5620..f0aeb2d 100644 --- a/Tests/GraphitiTests/FederationTests/FederationTests.swift +++ b/Tests/GraphitiTests/FederationTests/FederationTests.swift @@ -1,62 +1,60 @@ import Foundation import Graphiti import GraphQL -import XCTest +import Testing -final class FederationTests: XCTestCase { - private var api: ProductAPI! +struct FederationTests { + private var api: ProductAPI - override func setUpWithError() throws { + init() throws { + let sdl = try Self.loadSDL() let schema = try SchemaBuilder(ProductResolver.self, ProductContext.self) .use(partials: [ProductSchema()]) - .setFederatedSDL(to: loadSDL()) + .setFederatedSDL(to: sdl) .build() - api = try ProductAPI(resolver: ProductResolver(sdl: loadSDL()), schema: schema) - } - - override func tearDownWithError() throws { - api = nil + api = ProductAPI(resolver: ProductResolver(sdl: sdl), schema: schema) } // Test Queries from https://github.com/apollographql/apollo-federation-subgraph-compatibility/blob/main/COMPATIBILITY.md - func testServiceQuery() async throws { - let result = try await execute(request: query("service")) - try XCTAssertEqual( - result, - GraphQLResult(data: [ - "_service": [ - "sdl": Map(stringLiteral: loadSDL()), - ], - ]) + @Test func serviceQuery() async throws { + let result = try await execute(request: Self.query("service")) + let sdl = try Self.loadSDL() + #expect( + result == + GraphQLResult(data: [ + "_service": [ + "sdl": Map(stringLiteral: sdl), + ], + ]) ) } - func testEntityKey() async throws { + @Test func entityKey() async throws { let representations: [String: Map] = [ "representations": [ ["__typename": "User", "email": "support@apollographql.com"], ], ] - let result = try await execute(request: query("entities"), variables: representations) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "_entities": [ - [ - "email": "support@apollographql.com", - "name": "Jane Smith", - "totalProductsCreated": 1337, - "yearsOfEmployment": 10, - "averageProductsCreatedPerYear": 133, + let result = try await execute(request: Self.query("entities"), variables: representations) + #expect( + result == + GraphQLResult(data: [ + "_entities": [ + [ + "email": "support@apollographql.com", + "name": "Jane Smith", + "totalProductsCreated": 1337, + "yearsOfEmployment": 10, + "averageProductsCreatedPerYear": 133, + ], ], - ], - ]) + ]) ) } - func testEntityMultipleKey() async throws { + @Test func entityMultipleKey() async throws { let representations: [String: Map] = [ "representations": [ [ @@ -67,53 +65,53 @@ final class FederationTests: XCTestCase { ], ] - let result = try await execute(request: query("entities"), variables: representations) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "_entities": [ - [ - "sku": "apollo-federation-v1", - "package": "@apollo/federation-v1", - "reason": "Migrate to Federation V2", - "createdBy": [ - "email": "support@apollographql.com", - "name": "Jane Smith", - "totalProductsCreated": 1337, - "yearsOfEmployment": 10, - "averageProductsCreatedPerYear": 133, + let result = try await execute(request: Self.query("entities"), variables: representations) + #expect( + result == + GraphQLResult(data: [ + "_entities": [ + [ + "sku": "apollo-federation-v1", + "package": "@apollo/federation-v1", + "reason": "Migrate to Federation V2", + "createdBy": [ + "email": "support@apollographql.com", + "name": "Jane Smith", + "totalProductsCreated": 1337, + "yearsOfEmployment": 10, + "averageProductsCreatedPerYear": 133, + ], ], ], - ], - ]) + ]) ) } - func testEntityCompositeKey() async throws { + @Test func entityCompositeKey() async throws { let representations: [String: Map] = [ "representations": [ ["__typename": "ProductResearch", "study": ["caseNumber": "1234"]], ], ] - let result = try await execute(request: query("entities"), variables: representations) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "_entities": [ - [ - "study": [ - "caseNumber": "1234", - "description": "Federation Study", + let result = try await execute(request: Self.query("entities"), variables: representations) + #expect( + result == + GraphQLResult(data: [ + "_entities": [ + [ + "study": [ + "caseNumber": "1234", + "description": "Federation Study", + ], + "outcome": nil, ], - "outcome": nil, ], - ], - ]) + ]) ) } - func testEntityMultipleKeys() async throws { + @Test func entityMultipleKeys() async throws { let representations: [String: Map] = [ "representations": [ ["__typename": "Product", "id": "apollo-federation"], @@ -122,103 +120,103 @@ final class FederationTests: XCTestCase { ], ] - let result = try await execute(request: query("entities"), variables: representations) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "_entities": [ - [ - "id": "apollo-federation", - "sku": "federation", - "package": "@apollo/federation", - "variation": [ - "id": "OSS", - ], - "dimensions": [ - "size": "small", - "unit": "kg", - "weight": 1, - ], - "createdBy": [ - "email": "support@apollographql.com", - "name": "Jane Smith", - "totalProductsCreated": 1337, - "yearsOfEmployment": 10, - "averageProductsCreatedPerYear": 133, - ], - "notes": nil, - "research": [ - [ - "outcome": nil, - "study": [ - "caseNumber": "1234", - "description": "Federation Study", + let result = try await execute(request: Self.query("entities"), variables: representations) + #expect( + result == + GraphQLResult(data: [ + "_entities": [ + [ + "id": "apollo-federation", + "sku": "federation", + "package": "@apollo/federation", + "variation": [ + "id": "OSS", + ], + "dimensions": [ + "size": "small", + "unit": "kg", + "weight": 1, + ], + "createdBy": [ + "email": "support@apollographql.com", + "name": "Jane Smith", + "totalProductsCreated": 1337, + "yearsOfEmployment": 10, + "averageProductsCreatedPerYear": 133, + ], + "notes": nil, + "research": [ + [ + "outcome": nil, + "study": [ + "caseNumber": "1234", + "description": "Federation Study", + ], ], ], ], - ], - [ - "id": "apollo-federation", - "sku": "federation", - "package": "@apollo/federation", - "variation": [ - "id": "OSS", - ], - "dimensions": [ - "size": "small", - "unit": "kg", - "weight": 1, - ], - "createdBy": [ - "email": "support@apollographql.com", - "name": "Jane Smith", - "totalProductsCreated": 1337, - "yearsOfEmployment": 10, - "averageProductsCreatedPerYear": 133, - ], - "notes": nil, - "research": [ - [ - "outcome": nil, - "study": [ - "caseNumber": "1234", - "description": "Federation Study", + [ + "id": "apollo-federation", + "sku": "federation", + "package": "@apollo/federation", + "variation": [ + "id": "OSS", + ], + "dimensions": [ + "size": "small", + "unit": "kg", + "weight": 1, + ], + "createdBy": [ + "email": "support@apollographql.com", + "name": "Jane Smith", + "totalProductsCreated": 1337, + "yearsOfEmployment": 10, + "averageProductsCreatedPerYear": 133, + ], + "notes": nil, + "research": [ + [ + "outcome": nil, + "study": [ + "caseNumber": "1234", + "description": "Federation Study", + ], ], ], ], - ], - [ - "id": "apollo-studio", - "sku": "studio", - "package": "", - "variation": [ - "id": "platform", - ], - "dimensions": [ - "size": "small", - "unit": "kg", - "weight": 1, - ], - "createdBy": [ - "email": "support@apollographql.com", - "name": "Jane Smith", - "totalProductsCreated": 1337, - "yearsOfEmployment": 10, - "averageProductsCreatedPerYear": 133, - ], - "notes": nil, - "research": [ - [ - "outcome": nil, - "study": [ - "caseNumber": "1235", - "description": "Studio Study", + [ + "id": "apollo-studio", + "sku": "studio", + "package": "", + "variation": [ + "id": "platform", + ], + "dimensions": [ + "size": "small", + "unit": "kg", + "weight": 1, + ], + "createdBy": [ + "email": "support@apollographql.com", + "name": "Jane Smith", + "totalProductsCreated": 1337, + "yearsOfEmployment": 10, + "averageProductsCreatedPerYear": 133, + ], + "notes": nil, + "research": [ + [ + "outcome": nil, + "study": [ + "caseNumber": "1235", + "description": "Studio Study", + ], ], ], ], ], - ], - ]) + ]) ) } } @@ -230,7 +228,7 @@ extension FederationTests { case couldNotLoadFile } - func loadSDL() throws -> String { + static func loadSDL() throws -> String { guard let url = Bundle.module.url( forResource: "product", @@ -240,10 +238,10 @@ extension FederationTests { else { throw FederationTestsError.couldNotLoadFile } - return try String(contentsOf: url) + return try String(contentsOf: url, encoding: .utf8) } - func query(_ name: String) throws -> String { + static func query(_ name: String) throws -> String { guard let url = Bundle.module.url( forResource: name, @@ -253,7 +251,7 @@ extension FederationTests { else { throw FederationTestsError.couldNotLoadFile } - return try String(contentsOf: url) + return try String(contentsOf: url, encoding: .utf8) } func execute(request: String, variables: [String: Map] = [:]) async throws -> GraphQLResult { diff --git a/Tests/GraphitiTests/HelloWorldTests/HelloWorldAsyncTests.swift b/Tests/GraphitiTests/HelloWorldTests/HelloWorldAsyncTests.swift index 20da932..5b85360 100644 --- a/Tests/GraphitiTests/HelloWorldTests/HelloWorldAsyncTests.swift +++ b/Tests/GraphitiTests/HelloWorldTests/HelloWorldAsyncTests.swift @@ -1,322 +1,379 @@ -@testable import Graphiti -import GraphQL -import XCTest - -@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) -let pubsub = SimplePubSub() - -@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) -extension HelloResolver { - func asyncHello( - context: HelloContext, - arguments _: NoArguments - ) async -> String { - return await Task { - context.hello() - }.value - } - - func subscribeUser( - context _: HelloContext, - arguments _: NoArguments - ) async -> AsyncThrowingStream { - await pubsub.subscribe() - } - - func futureSubscribeUser( - context _: HelloContext, - arguments _: NoArguments - ) async -> AsyncThrowingStream { - await pubsub.subscribe() - } - - func asyncSubscribeUser( - context _: HelloContext, - arguments _: NoArguments - ) async -> AsyncThrowingStream { - return await Task { - await pubsub.subscribe() - }.value - } -} - -@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) -// Same as the HelloAPI, except with an async query and a few subscription fields -struct HelloAsyncAPI: API { - typealias ContextType = HelloContext - - let resolver: HelloResolver = .init() - let context: HelloContext = .init() - - let schema: Schema = try! Schema { - Scalar(Float.self) - .description( - "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point)." - ) - - Scalar(ID.self) - .description("The `ID` scalar type represents a unique identifier.") - - Type(User.self) { - Field("id", at: \.id) - Field("name", at: \.name) - Field("friends", at: \.friends) - } - - Input(UserInput.self) { - InputField("id", at: \.id) - InputField("name", at: \.name) - InputField("friends", at: \.friends) - } - - Type(UserEvent.self) { - Field("user", at: \.user) - } - - Query { - Field("hello", at: HelloResolver.hello) - Field("futureHello", at: HelloResolver.futureHello) - Field("asyncHello", at: HelloResolver.asyncHello) - - Field("float", at: HelloResolver.getFloat) { - Argument("float", at: \.float) - } - - Field("id", at: HelloResolver.getId) { - Argument("id", at: \.id) - } - - Field("user", at: HelloResolver.getUser) - } - - Mutation { - Field("addUser", at: HelloResolver.addUser) { - Argument("user", at: \.user) - } - } - - Subscription { - SubscriptionField( - "subscribeUser", - as: User.self, - atSub: HelloResolver.subscribeUser - ) - SubscriptionField( - "subscribeUserEvent", - at: User.toEvent, - atSub: HelloResolver.subscribeUser - ) - - SubscriptionField( - "futureSubscribeUser", - as: User.self, - atSub: HelloResolver.subscribeUser - ) - SubscriptionField( - "asyncSubscribeUser", - as: User.self, - atSub: HelloResolver.asyncSubscribeUser - ) - } - } -} - -@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) -class HelloWorldAsyncTests: XCTestCase { - private let api = HelloAsyncAPI() - - /// Tests that async version of API.execute works as expected - func testAsyncExecute() async throws { - let query = "{ hello }" - let result = try await api.execute( - request: query, - context: api.context - ) - XCTAssertEqual( - result, - GraphQLResult(data: ["hello": "world"]) - ) - } - - /// Tests that async fields (via ConcurrentResolve) are resolved successfully - func testAsyncHello() async throws { - let query = "{ asyncHello }" - let result = try await api.execute( - request: query, - context: api.context - ) - XCTAssertEqual( - result, - GraphQLResult(data: ["asyncHello": "world"]) - ) - } - - /// Tests subscription when the sourceEventStream type matches the resolved type (i.e. the normal resolution function should just short-circuit to the sourceEventStream object) - func testSubscriptionSelf() async throws { - let request = """ - subscription { - subscribeUser { - id - name - } - } - """ - - let subscription = try await api.subscribe( - request: request, - context: api.context - ).get() - var iterator = subscription.makeAsyncIterator() - - await pubsub.publish(event: User(id: "124", name: "Jerry", friends: nil)) - - let result = try await iterator.next() - XCTAssertEqual( - result, - GraphQLResult(data: [ - "subscribeUser": [ - "id": "124", - "name": "Jerry", - ], - ]) - ) - } - - /// Tests subscription when the sourceEventStream type does not match the resolved type (i.e. there is a non-trivial resolution function that transforms the sourceEventStream object) - func testSubscriptionEvent() async throws { - let request = """ - subscription { - subscribeUserEvent { - user { - id - name - } - } - } - """ - - let subscription = try await api.subscribe( - request: request, - context: api.context - ).get() - var iterator = subscription.makeAsyncIterator() - - await pubsub.publish(event: User(id: "124", name: "Jerry", friends: nil)) - - let result = try await iterator.next() - XCTAssertEqual( - result, - GraphQLResult(data: [ - "subscribeUserEvent": [ - "user": [ - "id": "124", - "name": "Jerry", - ], - ], - ]) - ) - } - - /// Tests that subscription resolvers that return futures work - func testFutureSubscription() async throws { - let request = """ - subscription { - futureSubscribeUser { - id - name - } - } - """ - - let subscription = try await api.subscribe( - request: request, - context: api.context - ).get() - var iterator = subscription.makeAsyncIterator() - - await pubsub.publish(event: User(id: "124", name: "Jerry", friends: nil)) - - let result = try await iterator.next() - XCTAssertEqual( - result, - GraphQLResult(data: [ - "futureSubscribeUser": [ - "id": "124", - "name": "Jerry", - ], - ]) - ) - } - - /// Tests that subscription resolvers that are async work - func testAsyncSubscription() async throws { - let request = """ - subscription { - asyncSubscribeUser { - id - name - } - } - """ - - let subscription = try await api.subscribe( - request: request, - context: api.context - ).get() - var iterator = subscription.makeAsyncIterator() - - await pubsub.publish(event: User(id: "124", name: "Jerry", friends: nil)) - - let result = try await iterator.next() - XCTAssertEqual( - result, - GraphQLResult(data: [ - "asyncSubscribeUser": [ - "id": "124", - "name": "Jerry", - ], - ]) - ) - } -} - -/// A very simple publish/subscriber used for testing -@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) -actor SimplePubSub: Sendable { - private var subscribers: [Subscriber] - - init() { - subscribers = [] - } - - func publish(event: T) { - for subscriber in subscribers { - subscriber.callback(event) - } - } - - func cancel() { - for subscriber in subscribers { - subscriber.cancel() - } - } - - func subscribe() -> AsyncThrowingStream { - return AsyncThrowingStream { continuation in - let subscriber = Subscriber( - callback: { newValue in - continuation.yield(newValue) - }, - cancel: { - continuation.finish() - } - ) - subscribers.append(subscriber) - } - } -} - -struct Subscriber { - let callback: (T) -> Void - let cancel: () -> Void -} +// @testable import Graphiti +// import GraphQL +// import Testing + +// @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) +// struct AsyncHelloResolver: Sendable { +// func hello(context: AsyncHelloContext, arguments _: NoArguments) -> String { +// context.hello() +// } + +// func futureHello( +// context: AsyncHelloContext, +// arguments _: NoArguments +// ) -> String { +// context.hello() +// } + +// struct FloatArguments: Codable { +// let float: Float +// } + +// func getFloat(context _: AsyncHelloContext, arguments: FloatArguments) -> Float { +// arguments.float +// } + +// struct IDArguments: Codable { +// let id: ID +// } + +// func getId(context _: AsyncHelloContext, arguments: IDArguments) -> ID { +// arguments.id +// } + +// func getUser(context _: AsyncHelloContext, arguments _: NoArguments) -> User { +// User(id: "123", name: "John Doe", friends: nil) +// } + +// struct AddUserArguments: Codable { +// let user: UserInput +// } + +// func addUser(context _: AsyncHelloContext, arguments: AddUserArguments) -> User { +// User(arguments.user) +// } + +// func asyncHello( +// context: AsyncHelloContext, +// arguments _: NoArguments +// ) async -> String { +// return await Task { +// context.hello() +// }.value +// } + +// func subscribeUser( +// context: AsyncHelloContext, +// arguments _: NoArguments +// ) async -> AsyncThrowingStream { +// await context.pubsub.subscribe() +// } + +// func futureSubscribeUser( +// context: AsyncHelloContext, +// arguments _: NoArguments +// ) async -> AsyncThrowingStream { +// await context.pubsub.subscribe() +// } + +// func asyncSubscribeUser( +// context: AsyncHelloContext, +// arguments _: NoArguments +// ) async -> AsyncThrowingStream { +// return await Task { +// await context.pubsub.subscribe() +// }.value +// } +// } + +// final class AsyncHelloContext: Sendable { +// let pubsub = SimplePubSub() + +// func hello() -> String { +// "world" +// } +// } + +// extension User { +// func toEvent(context _: AsyncHelloContext, arguments _: NoArguments) throws -> UserEvent { +// return UserEvent(user: self) +// } +// } + +// @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) +// struct HelloAsyncAPI: API { +// let resolver: AsyncHelloResolver = .init() + +// let schema: Schema = try! Schema { +// Scalar(Float.self) +// .description( +// "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point)." +// ) + +// Scalar(ID.self) +// .description("The `ID` scalar type represents a unique identifier.") + +// Type(User.self) { +// Field("id", at: \.id) +// Field("name", at: \.name) +// Field("friends", at: \.friends) +// } + +// Input(UserInput.self) { +// InputField("id", at: \.id) +// InputField("name", at: \.name) +// InputField("friends", at: \.friends) +// } + +// Type(UserEvent.self) { +// Field("user", at: \.user) +// } + +// Query { +// Field("hello", at: AsyncHelloResolver.hello) +// Field("futureHello", at: AsyncHelloResolver.futureHello) +// Field("asyncHello", at: AsyncHelloResolver.asyncHello) + +// Field("float", at: AsyncHelloResolver.getFloat) { +// Argument("float", at: \.float) +// } + +// Field("id", at: AsyncHelloResolver.getId) { +// Argument("id", at: \.id) +// } + +// Field("user", at: AsyncHelloResolver.getUser) +// } + +// Mutation { +// Field("addUser", at: AsyncHelloResolver.addUser) { +// Argument("user", at: \.user) +// } +// } + +// Subscription { +// SubscriptionField( +// "subscribeUser", +// as: User.self, +// atSub: AsyncHelloResolver.subscribeUser +// ) +// SubscriptionField( +// "subscribeUserEvent", +// at: User.toEvent, +// atSub: AsyncHelloResolver.subscribeUser +// ) + +// SubscriptionField( +// "futureSubscribeUser", +// as: User.self, +// atSub: AsyncHelloResolver.subscribeUser +// ) +// SubscriptionField( +// "asyncSubscribeUser", +// as: User.self, +// atSub: AsyncHelloResolver.asyncSubscribeUser +// ) +// } +// } +// } + +// struct HelloWorldAsyncTests { +// private let api = HelloAsyncAPI() + +// /// Tests that async version of API.execute works as expected +// @Test +// @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) +// func asyncExecute() async throws { +// let context = AsyncHelloContext() +// let query = "{ hello }" +// let result = try await api.execute( +// request: query, +// context: context +// ) +// #expect(result == GraphQLResult(data: ["hello": "world"])) +// } + +// /// Tests that async fields (via ConcurrentResolve) are resolved successfully +// @Test +// @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) +// func asyncHello() async throws { +// let context = AsyncHelloContext() +// let query = "{ asyncHello }" +// let result = try await api.execute( +// request: query, +// context: context +// ) +// #expect(result == GraphQLResult(data: ["asyncHello": "world"])) +// } + +// /// Tests subscription when the sourceEventStream type matches the resolved type (i.e. the normal resolution function should just short-circuit to the sourceEventStream object) +// @Test +// @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) +// func subscriptionSelf() async throws { +// let context = AsyncHelloContext() +// let request = """ +// subscription { +// subscribeUser { +// id +// name +// } +// } +// """ + +// let subscription = try await api.subscribe( +// request: request, +// context: context +// ).get() +// var iterator = subscription.makeAsyncIterator() + +// await context.pubsub.publish(event: User(id: "124", name: "Jerry", friends: nil)) + +// let result = try await iterator.next() +// #expect( +// result == +// GraphQLResult(data: [ +// "subscribeUser": [ +// "id": "124", +// "name": "Jerry", +// ], +// ]) +// ) +// } + +// /// Tests subscription when the sourceEventStream type does not match the resolved type (i.e. there is a non-trivial resolution function that transforms the sourceEventStream object) +// @Test +// @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) +// func subscriptionEvent() async throws { +// let context = AsyncHelloContext() +// let request = """ +// subscription { +// subscribeUserEvent { +// user { +// id +// name +// } +// } +// } +// """ + +// let subscription = try await api.subscribe( +// request: request, +// context: context +// ).get() +// var iterator = subscription.makeAsyncIterator() + +// await context.pubsub.publish(event: User(id: "124", name: "Jerry", friends: nil)) + +// let result = try await iterator.next() +// #expect( +// result == +// GraphQLResult(data: [ +// "subscribeUserEvent": [ +// "user": [ +// "id": "124", +// "name": "Jerry", +// ], +// ], +// ]) +// ) +// } + +// /// Tests that subscription resolvers that return futures work +// @Test +// @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) +// func futureSubscription() async throws { +// let context = AsyncHelloContext() +// let request = """ +// subscription { +// futureSubscribeUser { +// id +// name +// } +// } +// """ + +// let subscription = try await api.subscribe( +// request: request, +// context: context +// ).get() +// var iterator = subscription.makeAsyncIterator() + +// await context.pubsub.publish(event: User(id: "124", name: "Jerry", friends: nil)) + +// let result = try await iterator.next() +// #expect( +// result == +// GraphQLResult(data: [ +// "futureSubscribeUser": [ +// "id": "124", +// "name": "Jerry", +// ], +// ]) +// ) +// } + +// /// Tests that subscription resolvers that are async work +// @Test +// @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) +// func asyncSubscription() async throws { +// let context = AsyncHelloContext() +// let request = """ +// subscription { +// asyncSubscribeUser { +// id +// name +// } +// } +// """ + +// let subscription = try await api.subscribe( +// request: request, +// context: context +// ).get() +// var iterator = subscription.makeAsyncIterator() + +// await context.pubsub.publish(event: User(id: "124", name: "Jerry", friends: nil)) + +// let result = try await iterator.next() +// #expect( +// result == +// GraphQLResult(data: [ +// "asyncSubscribeUser": [ +// "id": "124", +// "name": "Jerry", +// ], +// ]) +// ) +// } +// } + +// /// A very simple publish/subscriber used for testing +// @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) +// actor SimplePubSub: Sendable { +// private var subscribers: [Subscriber] + +// init() { +// subscribers = [] +// } + +// func publish(event: T) { +// for subscriber in subscribers { +// subscriber.callback(event) +// } +// } + +// func cancel() { +// for subscriber in subscribers { +// subscriber.cancel() +// } +// } + +// func subscribe() -> AsyncThrowingStream { +// return AsyncThrowingStream { continuation in +// let subscriber = Subscriber( +// callback: { newValue in +// continuation.yield(newValue) +// }, +// cancel: { +// continuation.finish() +// } +// ) +// subscribers.append(subscriber) +// } +// } +// } + +// struct Subscriber { +// let callback: (T) -> Void +// let cancel: () -> Void +// } diff --git a/Tests/GraphitiTests/HelloWorldTests/HelloWorldTests.swift b/Tests/GraphitiTests/HelloWorldTests/HelloWorldTests.swift index 7037418..09de55d 100644 --- a/Tests/GraphitiTests/HelloWorldTests/HelloWorldTests.swift +++ b/Tests/GraphitiTests/HelloWorldTests/HelloWorldTests.swift @@ -1,6 +1,6 @@ @testable import Graphiti import GraphQL -import XCTest +import Testing struct ID: Codable { let id: String @@ -40,10 +40,6 @@ struct User { friends = nil } } - - func toEvent(context _: HelloContext, arguments _: NoArguments) throws -> UserEvent { - return UserEvent(user: self) - } } struct UserInput: Codable { @@ -155,50 +151,44 @@ struct HelloAPI: API { } } -class HelloWorldTests: XCTestCase { +struct HelloWorldTests { private let api = HelloAPI() - func testHello() async throws { + @Test func hello() async throws { let result = try await api.execute( request: "{ hello }", context: api.context ) - XCTAssertEqual( - result, - GraphQLResult(data: ["hello": "world"]) - ) + #expect(result == GraphQLResult(data: ["hello": "world"])) } - func testFutureHello() async throws { + @Test func futureHello() async throws { let result = try await api.execute( request: "{ futureHello }", context: api.context ) - XCTAssertEqual( - result, - GraphQLResult(data: ["futureHello": "world"]) - ) + #expect(result == GraphQLResult(data: ["futureHello": "world"])) } - func testBoyhowdy() async throws { + @Test func boyhowdy() async throws { let result = try await api.execute( request: "{ boyhowdy }", context: api.context ) - XCTAssertEqual( - result, - GraphQLResult( - errors: [ - GraphQLError( - message: "Cannot query field \"boyhowdy\" on type \"Query\".", - locations: [SourceLocation(line: 1, column: 3)] - ), - ] - ) + #expect( + result == + GraphQLResult( + errors: [ + GraphQLError( + message: "Cannot query field \"boyhowdy\" on type \"Query\".", + locations: [SourceLocation(line: 1, column: 3)] + ), + ] + ) ) } - func testScalar() async throws { + @Test func scalar() async throws { var result = try await api.execute( request: """ query Query($float: Float!) { @@ -208,10 +198,7 @@ class HelloWorldTests: XCTestCase { context: api.context, variables: ["float": 4] ) - XCTAssertEqual( - result, - GraphQLResult(data: ["float": 4.0]) - ) + #expect(result == GraphQLResult(data: ["float": 4.0])) result = try await api.execute( request: """ @@ -221,10 +208,7 @@ class HelloWorldTests: XCTestCase { """, context: api.context ) - XCTAssertEqual( - result, - GraphQLResult(data: ["float": 4.0]) - ) + #expect(result == GraphQLResult(data: ["float": 4.0])) result = try await api.execute( request: """ @@ -235,10 +219,7 @@ class HelloWorldTests: XCTestCase { context: api.context, variables: ["id": "85b8d502-8190-40ab-b18f-88edd297d8b6"] ) - XCTAssertEqual( - result, - GraphQLResult(data: ["id": "85b8d502-8190-40ab-b18f-88edd297d8b6"]) - ) + #expect(result == GraphQLResult(data: ["id": "85b8d502-8190-40ab-b18f-88edd297d8b6"])) result = try await api.execute( request: """ @@ -248,13 +229,10 @@ class HelloWorldTests: XCTestCase { """, context: api.context ) - XCTAssertEqual( - result, - GraphQLResult(data: ["id": "85b8d502-8190-40ab-b18f-88edd297d8b6"]) - ) + #expect(result == GraphQLResult(data: ["id": "85b8d502-8190-40ab-b18f-88edd297d8b6"])) } - func testInput() async throws { + @Test func input() async throws { let result = try await api.execute( request: """ mutation addUser($user: UserInput!) { @@ -267,15 +245,15 @@ class HelloWorldTests: XCTestCase { context: api.context, variables: ["user": ["id": "123", "name": "bob"]] ) - XCTAssertEqual( - result, - GraphQLResult( - data: ["addUser": ["id": "123", "name": "bob"]] - ) + #expect( + result == + GraphQLResult( + data: ["addUser": ["id": "123", "name": "bob"]] + ) ) } - func testInputRequest() async throws { + @Test func inputRequest() async throws { let result = try await api.execute( request: GraphQLRequest( query: """ @@ -290,15 +268,15 @@ class HelloWorldTests: XCTestCase { ), context: api.context ) - XCTAssertEqual( - result, - GraphQLResult( - data: ["addUser": ["id": "123", "name": "bob"]] - ) + #expect( + result == + GraphQLResult( + data: ["addUser": ["id": "123", "name": "bob"]] + ) ) } - func testInputRecursive() async throws { + @Test func inputRecursive() async throws { let result = try await api.execute( request: """ mutation addUser($user: UserInput!) { @@ -321,17 +299,17 @@ class HelloWorldTests: XCTestCase { ], ] ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "addUser": [ - "id": "123", - "name": "bob", - "friends": [["id": "124", "name": "jeff"]], - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "addUser": [ + "id": "123", + "name": "bob", + "friends": [["id": "124", "name": "jeff"]], + ], + ] + ) ) } } diff --git a/Tests/GraphitiTests/PartialSchemaTests.swift b/Tests/GraphitiTests/PartialSchemaTests.swift index 4bced79..4edf914 100644 --- a/Tests/GraphitiTests/PartialSchemaTests.swift +++ b/Tests/GraphitiTests/PartialSchemaTests.swift @@ -1,8 +1,8 @@ import Graphiti import GraphQL -import XCTest +import Testing -class PartialSchemaTests: XCTestCase { +struct PartialSchemaTests { class BaseSchema: PartialSchema { @TypeDefinitions override var types: Types { @@ -95,7 +95,7 @@ class PartialSchemaTests: XCTestCase { } } - func testPartialSchemaWithBuilder() async throws { + @Test func partialSchemaWithBuilder() async throws { let builder = SchemaBuilder(StarWarsResolver.self, StarWarsContext.self) builder.use(partials: [BaseSchema(), SearchSchema()]) @@ -119,17 +119,17 @@ class PartialSchemaTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "human": [ - "name": "Luke Skywalker", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "human": [ + "name": "Luke Skywalker", + ], + ]) ) } - func testPartialSchema() async throws { + @Test func partialSchema() async throws { /// Double check if static func works and the types are inferred properly let schema = try Schema.create(from: [BaseSchema(), SearchSchema()]) @@ -150,17 +150,17 @@ class PartialSchemaTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "human": [ - "name": "Luke Skywalker", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "human": [ + "name": "Luke Skywalker", + ], + ]) ) } - func testPartialSchemaOutOfOrder() async throws { + @Test func partialSchemaOutOfOrder() async throws { /// Double check if ordering of partial schema doesn't matter let schema = try Schema.create(from: [SearchSchema(), BaseSchema()]) @@ -181,17 +181,17 @@ class PartialSchemaTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "human": [ - "name": "Luke Skywalker", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "human": [ + "name": "Luke Skywalker", + ], + ]) ) } - func testInstancePartialSchema() async throws { + @Test func instancePartialSchema() async throws { let baseSchema = PartialSchema( types: { Interface(Character.self) { @@ -302,13 +302,13 @@ class PartialSchemaTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "human": [ - "name": "Luke Skywalker", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "human": [ + "name": "Luke Skywalker", + ], + ]) ) } } diff --git a/Tests/GraphitiTests/ScalarTests.swift b/Tests/GraphitiTests/ScalarTests.swift index bcb386e..d3c5116 100644 --- a/Tests/GraphitiTests/ScalarTests.swift +++ b/Tests/GraphitiTests/ScalarTests.swift @@ -1,12 +1,12 @@ import Foundation @testable import Graphiti import GraphQL -import XCTest +import Testing -class ScalarTests: XCTestCase { +struct ScalarTests { // MARK: Test UUID converts to String as expected - func testUUIDOutput() async throws { + @Test func uuidOutput() async throws { struct UUIDOutput { let value: UUID } @@ -41,17 +41,17 @@ class ScalarTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "uuid": [ - "value": "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "uuid": [ + "value": "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", + ], + ]) ) } - func testUUIDArg() async throws { + @Test func uuidArg() async throws { struct UUIDOutput { let value: UUID } @@ -92,17 +92,17 @@ class ScalarTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "uuid": [ - "value": "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "uuid": [ + "value": "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", + ], + ]) ) } - func testUUIDInput() async throws { + @Test func uuidInput() async throws { struct UUIDOutput { let value: UUID } @@ -150,19 +150,19 @@ class ScalarTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "uuid": [ - "value": "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "uuid": [ + "value": "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", + ], + ]) ) } // MARK: Test Date scalars convert to String using ISO8601 encoders - func testDateOutput() async throws { + @Test func dateOutput() async throws { struct DateOutput { let value: Date } @@ -202,17 +202,17 @@ class ScalarTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "date": [ - "value": "2001-01-01T00:00:00Z", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "date": [ + "value": "2001-01-01T00:00:00Z", + ], + ]) ) } - func testDateArg() async throws { + @Test func dateArg() async throws { struct DateOutput { let value: Date } @@ -258,17 +258,17 @@ class ScalarTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "date": [ - "value": "2001-01-01T00:00:00Z", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "date": [ + "value": "2001-01-01T00:00:00Z", + ], + ]) ) } - func testDateInput() async throws { + @Test func dateInput() async throws { struct DateOutput { let value: Date } @@ -321,19 +321,19 @@ class ScalarTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "date": [ - "value": "2001-01-01T00:00:00Z", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "date": [ + "value": "2001-01-01T00:00:00Z", + ], + ]) ) } // MARK: Test a scalar that converts to a single-value Map (StringCodedCoordinate -> String) - func testStringCoordOutput() async throws { + @Test func stringCoordOutput() async throws { struct CoordinateOutput { let value: StringCodedCoordinate } @@ -368,17 +368,17 @@ class ScalarTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "coord": [ - "value": "(0.0, 0.0)", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "coord": [ + "value": "(0.0, 0.0)", + ], + ]) ) } - func testStringCoordArg() async throws { + @Test func stringCoordArg() async throws { struct CoordinateOutput { let value: StringCodedCoordinate } @@ -419,17 +419,17 @@ class ScalarTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "coord": [ - "value": "(0.0, 0.0)", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "coord": [ + "value": "(0.0, 0.0)", + ], + ]) ) } - func testStringCoordInput() async throws { + @Test func stringCoordInput() async throws { struct CoordinateOutput { let value: StringCodedCoordinate } @@ -477,19 +477,19 @@ class ScalarTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "coord": [ - "value": "(0.0, 0.0)", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "coord": [ + "value": "(0.0, 0.0)", + ], + ]) ) } // MARK: Test a scalar that converts to a multi-value Map (Coordinate -> Dict) - func testDictCoordOutput() async throws { + @Test func dictCoordOutput() async throws { struct CoordinateOutput { let value: DictCodedCoordinate } @@ -528,17 +528,17 @@ class ScalarTests: XCTestCase { let value = result.data?.dictionary?["coord"]?.dictionary?["value"]?.dictionary - XCTAssertEqual( - value?["longitude"], - .number(0.0) + #expect( + value?["longitude"] == + .number(0.0) ) - XCTAssertEqual( - value?["latitude"], - .number(0.0) + #expect( + value?["latitude"] == + .number(0.0) ) } - func testDictCoordArg() async throws { + @Test func dictCoordArg() async throws { struct CoordinateOutput { let value: DictCodedCoordinate } @@ -583,17 +583,17 @@ class ScalarTests: XCTestCase { let value = result.data?.dictionary?["coord"]?.dictionary?["value"]?.dictionary - XCTAssertEqual( - value?["longitude"], - .number(0.0) + #expect( + value?["longitude"] == + .number(0.0) ) - XCTAssertEqual( - value?["latitude"], - .number(0.0) + #expect( + value?["latitude"] == + .number(0.0) ) } - func testDictCoordInput() async throws { + @Test func dictCoordInput() async throws { struct CoordinateOutput { let value: DictCodedCoordinate } @@ -645,20 +645,20 @@ class ScalarTests: XCTestCase { let value = result.data?.dictionary?["coord"]?.dictionary?["value"]?.dictionary - XCTAssertEqual( - value?["longitude"], - .number(0.0) + #expect( + value?["longitude"] == + .number(0.0) ) - XCTAssertEqual( - value?["latitude"], - .number(0.0) + #expect( + value?["latitude"] == + .number(0.0) ) } } private class TestAPI: API { - public let resolver: Resolver - public let schema: Schema + let resolver: Resolver + let schema: Schema init(resolver: Resolver, schema: Schema) { self.resolver = resolver diff --git a/Tests/GraphitiTests/SchemaBuilderTests.swift b/Tests/GraphitiTests/SchemaBuilderTests.swift index 8e8db85..b604b3c 100644 --- a/Tests/GraphitiTests/SchemaBuilderTests.swift +++ b/Tests/GraphitiTests/SchemaBuilderTests.swift @@ -1,9 +1,9 @@ import Graphiti import GraphQL -import XCTest +import Testing -class SchemaBuilderTests: XCTestCase { - func testSchemaBuilder() async throws { +struct SchemaBuilderTests { + @Test func schemaBuilder() async throws { let builder = SchemaBuilder(StarWarsResolver.self, StarWarsContext.self) // Add assets slightly out of order @@ -111,16 +111,16 @@ class SchemaBuilderTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "human": [ - "name": "Luke Skywalker", - ], - ]) + #expect( + result == + GraphQLResult(data: [ + "human": [ + "name": "Luke Skywalker", + ], + ]) ) - XCTAssert( + #expect( api.schema.schema.typeMap.contains(where: { key, _ in key == "PlanetConnection" }) diff --git a/Tests/GraphitiTests/SchemaTests.swift b/Tests/GraphitiTests/SchemaTests.swift index 2ac8493..0bccb6e 100644 --- a/Tests/GraphitiTests/SchemaTests.swift +++ b/Tests/GraphitiTests/SchemaTests.swift @@ -1,11 +1,11 @@ import Foundation @testable import Graphiti import GraphQL -import XCTest +import Testing -class SchemaTests: XCTestCase { +struct SchemaTests { // Tests that circularly dependent objects can be used in schema and resolved correctly - func testCircularDependencies() async throws { + @Test func circularDependencies() async throws { struct A: Codable { let name: String var b: B { @@ -56,20 +56,20 @@ class SchemaTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "a": [ - "b": [ - "name": "Circular", + #expect( + result == + GraphQLResult(data: [ + "a": [ + "b": [ + "name": "Circular", + ], ], - ], - ]) + ]) ) } // Tests that we can resolve type references for named types - func testTypeReferenceForNamedType() async throws { + @Test func typeReferenceForNamedType() async throws { struct LocationObject: Codable { let id: String let name: String @@ -122,19 +122,19 @@ class SchemaTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: [ - "user": [ - "location": [ - "name": "Earth", + #expect( + result == + GraphQLResult(data: [ + "user": [ + "location": [ + "name": "Earth", + ], ], - ], - ]) + ]) ) } - func testSchemaWithNoQuery() { + @Test func schemaWithNoQuery() { struct User: Codable { let id: String } @@ -148,19 +148,19 @@ class SchemaTests: XCTestCase { } } } catch { - XCTAssertEqual( - error as? SchemaError, - SchemaError( - description: "Schema must contain at least 1 query or federated resolver" - ) + #expect( + error as? SchemaError == + SchemaError( + description: "Schema must contain at least 1 query or federated resolver" + ) ) } } } private class TestAPI: API { - public let resolver: Resolver - public let schema: Schema + let resolver: Resolver + let schema: Schema init(resolver: Resolver, schema: Schema) { self.resolver = resolver diff --git a/Tests/GraphitiTests/StarWarsTests/StarWarsIntrospectionTests.swift b/Tests/GraphitiTests/StarWarsTests/StarWarsIntrospectionTests.swift index 6dd85dc..cdfe374 100644 --- a/Tests/GraphitiTests/StarWarsTests/StarWarsIntrospectionTests.swift +++ b/Tests/GraphitiTests/StarWarsTests/StarWarsIntrospectionTests.swift @@ -1,12 +1,12 @@ import GraphQL -import XCTest +import Testing @testable import Graphiti -class StarWarsIntrospectionTests: XCTestCase { +struct StarWarsIntrospectionTests { private let api = StarWarsAPI() - func testIntrospectionTypeQuery() async throws { + @Test func introspectionTypeQuery() async throws { let result = try await api.execute( request: """ query IntrospectionTypeQuery { @@ -19,74 +19,74 @@ class StarWarsIntrospectionTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "__schema": [ - "types": [ - [ - "name": "Boolean", - ], - [ - "name": "Character", - ], - [ - "name": "Droid", - ], - [ - "name": "Episode", - ], - [ - "name": "Human", - ], - [ - "name": "Int", - ], - [ - "name": "Planet", - ], - [ - "name": "Query", - ], - [ - "name": "SearchResult", - ], - [ - "name": "String", - ], - [ - "name": "__Directive", - ], - [ - "name": "__DirectiveLocation", - ], - [ - "name": "__EnumValue", - ], - [ - "name": "__Field", - ], - [ - "name": "__InputValue", - ], - [ - "name": "__Schema", - ], - [ - "name": "__Type", - ], - [ - "name": "__TypeKind", + #expect( + result == + GraphQLResult( + data: [ + "__schema": [ + "types": [ + [ + "name": "Boolean", + ], + [ + "name": "Character", + ], + [ + "name": "Droid", + ], + [ + "name": "Episode", + ], + [ + "name": "Human", + ], + [ + "name": "Int", + ], + [ + "name": "Planet", + ], + [ + "name": "Query", + ], + [ + "name": "SearchResult", + ], + [ + "name": "String", + ], + [ + "name": "__Directive", + ], + [ + "name": "__DirectiveLocation", + ], + [ + "name": "__EnumValue", + ], + [ + "name": "__Field", + ], + [ + "name": "__InputValue", + ], + [ + "name": "__Schema", + ], + [ + "name": "__Type", + ], + [ + "name": "__TypeKind", + ], ], ], - ], - ] - ) + ] + ) ) } - func testIntrospectionQueryTypeQuery() async throws { + @Test func introspectionQueryTypeQuery() async throws { let result = try await api.execute( request: """ query IntrospectionQueryTypeQuery { @@ -99,21 +99,21 @@ class StarWarsIntrospectionTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "__schema": [ - "queryType": [ - "name": "Query", + #expect( + result == + GraphQLResult( + data: [ + "__schema": [ + "queryType": [ + "name": "Query", + ], ], - ], - ] - ) + ] + ) ) } - func testIntrospectionDroidTypeQuery() async throws { + @Test func introspectionDroidTypeQuery() async throws { let result = try await api.execute( request: """ query IntrospectionDroidTypeQuery { @@ -124,19 +124,19 @@ class StarWarsIntrospectionTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "__type": [ - "name": "Droid", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "__type": [ + "name": "Droid", + ], + ] + ) ) } - func testIntrospectionDroidKindQuery() async throws { + @Test func introspectionDroidKindQuery() async throws { let result = try await api.execute( request: """ query IntrospectionDroidKindQuery { @@ -148,20 +148,20 @@ class StarWarsIntrospectionTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "__type": [ - "name": "Droid", - "kind": "OBJECT", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "__type": [ + "name": "Droid", + "kind": "OBJECT", + ], + ] + ) ) } - func testIntrospectionCharacterKindQuery() async throws { + @Test func introspectionCharacterKindQuery() async throws { let result = try await api.execute( request: """ query IntrospectionCharacterKindQuery { @@ -173,20 +173,20 @@ class StarWarsIntrospectionTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "__type": [ - "name": "Character", - "kind": "INTERFACE", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "__type": [ + "name": "Character", + "kind": "INTERFACE", + ], + ] + ) ) } - func testIntrospectionDroidFieldsQuery() async throws { + @Test func introspectionDroidFieldsQuery() async throws { let result = try await api.execute( request: """ query IntrospectionDroidFieldsQuery { @@ -204,63 +204,63 @@ class StarWarsIntrospectionTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "__type": [ - "name": "Droid", - "fields": [ - [ - "name": "appearsIn", - "type": [ - "name": nil, - "kind": "NON_NULL", + #expect( + result == + GraphQLResult( + data: [ + "__type": [ + "name": "Droid", + "fields": [ + [ + "name": "appearsIn", + "type": [ + "name": nil, + "kind": "NON_NULL", + ], ], - ], - [ - "name": "friends", - "type": [ - "name": nil, - "kind": "NON_NULL", + [ + "name": "friends", + "type": [ + "name": nil, + "kind": "NON_NULL", + ], ], - ], - [ - "name": "id", - "type": [ - "name": nil, - "kind": "NON_NULL", + [ + "name": "id", + "type": [ + "name": nil, + "kind": "NON_NULL", + ], ], - ], - [ - "name": "name", - "type": [ - "name": nil, - "kind": "NON_NULL", + [ + "name": "name", + "type": [ + "name": nil, + "kind": "NON_NULL", + ], ], - ], - [ - "name": "primaryFunction", - "type": [ - "name": nil, - "kind": "NON_NULL", + [ + "name": "primaryFunction", + "type": [ + "name": nil, + "kind": "NON_NULL", + ], ], - ], - [ - "name": "secretBackstory", - "type": [ - "name": "String", - "kind": "SCALAR", + [ + "name": "secretBackstory", + "type": [ + "name": "String", + "kind": "SCALAR", + ], ], ], ], - ], - ] - ) + ] + ) ) } - func testIntrospectionDroidNestedFieldsQuery() async throws { + @Test func introspectionDroidNestedFieldsQuery() async throws { let result = try await api.execute( request: """ query IntrospectionDroidNestedFieldsQuery { @@ -282,84 +282,84 @@ class StarWarsIntrospectionTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "__type": [ - "name": "Droid", - "fields": [ - [ - "name": "appearsIn", - "type": [ - "name": nil, - "kind": "NON_NULL", - "ofType": [ + #expect( + result == + GraphQLResult( + data: [ + "__type": [ + "name": "Droid", + "fields": [ + [ + "name": "appearsIn", + "type": [ "name": nil, - "kind": "LIST", + "kind": "NON_NULL", + "ofType": [ + "name": nil, + "kind": "LIST", + ], ], ], - ], - [ - "name": "friends", - "type": [ - "name": nil, - "kind": "NON_NULL", - "ofType": [ + [ + "name": "friends", + "type": [ "name": nil, - "kind": "LIST", + "kind": "NON_NULL", + "ofType": [ + "name": nil, + "kind": "LIST", + ], ], ], - ], - [ - "name": "id", - "type": [ - "name": nil, - "kind": "NON_NULL", - "ofType": [ - "name": "String", - "kind": "SCALAR", + [ + "name": "id", + "type": [ + "name": nil, + "kind": "NON_NULL", + "ofType": [ + "name": "String", + "kind": "SCALAR", + ], ], ], - ], - [ - "name": "name", - "type": [ - "name": nil, - "kind": "NON_NULL", - "ofType": [ - "name": "String", - "kind": "SCALAR", + [ + "name": "name", + "type": [ + "name": nil, + "kind": "NON_NULL", + "ofType": [ + "name": "String", + "kind": "SCALAR", + ], ], ], - ], - [ - "name": "primaryFunction", - "type": [ - "name": nil, - "kind": "NON_NULL", - "ofType": [ + [ + "name": "primaryFunction", + "type": [ + "name": nil, + "kind": "NON_NULL", + "ofType": [ + "name": "String", + "kind": "SCALAR", + ], + ], + ], + [ + "name": "secretBackstory", + "type": [ "name": "String", "kind": "SCALAR", + "ofType": nil, ], ], ], - [ - "name": "secretBackstory", - "type": [ - "name": "String", - "kind": "SCALAR", - "ofType": nil, - ], - ], ], - ], - ] - ) + ] + ) ) } - func testIntrospectionFieldArgsQuery() async throws { + @Test func introspectionFieldArgsQuery() async throws { let result = try await api.execute( request: """ query IntrospectionFieldArgsQuery { @@ -387,91 +387,91 @@ class StarWarsIntrospectionTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "__schema": [ - "queryType": [ - "fields": [ - [ - "name": "droid", - "args": [ - [ - "name": "id", - "description": "Id of the droid.", - "type": [ - "name": nil, - "kind": "NON_NULL", - "ofType": [ - "name": "String", - "kind": "SCALAR", + #expect( + result == + GraphQLResult( + data: [ + "__schema": [ + "queryType": [ + "fields": [ + [ + "name": "droid", + "args": [ + [ + "name": "id", + "description": "Id of the droid.", + "type": [ + "name": nil, + "kind": "NON_NULL", + "ofType": [ + "name": "String", + "kind": "SCALAR", + ], ], + "defaultValue": nil, ], - "defaultValue": nil, ], ], - ], - [ - "name": "hero", - "args": [ - [ - "name": "episode", - "description": "If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode.", - "type": [ - "name": "Episode", - "kind": "ENUM", - "ofType": nil, + [ + "name": "hero", + "args": [ + [ + "name": "episode", + "description": "If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode.", + "type": [ + "name": "Episode", + "kind": "ENUM", + "ofType": nil, + ], + "defaultValue": nil, ], - "defaultValue": nil, ], ], - ], - [ - "name": "human", - "args": [ - [ - "name": "id", - "description": "Id of the human.", - "type": [ - "name": nil, - "kind": "NON_NULL", - "ofType": [ - "name": "String", - "kind": "SCALAR", + [ + "name": "human", + "args": [ + [ + "name": "id", + "description": "Id of the human.", + "type": [ + "name": nil, + "kind": "NON_NULL", + "ofType": [ + "name": "String", + "kind": "SCALAR", + ], ], + "defaultValue": nil, ], - "defaultValue": nil, ], ], - ], - [ - "name": "search", - "args": [ - [ - "name": "query", - "description": nil, - "type": [ - "name": nil, - "kind": "NON_NULL", - "ofType": [ - "name": "String", - "kind": "SCALAR", + [ + "name": "search", + "args": [ + [ + "name": "query", + "description": nil, + "type": [ + "name": nil, + "kind": "NON_NULL", + "ofType": [ + "name": "String", + "kind": "SCALAR", + ], ], + "defaultValue": "\"R2-D2\"", ], - "defaultValue": "\"R2-D2\"", ], ], ], ], ], - ], - ] - ) + ] + ) ) } - func testIntrospectionDroidDescriptionQuery() async throws { + @Test func introspectionDroidDescriptionQuery() async throws { let result = try await api.execute( request: """ query IntrospectionDroidDescriptionQuery { @@ -483,16 +483,16 @@ class StarWarsIntrospectionTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "__type": [ - "name": "Droid", - "description": "A mechanical creature in the Star Wars universe.", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "__type": [ + "name": "Droid", + "description": "A mechanical creature in the Star Wars universe.", + ], + ] + ) ) } } diff --git a/Tests/GraphitiTests/StarWarsTests/StarWarsQueryTests.swift b/Tests/GraphitiTests/StarWarsTests/StarWarsQueryTests.swift index bb667a5..8e52b00 100644 --- a/Tests/GraphitiTests/StarWarsTests/StarWarsQueryTests.swift +++ b/Tests/GraphitiTests/StarWarsTests/StarWarsQueryTests.swift @@ -1,11 +1,11 @@ @testable import Graphiti import GraphQL -import XCTest +import Testing -class StarWarsQueryTests: XCTestCase { +struct StarWarsQueryTests { private let api = StarWarsAPI() - func testHeroNameQuery() async throws { + @Test func heroNameQuery() async throws { let result = try await api.execute( request: """ query HeroNameQuery { @@ -16,13 +16,13 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult(data: ["hero": ["name": "R2-D2"]]) + #expect( + result == + GraphQLResult(data: ["hero": ["name": "R2-D2"]]) ) } - func testHeroNameAndFriendsQuery() async throws { + @Test func heroNameAndFriendsQuery() async throws { let result = try await api.execute( request: """ query HeroNameAndFriendsQuery { @@ -37,25 +37,25 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "hero": [ - "id": "2001", - "name": "R2-D2", - "friends": [ - ["name": "Luke Skywalker"], - ["name": "Han Solo"], - ["name": "Leia Organa"], + #expect( + result == + GraphQLResult( + data: [ + "hero": [ + "id": "2001", + "name": "R2-D2", + "friends": [ + ["name": "Luke Skywalker"], + ["name": "Han Solo"], + ["name": "Leia Organa"], + ], ], - ], - ] - ) + ] + ) ) } - func testNestedQuery() async throws { + @Test func nestedQuery() async throws { let result = try await api.execute( request: """ query NestedQuery { @@ -73,50 +73,50 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "hero": [ - "name": "R2-D2", - "friends": [ - [ - "name": "Luke Skywalker", - "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"], - "friends": [ - ["name": "Han Solo"], - ["name": "Leia Organa"], - ["name": "C-3PO"], - ["name": "R2-D2"], + #expect( + result == + GraphQLResult( + data: [ + "hero": [ + "name": "R2-D2", + "friends": [ + [ + "name": "Luke Skywalker", + "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"], + "friends": [ + ["name": "Han Solo"], + ["name": "Leia Organa"], + ["name": "C-3PO"], + ["name": "R2-D2"], + ], ], - ], - [ - "name": "Han Solo", - "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"], - "friends": [ - ["name": "Luke Skywalker"], - ["name": "Leia Organa"], - ["name": "R2-D2"], + [ + "name": "Han Solo", + "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"], + "friends": [ + ["name": "Luke Skywalker"], + ["name": "Leia Organa"], + ["name": "R2-D2"], + ], ], - ], - [ - "name": "Leia Organa", - "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"], - "friends": [ - ["name": "Luke Skywalker"], - ["name": "Han Solo"], - ["name": "C-3PO"], - ["name": "R2-D2"], + [ + "name": "Leia Organa", + "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"], + "friends": [ + ["name": "Luke Skywalker"], + ["name": "Han Solo"], + ["name": "C-3PO"], + ["name": "R2-D2"], + ], ], ], ], - ], - ] - ) + ] + ) ) } - func testFetchLukeQuery() async throws { + @Test func fetchLukeQuery() async throws { let result = try await api.execute( request: """ query FetchLukeQuery { @@ -127,19 +127,19 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "human": [ - "name": "Luke Skywalker", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "human": [ + "name": "Luke Skywalker", + ], + ] + ) ) } - func testFetchSomeIDQuery() async throws { + @Test func fetchSomeIDQuery() async throws { var result = try await api.execute( request: """ query FetchSomeIDQuery($someId: String!) { @@ -151,15 +151,15 @@ class StarWarsQueryTests: XCTestCase { context: StarWarsContext(), variables: ["someId": "1000"] ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "human": [ - "name": "Luke Skywalker", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "human": [ + "name": "Luke Skywalker", + ], + ] + ) ) result = try await api.execute( @@ -173,15 +173,15 @@ class StarWarsQueryTests: XCTestCase { context: StarWarsContext(), variables: ["someId": "1002"] ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "human": [ - "name": "Han Solo", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "human": [ + "name": "Han Solo", + ], + ] + ) ) result = try await api.execute( @@ -195,17 +195,17 @@ class StarWarsQueryTests: XCTestCase { context: StarWarsContext(), variables: ["someId": "not a valid id"] ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "human": nil, - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "human": nil, + ] + ) ) } - func testFetchLukeAliasedQuery() async throws { + @Test func fetchLukeAliasedQuery() async throws { let result = try await api.execute( request: """ query FetchLukeAliasedQuery { @@ -216,19 +216,19 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "luke": [ - "name": "Luke Skywalker", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "luke": [ + "name": "Luke Skywalker", + ], + ] + ) ) } - func testFetchLukeAndLeiaAliasedQuery() async throws { + @Test func fetchLukeAndLeiaAliasedQuery() async throws { let result = try await api.execute( request: """ query FetchLukeAndLeiaAliasedQuery { @@ -242,22 +242,22 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "luke": [ - "name": "Luke Skywalker", - ], - "leia": [ - "name": "Leia Organa", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "luke": [ + "name": "Luke Skywalker", + ], + "leia": [ + "name": "Leia Organa", + ], + ] + ) ) } - func testDuplicateFieldsQuery() async throws { + @Test func duplicateFieldsQuery() async throws { let result = try await api.execute( request: """ query DuplicateFieldsQuery { @@ -273,24 +273,24 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "luke": [ - "name": "Luke Skywalker", - "homePlanet": ["name": "Tatooine"], - ], - "leia": [ - "name": "Leia Organa", - "homePlanet": ["name": "Alderaan"], - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "luke": [ + "name": "Luke Skywalker", + "homePlanet": ["name": "Tatooine"], + ], + "leia": [ + "name": "Leia Organa", + "homePlanet": ["name": "Alderaan"], + ], + ] + ) ) } - func testUseFragmentQuery() async throws { + @Test func useFragmentQuery() async throws { let result = try await api.execute( request: """ query UseFragmentQuery { @@ -308,24 +308,24 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "luke": [ - "name": "Luke Skywalker", - "homePlanet": ["name": "Tatooine"], - ], - "leia": [ - "name": "Leia Organa", - "homePlanet": ["name": "Alderaan"], - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "luke": [ + "name": "Luke Skywalker", + "homePlanet": ["name": "Tatooine"], + ], + "leia": [ + "name": "Leia Organa", + "homePlanet": ["name": "Alderaan"], + ], + ] + ) ) } - func testCheckTypeOfR2Query() async throws { + @Test func checkTypeOfR2Query() async throws { let result = try await api.execute( request: """ query CheckTypeOfR2Query { @@ -337,20 +337,20 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "hero": [ - "__typename": "Droid", - "name": "R2-D2", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "hero": [ + "__typename": "Droid", + "name": "R2-D2", + ], + ] + ) ) } - func testCheckTypeOfLukeQuery() async throws { + @Test func checkTypeOfLukeQuery() async throws { let result = try await api.execute( request: """ query CheckTypeOfLukeQuery { @@ -362,20 +362,20 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "hero": [ - "__typename": "Human", - "name": "Luke Skywalker", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "hero": [ + "__typename": "Human", + "name": "Luke Skywalker", + ], + ] + ) ) } - func testSecretBackstoryQuery() async throws { + @Test func secretBackstoryQuery() async throws { let result = try await api.execute( request: """ query SecretBackstoryQuery { @@ -387,27 +387,27 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "hero": [ - "name": "R2-D2", - "secretBackstory": nil, + #expect( + result == + GraphQLResult( + data: [ + "hero": [ + "name": "R2-D2", + "secretBackstory": nil, + ], ], - ], - errors: [ - GraphQLError( - message: "secretBackstory is secret.", - locations: [SourceLocation(line: 4, column: 9)], - path: ["hero", "secretBackstory"] - ), - ] - ) + errors: [ + GraphQLError( + message: "secretBackstory is secret.", + locations: [SourceLocation(line: 4, column: 9)], + path: ["hero", "secretBackstory"] + ), + ] + ) ) } - func testSecretBackstoryListQuery() async throws { + @Test func secretBackstoryListQuery() async throws { let result = try await api.execute( request: """ query SecretBackstoryListQuery { @@ -422,50 +422,50 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "hero": [ - "name": "R2-D2", - "friends": [ - [ - "name": "Luke Skywalker", - "secretBackstory": nil, - ], - [ - "name": "Han Solo", - "secretBackstory": nil, - ], - [ - "name": "Leia Organa", - "secretBackstory": nil, + #expect( + result == + GraphQLResult( + data: [ + "hero": [ + "name": "R2-D2", + "friends": [ + [ + "name": "Luke Skywalker", + "secretBackstory": nil, + ], + [ + "name": "Han Solo", + "secretBackstory": nil, + ], + [ + "name": "Leia Organa", + "secretBackstory": nil, + ], ], ], ], - ], - errors: [ - GraphQLError( - message: "secretBackstory is secret.", - locations: [SourceLocation(line: 6, column: 13)], - path: ["hero", "friends", 0, "secretBackstory"] - ), - GraphQLError( - message: "secretBackstory is secret.", - locations: [SourceLocation(line: 6, column: 13)], - path: ["hero", "friends", 1, "secretBackstory"] - ), - GraphQLError( - message: "secretBackstory is secret.", - locations: [SourceLocation(line: 6, column: 13)], - path: ["hero", "friends", 2, "secretBackstory"] - ), - ] - ) + errors: [ + GraphQLError( + message: "secretBackstory is secret.", + locations: [SourceLocation(line: 6, column: 13)], + path: ["hero", "friends", 0, "secretBackstory"] + ), + GraphQLError( + message: "secretBackstory is secret.", + locations: [SourceLocation(line: 6, column: 13)], + path: ["hero", "friends", 1, "secretBackstory"] + ), + GraphQLError( + message: "secretBackstory is secret.", + locations: [SourceLocation(line: 6, column: 13)], + path: ["hero", "friends", 2, "secretBackstory"] + ), + ] + ) ) } - func testSecretBackstoryAliasQuery() async throws { + @Test func secretBackstoryAliasQuery() async throws { let result = try await api.execute( request: """ query SecretBackstoryAliasQuery { @@ -477,27 +477,27 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "mainHero": [ - "name": "R2-D2", - "story": nil, + #expect( + result == + GraphQLResult( + data: [ + "mainHero": [ + "name": "R2-D2", + "story": nil, + ], ], - ], - errors: [ - GraphQLError( - message: "secretBackstory is secret.", - locations: [SourceLocation(line: 4, column: 9)], - path: ["mainHero", "story"] - ), - ] - ) + errors: [ + GraphQLError( + message: "secretBackstory is secret.", + locations: [SourceLocation(line: 4, column: 9)], + path: ["mainHero", "story"] + ), + ] + ) ) } - func testNonNullableFieldsQuery() async throws { + @Test func nonNullableFieldsQuery() async throws { struct A { func nullableA(context _: NoContext, arguments _: NoArguments) -> A? { return A() @@ -555,26 +555,26 @@ class StarWarsQueryTests: XCTestCase { """, context: NoContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "nullableA": [ - "nullableA": nil, + #expect( + result == + GraphQLResult( + data: [ + "nullableA": [ + "nullableA": nil, + ], ], - ], - errors: [ - GraphQLError( - message: "catch me if you can.", - locations: [SourceLocation(line: 6, column: 21)], - path: ["nullableA", "nullableA", "nonNullA", "nonNullA", "throws"] - ), - ] - ) + errors: [ + GraphQLError( + message: "catch me if you can.", + locations: [SourceLocation(line: 6, column: 21)], + path: ["nullableA", "nullableA", "nonNullA", "nonNullA", "throws"] + ), + ] + ) ) } - func testSearchQuery() async throws { + @Test func searchQuery() async throws { let result = try await api.execute( request: """ query { @@ -595,22 +595,22 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "search": [ - ["name": "Tatooine", "diameter": 10465], - ["name": "Han Solo"], - ["name": "Leia Organa"], - ["name": "C-3PO", "primaryFunction": "Protocol"], - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "search": [ + ["name": "Tatooine", "diameter": 10465], + ["name": "Han Solo"], + ["name": "Leia Organa"], + ["name": "C-3PO", "primaryFunction": "Protocol"], + ], + ] + ) ) } - func testDirective() async throws { + @Test func directive() async throws { var result = try await api.execute( request: """ query Hero { @@ -625,15 +625,15 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "hero": [ - "name": "R2-D2", - ], - ] - ) + #expect( + result == + GraphQLResult( + data: [ + "hero": [ + "name": "R2-D2", + ], + ] + ) ) result = try await api.execute( @@ -650,20 +650,20 @@ class StarWarsQueryTests: XCTestCase { """, context: StarWarsContext() ) - XCTAssertEqual( - result, - GraphQLResult( - data: [ - "hero": [ - "name": "R2-D2", - "friends": [ - ["name": "Luke Skywalker"], - ["name": "Han Solo"], - ["name": "Leia Organa"], + #expect( + result == + GraphQLResult( + data: [ + "hero": [ + "name": "R2-D2", + "friends": [ + ["name": "Luke Skywalker"], + ["name": "Han Solo"], + ["name": "Leia Organa"], + ], ], - ], - ] - ) + ] + ) ) } } diff --git a/Tests/GraphitiTests/UnionTests.swift b/Tests/GraphitiTests/UnionTests.swift index 4a83251..72fc7bd 100644 --- a/Tests/GraphitiTests/UnionTests.swift +++ b/Tests/GraphitiTests/UnionTests.swift @@ -1,10 +1,10 @@ import Foundation @testable import Graphiti import GraphQL -import XCTest +import Testing -class UnionTests: XCTestCase { - func testUnionInit() throws { +struct UnionTests { + @Test func unionInit() throws { _ = try Schema { Type(Planet.self) { Field("id", at: \.id) diff --git a/Tests/GraphitiTests/ValidationRulesTests.swift b/Tests/GraphitiTests/ValidationRulesTests.swift index ecf166b..5fe63d6 100644 --- a/Tests/GraphitiTests/ValidationRulesTests.swift +++ b/Tests/GraphitiTests/ValidationRulesTests.swift @@ -1,11 +1,11 @@ import Foundation @testable import Graphiti import GraphQL -import XCTest +import Testing -class ValidationRulesTests: XCTestCase { +struct ValidationRulesTests { // Test registering custom validation rules - func testRegisteringCustomValidationRule() async throws { + @Test func registeringCustomValidationRule() async throws { struct TestResolver { var helloWorld: String { "Hellow World" } } @@ -32,21 +32,21 @@ class ValidationRulesTests: XCTestCase { context: NoContext(), validationRules: [NoIntrospectionRule] ) - XCTAssertEqual( - result, - GraphQLResult(errors: [ - .init( - message: "GraphQL introspection is not allowed, but the query contained __schema or __type", - locations: [.init(line: 2, column: 3)] - ), - ]) + #expect( + result == + GraphQLResult(errors: [ + .init( + message: "GraphQL introspection is not allowed, but the query contained __schema or __type", + locations: [.init(line: 2, column: 3)] + ), + ]) ) } } private class TestAPI: API { - public let resolver: Resolver - public let schema: Schema + let resolver: Resolver + let schema: Schema init(resolver: Resolver, schema: Schema) { self.resolver = resolver