@@ -954,7 +954,7 @@ describe("composition involving @override directive", () => {
954
954
@join__type(graph: SUBGRAPH2, key: \\"k\\")
955
955
{
956
956
k: ID
957
- a: Int @join__field(graph: SUBGRAPH1, override: \\"Subgraph2\\", overrideLabel: \\"foo\\")
957
+ a: Int @join__field(graph: SUBGRAPH1, override: \\"Subgraph2\\", overrideLabel: \\"foo\\") @join__field(graph: SUBGRAPH2, overrideLabel: \\"foo\\")
958
958
b: Int @join__field(graph: SUBGRAPH2)
959
959
}"
960
960
` ) ;
@@ -971,6 +971,70 @@ describe("composition involving @override directive", () => {
971
971
b: Int
972
972
}
973
973
` ) ;
974
+
975
+ expect ( result . supergraphSdl ) . toMatchInlineSnapshot ( `
976
+ "schema
977
+ @link(url: \\"https://specs.apollo.dev/link/v1.0\\")
978
+ @link(url: \\"https://specs.apollo.dev/join/v0.4\\", for: EXECUTION)
979
+ {
980
+ query: Query
981
+ }
982
+
983
+ directive @join__directive(graphs: [join__Graph!], name: String!, args: join__DirectiveArguments) repeatable on SCHEMA | OBJECT | INTERFACE | FIELD_DEFINITION
984
+
985
+ directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE
986
+
987
+ directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean, overrideLabel: String) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
988
+
989
+ directive @join__graph(name: String!, url: String!) on ENUM_VALUE
990
+
991
+ directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE
992
+
993
+ directive @join__type(graph: join__Graph!, key: join__FieldSet, extension: Boolean! = false, resolvable: Boolean! = true, isInterfaceObject: Boolean! = false) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR
994
+
995
+ directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION
996
+
997
+ directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA
998
+
999
+ scalar join__DirectiveArguments
1000
+
1001
+ scalar join__FieldSet
1002
+
1003
+ enum join__Graph {
1004
+ SUBGRAPH1 @join__graph(name: \\"Subgraph1\\", url: \\"https://Subgraph1\\")
1005
+ SUBGRAPH2 @join__graph(name: \\"Subgraph2\\", url: \\"https://Subgraph2\\")
1006
+ }
1007
+
1008
+ scalar link__Import
1009
+
1010
+ enum link__Purpose {
1011
+ \\"\\"\\"
1012
+ \`SECURITY\` features provide metadata necessary to securely resolve fields.
1013
+ \\"\\"\\"
1014
+ SECURITY
1015
+
1016
+ \\"\\"\\"
1017
+ \`EXECUTION\` features provide metadata necessary for operation execution.
1018
+ \\"\\"\\"
1019
+ EXECUTION
1020
+ }
1021
+
1022
+ type Query
1023
+ @join__type(graph: SUBGRAPH1)
1024
+ @join__type(graph: SUBGRAPH2)
1025
+ {
1026
+ t: T @join__field(graph: SUBGRAPH1)
1027
+ }
1028
+
1029
+ type T
1030
+ @join__type(graph: SUBGRAPH1, key: \\"k\\")
1031
+ @join__type(graph: SUBGRAPH2, key: \\"k\\")
1032
+ {
1033
+ k: ID
1034
+ a: Int @join__field(graph: SUBGRAPH1, override: \\"Subgraph2\\", overrideLabel: \\"foo\\") @join__field(graph: SUBGRAPH2, overrideLabel: \\"foo\\")
1035
+ b: Int @join__field(graph: SUBGRAPH2)
1036
+ }"
1037
+ ` ) ;
974
1038
} ) ;
975
1039
976
1040
describe ( "label validation" , ( ) => {
@@ -1088,5 +1152,103 @@ describe("composition involving @override directive", () => {
1088
1152
}
1089
1153
) ;
1090
1154
} ) ;
1155
+
1156
+ describe ( "composition validation" , ( ) => {
1157
+ it ( "forced jump from S1 -> S2 -> S1 due to @override usages" , ( ) => {
1158
+ const subgraph1 = {
1159
+ name : "Subgraph1" ,
1160
+ url : "https://Subgraph1" ,
1161
+ typeDefs : gql `
1162
+ type Query {
1163
+ t: T
1164
+ }
1165
+
1166
+ type T @key(fields: "id") {
1167
+ id: ID
1168
+ a: A @override(from: "Subgraph2", label: "foo")
1169
+ }
1170
+
1171
+ type A @key(fields: "id") {
1172
+ id: ID
1173
+ b: Int
1174
+ }
1175
+ ` ,
1176
+ } ;
1177
+
1178
+ const subgraph2 = {
1179
+ name : "Subgraph2" ,
1180
+ url : "https://Subgraph2" ,
1181
+ typeDefs : gql `
1182
+ type T @key(fields: "id") {
1183
+ id: ID
1184
+ a: A
1185
+ }
1186
+
1187
+ type A @key(fields: "id") {
1188
+ id: ID
1189
+ b: Int @override(from: "Subgraph1", label: "foo")
1190
+ }
1191
+ ` ,
1192
+ } ;
1193
+
1194
+ const result = composeAsFed2Subgraphs ( [ subgraph1 , subgraph2 ] ) ;
1195
+ assertCompositionSuccess ( result ) ;
1196
+ } ) ;
1197
+
1198
+ it ( "errors on overridden fields in @requires FieldSet" , ( ) => {
1199
+ const subgraph1 = {
1200
+ name : "Subgraph1" ,
1201
+ url : "https://Subgraph1" ,
1202
+ typeDefs : gql `
1203
+ type Query {
1204
+ t: T
1205
+ }
1206
+
1207
+ type T @key(fields: "id") {
1208
+ id: ID
1209
+ a: A @override(from: "Subgraph2", label: "foo")
1210
+ }
1211
+
1212
+ type A @key(fields: "id") {
1213
+ id: ID
1214
+ b: Int
1215
+ c: Int
1216
+ }
1217
+ ` ,
1218
+ } ;
1219
+
1220
+ const subgraph2 = {
1221
+ name : "Subgraph2" ,
1222
+ url : "https://Subgraph2" ,
1223
+ typeDefs : gql `
1224
+ type T @key(fields: "id") {
1225
+ id: ID
1226
+ a: A
1227
+ b: Int @requires(fields: "a { c }")
1228
+ }
1229
+
1230
+ type A @key(fields: "id") {
1231
+ id: ID
1232
+ b: Int @override(from: "Subgraph1", label: "foo")
1233
+ c: Int @external
1234
+ }
1235
+ ` ,
1236
+ } ;
1237
+
1238
+ const result = composeAsFed2Subgraphs ( [ subgraph1 , subgraph2 ] ) ;
1239
+ expect ( result . errors ) . toBeDefined ( ) ;
1240
+ expect ( result . errors ! [ 0 ] ) . toMatchInlineSnapshot ( `
1241
+ [GraphQLError: The following supergraph API query:
1242
+ {
1243
+ t {
1244
+ b
1245
+ }
1246
+ }
1247
+ cannot be satisfied by the subgraphs because:
1248
+ - from subgraph "Subgraph1": cannot find field "T.b".
1249
+ - from subgraph "Subgraph2": cannot satisfy @require conditions on field "T.b".]
1250
+ ` ) ;
1251
+ } ) ;
1252
+ } ) ;
1091
1253
} ) ;
1092
1254
} ) ;
0 commit comments