Skip to content

Commit c98ebf7

Browse files
committed
some docs about how type in ESI works plus test
1 parent 987fd78 commit c98ebf7

File tree

3 files changed

+118
-3
lines changed

3 files changed

+118
-3
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ docs/_build/
1313
\.classpath
1414
\.project
1515
\.settings/
16-
/.nb-gradle/
16+
/.nb-gradle/
17+
gen

src/main/java/graphql/execution/ExecutionStepInfo.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import graphql.schema.GraphQLTypeUtil;
1010

1111
import java.util.Collections;
12-
import java.util.LinkedHashMap;
1312
import java.util.Map;
1413
import java.util.function.Consumer;
1514

@@ -27,11 +26,41 @@
2726
@PublicApi
2827
public class ExecutionStepInfo {
2928

29+
/**
30+
* An ExecutionStepInfo represent either a field or a list element inside a list of objects/interfaces/unions.
31+
*
32+
* A StepInfo never represent a Scalar/Enum inside a list (e.g. [String]) because GraphQL execution doesn't descend down
33+
* scalar/enums lists.
34+
*
35+
*/
36+
37+
/**
38+
* If this StepInfo represent a field the type is equal to fieldDefinition.getType()
39+
*
40+
* if this StepInfo is a list element this type is the actual current list element. For example:
41+
* Query.pets: [[Pet]] with Pet either a Dog or Cat and the actual result is [[Dog1],[[Cat1]]
42+
* Then the type is (for a query "{pets{name}}"):
43+
* [[Pet]] for /pets (representing the field Query.pets, not a list element)
44+
* [Pet] fot /pets[0]
45+
* [Pet] for /pets[1]
46+
* Dog for /pets[0][0]
47+
* Cat for /pets[1][0]
48+
* String for /pets[0][0]/name (representing the field Dog.name, not a list element)
49+
* String for /pets[1][0]/name (representing the field Cat.name, not a list element)
50+
*/
3051
private final GraphQLOutputType type;
52+
53+
/**
54+
* A list element is characterized by having a path ending with an index segment. (ExecutionPath.isListSegment())
55+
*/
3156
private final ExecutionPath path;
3257
private final ExecutionStepInfo parent;
3358

34-
// field, fieldDefinition, fieldContainer and arguments stay the same for steps inside a list field
59+
/**
60+
* field, fieldDefinition, fieldContainer and arguments differ per field StepInfo.
61+
*
62+
* But for list StepInfos these properties are the same as the field returning the list.
63+
*/
3564
private final MergedField field;
3665
private final GraphQLFieldDefinition fieldDefinition;
3766
private final GraphQLObjectType fieldContainer;

src/test/groovy/graphql/execution/ExecutionStepInfoTest.groovy

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import graphql.schema.GraphQLNonNull
1212
import graphql.schema.GraphQLObjectType
1313
import graphql.schema.GraphQLType
1414
import graphql.schema.GraphQLTypeUtil
15+
import graphql.schema.TypeResolver
1516
import spock.lang.Specification
1617

1718
import java.util.function.Function
@@ -22,6 +23,7 @@ import static graphql.TestUtil.mergedField
2223
import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition
2324
import static graphql.schema.GraphQLList.list
2425
import static graphql.schema.GraphQLNonNull.nonNull
26+
import static graphql.schema.GraphQLTypeUtil.simplePrint
2527
import static graphql.schema.GraphQLTypeUtil.unwrapAll
2628
import static graphql.schema.idl.RuntimeWiring.newRuntimeWiring
2729
import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring
@@ -229,4 +231,87 @@ class ExecutionStepInfoTest extends Specification {
229231
then:
230232
transformed.getFieldContainer() == executionStepInfo.getFieldContainer()
231233
}
234+
235+
def "step info for list of lists of abstract type"() {
236+
def spec = '''
237+
type Query {
238+
pets: [[Pet]]
239+
}
240+
241+
interface Pet {
242+
names : [String]
243+
}
244+
type Cat implements Pet {
245+
names : [String]
246+
}
247+
type Dog implements Pet {
248+
names : [String]
249+
}
250+
'''
251+
252+
def dog = [name: "Dog", __typename: "Dog"]
253+
def cat = [name: "Cat", __typename: "Cat"]
254+
def petTypeResolver = { it -> it.schema.getObjectType(it.object.__typename) } as TypeResolver
255+
256+
257+
ExecutionStepInfo dogStepInfo
258+
def dogDf = { it ->
259+
dogStepInfo = it.getExecutionStepInfo()
260+
return null
261+
} as DataFetcher
262+
263+
264+
ExecutionStepInfo catStepInfo
265+
def catDf = { it ->
266+
catStepInfo = it.getExecutionStepInfo()
267+
return null
268+
} as DataFetcher
269+
270+
def pets = [[dog], [cat]]
271+
def runtimeWiring = newRuntimeWiring()
272+
.type(newTypeWiring("Query").dataFetcher("pets", { it -> pets }))
273+
.type(newTypeWiring("Pet").typeResolver(petTypeResolver).build())
274+
.type(newTypeWiring("Cat").dataFetcher("names", catDf).build())
275+
.type(newTypeWiring("Dog").dataFetcher("names", dogDf).build())
276+
.build()
277+
278+
def graphQL = TestUtil.graphQL(spec, runtimeWiring).build()
279+
280+
def query = '''
281+
{
282+
pets {names}
283+
}
284+
'''
285+
def executionInput = ExecutionInput.newExecutionInput().query(query).build()
286+
when:
287+
graphQL.execute(executionInput)
288+
then:
289+
// dog info
290+
dogStepInfo.path.toString() == "/pets[0][0]/names"
291+
simplePrint(dogStepInfo.type) == "[String]"
292+
293+
dogStepInfo.parent.path.toString() == "/pets[0][0]"
294+
simplePrint(dogStepInfo.parent.type) == "Dog"
295+
296+
dogStepInfo.parent.parent.path.toString() == "/pets[0]"
297+
simplePrint(dogStepInfo.parent.parent.type) == "[Pet]"
298+
299+
dogStepInfo.parent.parent.parent.path.toString() == "/pets"
300+
simplePrint(dogStepInfo.parent.parent.parent.type) == "[[Pet]]"
301+
302+
// cat info
303+
catStepInfo.path.toString() == "/pets[1][0]/names"
304+
simplePrint(catStepInfo.type) == "[String]"
305+
306+
catStepInfo.parent.path.toString() == "/pets[1][0]"
307+
simplePrint(catStepInfo.parent.type) == "Cat"
308+
309+
catStepInfo.parent.parent.path.toString() == "/pets[1]"
310+
simplePrint(catStepInfo.parent.parent.type) == "[Pet]"
311+
312+
catStepInfo.parent.parent.parent.path.toString() == "/pets"
313+
simplePrint(catStepInfo.parent.parent.parent.type) == "[[Pet]]"
314+
315+
316+
}
232317
}

0 commit comments

Comments
 (0)