@@ -160,4 +160,295 @@ testVersions((api, version) => {
160160 ] ) ;
161161 } , "detected exact same urls" ) . not . toThrow ( ) ;
162162 } ) ;
163+
164+ test ( "executable directive definition is retained in supergraph" , ( ) => {
165+ const result = api . composeServices ( [
166+ {
167+ name : "foo" ,
168+ url : "http://foo.com" ,
169+ typeDefs : graphql `
170+ extend schema
171+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
172+
173+ directive @a(n: Int) on FIELD
174+
175+ type Query {
176+ a: Int
177+ }
178+ ` ,
179+ } ,
180+ ] ) ;
181+ expect ( result . supergraphSdl ) . toContain ( "directive @a(n: Int)" ) ;
182+ } ) ;
183+
184+ test ( "executable directive definition is retained if defined identical in all subgraphs" , ( ) => {
185+ const result = api . composeServices ( [
186+ {
187+ name : "a" ,
188+ url : "http://a.com" ,
189+ typeDefs : graphql `
190+ extend schema
191+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
192+
193+ directive @a(n: Int) on FIELD
194+
195+ type Query {
196+ a: Int
197+ }
198+ ` ,
199+ } ,
200+ {
201+ name : "b" ,
202+ url : "http://b.com" ,
203+ typeDefs : graphql `
204+ extend schema
205+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
206+
207+ directive @a(n: Int) on FIELD
208+
209+ type Query {
210+ b: Int
211+ }
212+ ` ,
213+ } ,
214+ ] ) ;
215+ expect ( result . supergraphSdl ) . toContain ( "directive @a(n: Int)" ) ;
216+ } ) ;
217+
218+ test ( "executable directive definition is omitted if only defined within a single subgraph" , ( ) => {
219+ const result = api . composeServices ( [
220+ {
221+ name : "a" ,
222+ url : "http://a.com" ,
223+ typeDefs : graphql `
224+ extend schema
225+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
226+
227+ directive @a(n: Int) on FIELD
228+
229+ type Query {
230+ a: Int
231+ }
232+ ` ,
233+ } ,
234+ {
235+ name : "b" ,
236+ url : "http://b.com" ,
237+ typeDefs : graphql `
238+ extend schema
239+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
240+
241+ type Query {
242+ b: Int
243+ }
244+ ` ,
245+ } ,
246+ ] ) ;
247+ expect ( result . supergraphSdl ) . not . toContain ( "directive @a(n: Int)" ) ;
248+ } ) ;
249+
250+ test ( "executable directive only contains locations shared between all subgraphs" , ( ) => {
251+ const result = api . composeServices ( [
252+ {
253+ name : "a" ,
254+ url : "http://a.com" ,
255+ typeDefs : graphql `
256+ extend schema
257+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
258+
259+ directive @a(n: Int) on FIELD
260+
261+ type Query {
262+ a: Int
263+ }
264+ ` ,
265+ } ,
266+ {
267+ name : "b" ,
268+ url : "http://b.com" ,
269+ typeDefs : graphql `
270+ extend schema
271+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
272+
273+ directive @a(n: Int) on FIELD | FRAGMENT_SPREAD
274+
275+ type Query {
276+ b: Int
277+ }
278+ ` ,
279+ } ,
280+ ] ) ;
281+ expect ( result . supergraphSdl ) . toBeDefined ( ) ;
282+ expect ( result . supergraphSdl ) . toContainGraphQL ( graphql `
283+ directive @a(n: Int) on FIELD
284+ ` ) ;
285+ expect ( result . supergraphSdl ) . not . toContainGraphQL ( graphql `
286+ directive @a(n: Int) on FIELD | FRAGMENT_SPREAD
287+ ` ) ;
288+ } ) ;
289+
290+ test ( "executable directive is removed if no locations are shared between all subgraphs" , ( ) => {
291+ const result = api . composeServices ( [
292+ {
293+ name : "a" ,
294+ url : "http://a.com" ,
295+ typeDefs : graphql `
296+ extend schema
297+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
298+
299+ directive @a(n: Int) on FIELD
300+
301+ type Query {
302+ a: Int
303+ }
304+ ` ,
305+ } ,
306+ {
307+ name : "b" ,
308+ url : "http://b.com" ,
309+ typeDefs : graphql `
310+ extend schema
311+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
312+
313+ directive @a(n: Int) on FRAGMENT_SPREAD
314+
315+ type Query {
316+ b: Int
317+ }
318+ ` ,
319+ } ,
320+ ] ) ;
321+
322+ expect ( result . supergraphSdl ) . toBeDefined ( ) ;
323+ expect ( result . supergraphSdl ) . not . toContain ( "directive @a(n: Int)" ) ;
324+ } ) ;
325+
326+ test ( "executable directive is only included with executable definition locations" , ( ) => {
327+ const result = api . composeServices ( [
328+ {
329+ name : "a" ,
330+ url : "http://a.com" ,
331+ typeDefs : graphql `
332+ extend schema
333+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
334+
335+ directive @a(n: Int) on FIELD | FIELD_DEFINITION
336+
337+ type Query {
338+ a: Int
339+ }
340+ ` ,
341+ } ,
342+ {
343+ name : "b" ,
344+ url : "http://b.com" ,
345+ typeDefs : graphql `
346+ extend schema
347+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@key"])
348+
349+ directive @a(n: Int) on FIELD | FIELD_DEFINITION
350+
351+ type Query {
352+ b: Int
353+ }
354+ ` ,
355+ } ,
356+ ] ) ;
357+
358+ expect ( result . supergraphSdl ) . toBeDefined ( ) ;
359+ expect ( result . supergraphSdl ) . toContainGraphQL ( graphql `
360+ directive @a(n: Int) on FIELD
361+ ` ) ;
362+ } ) ;
363+
364+ if ( version !== "v2.0" ) {
365+ test ( "executable directive that is also a compose directive is included with executable definition and schema definition locations" , ( ) => {
366+ const result = api . composeServices ( [
367+ {
368+ name : "a" ,
369+ url : "http://a.com" ,
370+ typeDefs : graphql `
371+ extend schema
372+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@composeDirective"])
373+ @link(url: "https://a.dev/a/v1.0", import: ["@a"])
374+ @composeDirective(name: "@a")
375+
376+ directive @a(n: Int) on FIELD | FIELD_DEFINITION
377+
378+ type Query {
379+ a: Int
380+ }
381+ ` ,
382+ } ,
383+ {
384+ name : "b" ,
385+ url : "http://b.com" ,
386+ typeDefs : graphql `
387+ extend schema
388+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: [ "@composeDirective"])
389+ @link(url: "https://a.dev/a/v1.0", import: ["@a"])
390+ @composeDirective(name: "@a")
391+
392+ directive @a(n: Int) on FIELD | FIELD_DEFINITION
393+
394+ type Query {
395+ b: Int
396+ }
397+ ` ,
398+ } ,
399+ ] ) ;
400+
401+ expect ( result . supergraphSdl ) . toBeDefined ( ) ;
402+ expect ( result . supergraphSdl ) . toContainGraphQL ( graphql `
403+ directive @a(n: Int) on FIELD | FIELD_DEFINITION
404+ ` ) ;
405+ } ) ;
406+
407+ test ( "executable directive that is also a compose directive and used within the subgraph schemas is only included with executable definition locations and schema definition locations" , ( ) => {
408+ const result = api . composeServices ( [
409+ {
410+ name : "a" ,
411+ url : "http://a.com" ,
412+ typeDefs : graphql `
413+ extend schema
414+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: ["@composeDirective"])
415+ @link(url: "https://a.dev/a/v1.0", import: ["@a"])
416+ @composeDirective(name: "@a")
417+
418+ directive @a(n: Int) on FIELD | FIELD_DEFINITION
419+
420+ type Query {
421+ a: Int @a
422+ }
423+ ` ,
424+ } ,
425+ {
426+ name : "b" ,
427+ url : "http://b.com" ,
428+ typeDefs : graphql `
429+ extend schema
430+ @link(url: "https://specs.apollo.dev/federation/${ version } ", import: [ "@composeDirective"])
431+ @link(url: "https://a.dev/a/v1.0", import: ["@a"])
432+ @composeDirective(name: "@a")
433+
434+ directive @a(n: Int) on FIELD | FIELD_DEFINITION
435+
436+ type Query {
437+ b: Int @a
438+ }
439+ ` ,
440+ } ,
441+ ] ) ;
442+ expect ( result . supergraphSdl ) . toBeDefined ( ) ;
443+ expect ( result . supergraphSdl ) . toContainGraphQL ( graphql `
444+ directive @a(n: Int) on FIELD | FIELD_DEFINITION
445+ ` ) ;
446+ expect ( result . supergraphSdl ) . toContainGraphQL ( graphql `
447+ type Query @join__type(graph: A) @join__type(graph: B) {
448+ a: Int @a @join__field(graph: A)
449+ b: Int @a @join__field(graph: B)
450+ }
451+ ` ) ;
452+ } ) ;
453+ }
163454} ) ;
0 commit comments