Skip to content

Commit 0f46649

Browse files
committed
add tests for federation schema parsing
1 parent 680834c commit 0f46649

File tree

1 file changed

+221
-0
lines changed

1 file changed

+221
-0
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
@testable import GraphQL
2+
import XCTest
3+
4+
final class FederationTests: XCTestCase {
5+
func testFederationSampleSchema() throws {
6+
// Confirm that the Apollo test schema can be parsed as expected https://github.com/apollographql/apollo-federation-subgraph-compatibility/blob/main/COMPATIBILITY.md
7+
let source =
8+
"""
9+
extend schema
10+
@link(
11+
url: "https://specs.apollo.dev/federation/v2.0",
12+
import: [
13+
"@extends",
14+
"@external",
15+
"@key",
16+
"@inaccessible",
17+
"@override",
18+
"@provides",
19+
"@requires",
20+
"@shareable",
21+
"@tag"
22+
]
23+
)
24+
25+
type Product
26+
@key(fields: "id")
27+
@key(fields: "sku package")
28+
@key(fields: "sku variation { id }") {
29+
id: ID!
30+
sku: String
31+
package: String
32+
variation: ProductVariation
33+
dimensions: ProductDimension
34+
createdBy: User @provides(fields: "totalProductsCreated")
35+
notes: String @tag(name: "internal")
36+
research: [ProductResearch!]!
37+
}
38+
39+
type DeprecatedProduct @key(fields: "sku package") {
40+
sku: String!
41+
package: String!
42+
reason: String
43+
createdBy: User
44+
}
45+
46+
type ProductVariation {
47+
id: ID!
48+
}
49+
50+
type ProductResearch @key(fields: "study { caseNumber }") {
51+
study: CaseStudy!
52+
outcome: String
53+
}
54+
55+
type CaseStudy {
56+
caseNumber: ID!
57+
description: String
58+
}
59+
60+
type ProductDimension @shareable {
61+
size: String
62+
weight: Float
63+
unit: String @inaccessible
64+
}
65+
66+
extend type Query {
67+
product(id: ID!): Product
68+
deprecatedProduct(sku: String!, package: String!): DeprecatedProduct @deprecated(reason: "Use product query instead")
69+
}
70+
71+
extend type User @key(fields: "email") {
72+
averageProductsCreatedPerYear: Int @requires(fields: "totalProductsCreated yearsOfEmployment")
73+
email: ID! @external
74+
name: String @override(from: "users")
75+
totalProductsCreated: Int @external
76+
yearsOfEmployment: Int! @external
77+
}
78+
"""
79+
80+
let schemaExtensionDefinition = SchemaExtensionDefinition(definition: SchemaDefinition(directives: [
81+
Directive(name: nameNode("link"), arguments: [
82+
Argument(name: nameNode("url"), value: StringValue(value: "https://specs.apollo.dev/federation/v2.0", block: false)),
83+
Argument(name: nameNode("import"), value: ListValue(values: [
84+
StringValue(value: "@extends", block: false),
85+
StringValue(value: "@external", block: false),
86+
StringValue(value: "@key", block: false),
87+
StringValue(value: "@inaccessible", block: false),
88+
StringValue(value: "@override", block: false),
89+
StringValue(value: "@provides", block: false),
90+
StringValue(value: "@requires", block: false),
91+
StringValue(value: "@shareable", block: false),
92+
StringValue(value: "@tag", block: false),
93+
])
94+
),
95+
]),
96+
], operationTypes: []))
97+
98+
let productObjectTypeDefinition = ObjectTypeDefinition(name: nameNode("Product"), directives: [
99+
Directive(name: nameNode("key"), arguments: [
100+
Argument(name: nameNode("fields"), value: StringValue(value: "id", block: false)),
101+
]),
102+
Directive(name: nameNode("key"), arguments: [
103+
Argument(name: nameNode("fields"), value: StringValue(value: "sku package", block: false))
104+
]),
105+
Directive(name: nameNode("key"), arguments: [
106+
Argument(name: nameNode("fields"), value: StringValue(value: "sku variation { id }", block: false))
107+
]),
108+
], fields: [
109+
FieldDefinition(name: nameNode("id"), type: NonNullType(type: typeNode("ID"))),
110+
FieldDefinition(name: nameNode("sku"), type: typeNode("String")),
111+
FieldDefinition(name: nameNode("package"), type: typeNode("String")),
112+
FieldDefinition(name: nameNode("variation"), type: typeNode("ProductVariation")),
113+
FieldDefinition(name: nameNode("dimensions"), type: typeNode("ProductDimension")),
114+
FieldDefinition(name: nameNode("createdBy"), type: typeNode("User"), directives: [
115+
Directive(name: nameNode("provides"), arguments: [
116+
Argument(name: nameNode("fields"), value: StringValue(value: "totalProductsCreated", block: false))
117+
]),
118+
]),
119+
FieldDefinition(name: nameNode("notes"), type: typeNode("String"), directives: [
120+
Directive(name: nameNode("tag"), arguments: [
121+
Argument(name: nameNode("name"), value: StringValue(value: "internal", block: false))
122+
]),
123+
]),
124+
FieldDefinition(name: nameNode("research"), type: NonNullType(type: ListType(type: NonNullType(type: NamedType(name: nameNode("ProductResearch")))))),
125+
])
126+
127+
let deprecatedProductObjectTypeDefinition = ObjectTypeDefinition(name: nameNode("DeprecatedProduct"), directives: [
128+
Directive(name: nameNode("key"), arguments: [
129+
Argument(name: nameNode("fields"), value: StringValue(value: "sku package", block: false))
130+
]),
131+
], fields: [
132+
FieldDefinition(name: nameNode("sku"), type: NonNullType(type: typeNode("String"))),
133+
FieldDefinition(name: nameNode("package"), type: NonNullType(type: typeNode("String"))),
134+
FieldDefinition(name: nameNode("reason"), type: typeNode("String")),
135+
FieldDefinition(name: nameNode("createdBy"), type: typeNode("User")),
136+
])
137+
138+
let productVariationObjectTypeDefinition = ObjectTypeDefinition(name: nameNode("ProductVariation"), fields: [
139+
FieldDefinition(name: nameNode("id"), type: NonNullType(type: typeNode("ID"))),
140+
])
141+
142+
let productResearchObjectTypeDefinition = ObjectTypeDefinition(name: nameNode("ProductResearch"), directives: [
143+
Directive(name: nameNode("key"), arguments: [
144+
Argument(name: nameNode("fields"), value: StringValue(value: "study { caseNumber }", block: false))
145+
]),
146+
], fields: [
147+
FieldDefinition(name: nameNode("study"), type: NonNullType(type: typeNode("CaseStudy"))),
148+
FieldDefinition(name: nameNode("outcome"), type: typeNode("String")),
149+
])
150+
151+
let caseStudyObjectTypeDefinition = ObjectTypeDefinition(name: nameNode("CaseStudy"), fields: [
152+
FieldDefinition(name: nameNode("caseNumber"), type: NonNullType(type: typeNode("ID"))),
153+
FieldDefinition(name: nameNode("description"), type: typeNode("String")),
154+
])
155+
156+
let productDimensionObjectTypeDefinition = ObjectTypeDefinition(name: nameNode("ProductDimension"), directives: [
157+
Directive(name: nameNode("shareable"))
158+
], fields: [
159+
FieldDefinition(name: nameNode("size"), type: typeNode("String")),
160+
FieldDefinition(name: nameNode("weight"), type: typeNode("Float")),
161+
FieldDefinition(name: nameNode("unit"), type: typeNode("String"), directives: [
162+
Directive(name: nameNode("inaccessible"))
163+
]),
164+
])
165+
166+
let queryExtensionObjectTypeDefinition = TypeExtensionDefinition(definition: ObjectTypeDefinition(name: nameNode("Query"), fields: [
167+
FieldDefinition(name: nameNode("product"), arguments: [
168+
InputValueDefinition(name: nameNode("id"), type: NonNullType(type: NamedType(name: nameNode("ID"))))
169+
], type: typeNode("Product")),
170+
FieldDefinition(name: nameNode("deprecatedProduct"), arguments: [
171+
InputValueDefinition(name: nameNode("sku"), type: NonNullType(type: NamedType(name: nameNode("String")))),
172+
InputValueDefinition(name: nameNode("package"), type: NonNullType(type: NamedType(name: nameNode("String")))),
173+
], type: typeNode("DeprecatedProduct"), directives: [
174+
Directive(name: nameNode("deprecated"), arguments: [
175+
Argument(name: nameNode("reason"), value: StringValue(value: "Use product query instead", block: false))
176+
])
177+
])
178+
]))
179+
180+
let userExtensionObjectTypeDefinition = TypeExtensionDefinition(definition: ObjectTypeDefinition(name: nameNode("User"), directives: [
181+
Directive(name: nameNode("key"), arguments: [
182+
Argument(name: nameNode("fields"), value: StringValue(value: "email", block: false)),
183+
]),
184+
], fields: [
185+
FieldDefinition(name: nameNode("averageProductsCreatedPerYear"), type: typeNode("Int"), directives: [
186+
Directive(name: nameNode("requires"), arguments: [
187+
Argument(name: nameNode("fields"), value: StringValue(value: "totalProductsCreated yearsOfEmployment", block: false))
188+
])
189+
]),
190+
FieldDefinition(name: nameNode("email"), type: NonNullType(type: NamedType(name: nameNode("ID"))), directives: [
191+
Directive(name: nameNode("external"))
192+
]),
193+
FieldDefinition(name: nameNode("name"), type: typeNode("String"), directives: [
194+
Directive(name: nameNode("override"), arguments: [
195+
Argument(name: nameNode("from"), value: StringValue(value: "users", block: false))
196+
])
197+
]),
198+
FieldDefinition(name: nameNode("totalProductsCreated"), type: typeNode("Int"), directives: [
199+
Directive(name: nameNode("external"))
200+
]),
201+
FieldDefinition(name: nameNode("yearsOfEmployment"), type: NonNullType(type: typeNode("Int")), directives: [
202+
Directive(name: nameNode("external"))
203+
]),
204+
]))
205+
206+
let expected = Document(definitions: [
207+
schemaExtensionDefinition,
208+
productObjectTypeDefinition,
209+
deprecatedProductObjectTypeDefinition,
210+
productVariationObjectTypeDefinition,
211+
productResearchObjectTypeDefinition,
212+
caseStudyObjectTypeDefinition,
213+
productDimensionObjectTypeDefinition,
214+
queryExtensionObjectTypeDefinition,
215+
userExtensionObjectTypeDefinition,
216+
])
217+
218+
let result = try parse(source: source)
219+
XCTAssert(result == expected)
220+
}
221+
}

0 commit comments

Comments
 (0)