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