Skip to content

Commit 197c60b

Browse files
committed
Fix bug to support multple subgraphs extending entities
1 parent e92fc16 commit 197c60b

File tree

5 files changed

+72
-55
lines changed

5 files changed

+72
-55
lines changed

src/main/java/com/intuit/graphql/orchestrator/schema/transform/FederationTransformerPostMerge.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ public class FederationTransformerPostMerge implements Transformer<XtextGraph, X
4444

4545
@Override
4646
public XtextGraph transform(XtextGraph xtextGraph) {
47-
xtextGraph.getEntityExtensionsByNamespace().keySet().stream()
48-
.flatMap(namespace -> createEntityMergingContexts(namespace, xtextGraph))
49-
.peek(this::validateBaseExtensionCompatibility)
50-
.map(entityTypeMerger::mergeIntoBaseType)
51-
.forEach(Federation2PureGraphQLUtil::makeAsPureGraphQL);
47+
List<TypeDefinition> baseEntityTypes = xtextGraph.getEntityExtensionsByNamespace().keySet().stream()
48+
.flatMap(namespace -> createEntityMergingContexts(namespace, xtextGraph))
49+
.peek(this::validateBaseExtensionCompatibility)
50+
.map(entityTypeMerger::mergeIntoBaseType)
51+
.collect(Collectors.toList());
52+
53+
baseEntityTypes.forEach(Federation2PureGraphQLUtil::makeAsPureGraphQL);
5254

5355
for (FederationMetadata.EntityExtensionMetadata entityExtensionMetadata : xtextGraph.getEntityExtensionMetadatas()) {
5456
Optional<FederationMetadata.EntityMetadata> optionalEntityMetadata = xtextGraph.getFederationMetadataByNamespace()
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
1-
package com.intuit.graphql.orchestrator.integration
1+
package com.intuit.graphql.orchestrator.integration.federation
2+
23

3-
import com.google.common.collect.ImmutableMap
44
import com.intuit.graphql.orchestrator.ServiceProvider
55
import com.intuit.graphql.orchestrator.TestHelper
66
import com.intuit.graphql.orchestrator.TestServiceProvider
77
import com.intuit.graphql.orchestrator.schema.Operation
8-
import com.intuit.graphql.orchestrator.schema.RuntimeGraph
9-
import graphql.ExecutionInput
10-
import graphql.ExecutionResult
118
import graphql.schema.GraphQLObjectType
129
import graphql.schema.GraphQLSchema
1310
import helpers.BaseIntegrationTestSpecification
1411
import spock.lang.Subject
1512

16-
import static org.assertj.core.api.Assertions.assertThat
17-
18-
class StitchingTopLevelSpec extends BaseIntegrationTestSpecification {
13+
class EntityTypeSpec extends BaseIntegrationTestSpecification {
1914
ServiceProvider employeeProvider, inventoryProvider, reviewsProvider
2015

2116
@Subject
@@ -68,58 +63,27 @@ class StitchingTopLevelSpec extends BaseIntegrationTestSpecification {
6863
queryType.getFieldDefinition("getStoreByIdAndName") != null
6964
}
7065

71-
def "Federation shared value types do not conflict"(){
72-
given:
73-
def schema1 = """
74-
type Query {
75-
getProvider1Val: sharedValueType
76-
}
77-
type sharedValueType {
78-
id: ID!
79-
name: String
80-
}
81-
"""
82-
83-
def schema2 = """
84-
type Query {
85-
getProvider2Val: sharedValueType
86-
}
87-
type sharedValueType {
88-
id: ID!
89-
name: String
90-
test: String
91-
}
92-
"""
93-
94-
def valueProvider1 = TestServiceProvider.newBuilder()
95-
.namespace("A")
96-
.serviceType(ServiceProvider.ServiceType.FEDERATION_SUBGRAPH)
97-
.sdlFiles(ImmutableMap.of("schema1", schema1))
98-
.build()
99-
100-
def valueProvider2 = TestServiceProvider.newBuilder()
101-
.namespace("B")
102-
.serviceType(ServiceProvider.ServiceType.FEDERATION_SUBGRAPH)
103-
.sdlFiles(ImmutableMap.of("schema2", schema2))
104-
.build()
105-
66+
def "Federation entities can be extended with extends directive and extend keyword"() {
10667
when:
107-
specUnderTest = createGraphQLOrchestrator([valueProvider1, valueProvider2])
68+
specUnderTest = createGraphQLOrchestrator([employeeProvider, inventoryProvider, reviewsProvider])
10869

10970
then:
110-
final GraphQLObjectType queryType = specUnderTest?.runtimeGraph?.getOperation(Operation.QUERY)
111-
queryType.getFieldDefinition("getProvider1Val").type.name == "sharedValueType"
112-
queryType.getFieldDefinition("getProvider2Val").type.name == "sharedValueType"
113-
//todo verify the new field in federation spec
71+
final GraphQLSchema graphQLSchema = specUnderTest?.runtimeGraph?.getExecutableSchema()
72+
graphQLSchema.getType("Store")?.getFieldDefinition("review") != null
73+
graphQLSchema.getType("Employee")?.getFieldDefinition("review") != null
11474
}
11575

116-
def "Federation entities can be extended with extends directive and extend keyword"() {
76+
def "Federation multiple providers can extend entities"() {
11777
when:
11878
specUnderTest = createGraphQLOrchestrator([employeeProvider, inventoryProvider, reviewsProvider])
11979

12080
then:
12181
final GraphQLSchema graphQLSchema = specUnderTest?.runtimeGraph?.getExecutableSchema()
122-
graphQLSchema.getType("Store")?.getFieldDefinition("review") != null
82+
83+
graphQLSchema.getType("Employee")?.getFieldDefinition("id") != null
84+
graphQLSchema.getType("Employee")?.getFieldDefinition("username") != null
85+
graphQLSchema.getType("Employee")?.getFieldDefinition("password") != null
12386
graphQLSchema.getType("Employee")?.getFieldDefinition("review") != null
87+
graphQLSchema.getType("Employee")?.getFieldDefinition("favoriteItem") != null
12488
}
12589
}

src/test/groovy/com/intuit/graphql/orchestrator/integration/federation/ValueTypeSpec.groovy

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.intuit.graphql.orchestrator.integration.federation
22

3+
import com.google.common.collect.ImmutableMap
34
import com.intuit.graphql.orchestrator.ServiceProvider
45
import com.intuit.graphql.orchestrator.TestHelper
56
import com.intuit.graphql.orchestrator.TestServiceProvider
@@ -75,4 +76,48 @@ class ValueTypeSpec extends BaseIntegrationTestSpecification {
7576
objectType.getFieldDefinition("features") != null
7677
}
7778

79+
def "Federation shared value types do not conflict"(){
80+
given:
81+
def schema1 = """
82+
type Query {
83+
getProvider1Val: sharedValueType
84+
}
85+
type sharedValueType {
86+
id: ID!
87+
name: String
88+
}
89+
"""
90+
91+
def schema2 = """
92+
type Query {
93+
getProvider2Val: sharedValueType
94+
}
95+
type sharedValueType {
96+
id: ID!
97+
name: String
98+
test: String
99+
}
100+
"""
101+
102+
def valueProvider1 = TestServiceProvider.newBuilder()
103+
.namespace("A")
104+
.serviceType(ServiceProvider.ServiceType.FEDERATION_SUBGRAPH)
105+
.sdlFiles(ImmutableMap.of("schema1", schema1))
106+
.build()
107+
108+
def valueProvider2 = TestServiceProvider.newBuilder()
109+
.namespace("B")
110+
.serviceType(ServiceProvider.ServiceType.FEDERATION_SUBGRAPH)
111+
.sdlFiles(ImmutableMap.of("schema2", schema2))
112+
.build()
113+
114+
when:
115+
specUnderTest = createGraphQLOrchestrator([valueProvider1, valueProvider2])
116+
117+
then:
118+
final GraphQLObjectType queryType = specUnderTest?.runtimeGraph?.getOperation(Operation.QUERY)
119+
queryType.getFieldDefinition("getProvider1Val").type.name == "sharedValueType"
120+
queryType.getFieldDefinition("getProvider2Val").type.name == "sharedValueType"
121+
//todo verify the new field in federation spec
122+
}
78123
}

src/test/resources/top_level/federation/inventory.graphqls

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ type Store @key(fields: "id") {
1010
stock: [Product]
1111
}
1212

13+
type Employee @key(fields: "id") @extends {
14+
id: ID @external
15+
favoriteItem: Product
16+
}
17+
1318
type Product {
1419
name: String
1520
}

src/test/resources/top_level/federation/review.graphqls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ type Review {
1212
reviewId: ID!
1313
rating: Int!
1414
comments: String
15+
test: String
1516
}

0 commit comments

Comments
 (0)