1
+ import { GraphQLError , parse } from 'graphql' ;
2
+ import { batchDelegateToSchema } from '@graphql-tools/batch-delegate' ;
3
+ import { delegateToSchema } from '@graphql-tools/delegate' ;
4
+ import { makeExecutableSchema } from '@graphql-tools/schema' ;
5
+ import { stitchSchemas } from '@graphql-tools/stitch' ;
6
+ import { beforeEach , describe , expect , test , vi } from 'vitest' ;
7
+ import { normalizedExecutor } from '@graphql-tools/executor' ;
8
+
9
+ class NotFoundError extends GraphQLError {
10
+ constructor ( id : unknown ) {
11
+ super ( 'Not Found' , {
12
+ extensions : { id } ,
13
+ } )
14
+ }
15
+ }
16
+
17
+ describe ( 'preserves error path indices' , ( ) => {
18
+ const getProperty = vi . fn ( ( id : unknown ) => {
19
+ return new NotFoundError ( id ) ;
20
+ } ) ;
21
+
22
+ beforeEach ( ( ) => {
23
+ getProperty . mockClear ( ) ;
24
+ } ) ;
25
+
26
+ const subschema = makeExecutableSchema ( {
27
+ typeDefs : /* GraphQL */ `
28
+ type Property {
29
+ id: ID!
30
+ }
31
+
32
+ type Object {
33
+ id: ID!
34
+ propertyId: ID!
35
+ }
36
+
37
+ type Query {
38
+ objects: [Object!]!
39
+ propertyById(id: ID!): Property
40
+ propertiesByIds(ids: [ID!]!): [Property]!
41
+ }
42
+ ` ,
43
+ resolvers : {
44
+ Query : {
45
+ objects : ( ) => {
46
+ return [
47
+ { id : '1' , propertyId : '1' } ,
48
+ { id : '2' , propertyId : '1' } ,
49
+ ] ;
50
+ } ,
51
+ propertyById : ( _ , args ) => getProperty ( args . id ) ,
52
+ propertiesByIds : ( _ , args ) => args . ids . map ( getProperty ) ,
53
+ } ,
54
+ } ,
55
+ } ) ;
56
+
57
+ const subschemas = [ subschema ] ;
58
+ const typeDefs = /* GraphQL */ `
59
+ extend type Object {
60
+ property: Property
61
+ }
62
+ ` ;
63
+
64
+ const query = /* GraphQL */ `
65
+ query {
66
+ objects {
67
+ id
68
+ property {
69
+ id
70
+ }
71
+ }
72
+ }
73
+ ` ;
74
+
75
+ const expected = {
76
+ errors : [
77
+ {
78
+ message : 'Not Found' ,
79
+ extensions : { id : '1' } ,
80
+ path : [ 'objects' , 0 , 'property' ] ,
81
+ } ,
82
+ {
83
+ message : 'Not Found' ,
84
+ extensions : { id : '1' } ,
85
+ path : [ 'objects' , 1 , 'property' ] ,
86
+ } ,
87
+ ] ,
88
+ data : {
89
+ objects : [
90
+ {
91
+ id : '1' ,
92
+ property : null as null ,
93
+ } ,
94
+ {
95
+ id : '2' ,
96
+ property : null as null ,
97
+ } ,
98
+ ] ,
99
+ } ,
100
+ } ;
101
+
102
+ test ( 'using delegateToSchema' , async ( ) => {
103
+ const schema = stitchSchemas ( {
104
+ subschemas,
105
+ typeDefs,
106
+ resolvers : {
107
+ Object : {
108
+ property : {
109
+ selectionSet : '{ propertyId }' ,
110
+ resolve : ( source , _ , context , info ) => {
111
+ return delegateToSchema ( {
112
+ schema : subschema ,
113
+ fieldName : 'propertyById' ,
114
+ args : { id : source . propertyId } ,
115
+ context,
116
+ info,
117
+ } ) ;
118
+ } ,
119
+ } ,
120
+ } ,
121
+ } ,
122
+ } ) ;
123
+
124
+
125
+ const result = await normalizedExecutor ( {
126
+ schema,
127
+ document : parse ( query ) ,
128
+ } )
129
+
130
+ expect ( getProperty ) . toBeCalledTimes ( 2 ) ;
131
+ expect ( result ) . toMatchObject ( expected ) ;
132
+ } ) ;
133
+
134
+ test ( 'using batchDelegateToSchema' , async ( ) => {
135
+ const schema = stitchSchemas ( {
136
+ subschemas,
137
+ typeDefs,
138
+ resolvers : {
139
+ Object : {
140
+ property : {
141
+ selectionSet : '{ propertyId }' ,
142
+ resolve : ( source , _ , context , info ) => batchDelegateToSchema ( {
143
+ schema : subschema ,
144
+ fieldName : 'propertiesByIds' ,
145
+ key : source . propertyId ,
146
+ context,
147
+ info,
148
+ } ) ,
149
+ } ,
150
+ } ,
151
+ } ,
152
+ } ) ;
153
+
154
+ const result = await normalizedExecutor ( {
155
+ schema,
156
+ document : parse ( query ) ,
157
+ } )
158
+
159
+ expect ( getProperty ) . toBeCalledTimes ( 1 ) ;
160
+ expect ( result ) . toMatchObject ( expected ) ;
161
+ } ) ;
162
+ } ) ;
0 commit comments