@apollo/gateway 2.0.0-alpha.1 → 2.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +1 -1
  2. package/dist/__generated__/graphqlTypes.d.ts +13 -11
  3. package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
  4. package/dist/__generated__/graphqlTypes.js.map +1 -1
  5. package/dist/config.d.ts +2 -9
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +6 -17
  8. package/dist/config.js.map +1 -1
  9. package/dist/datasources/types.d.ts +1 -1
  10. package/dist/datasources/types.d.ts.map +1 -1
  11. package/dist/executeQueryPlan.d.ts.map +1 -1
  12. package/dist/executeQueryPlan.js +4 -4
  13. package/dist/executeQueryPlan.js.map +1 -1
  14. package/dist/index.d.ts +1 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +14 -28
  17. package/dist/index.js.map +1 -1
  18. package/dist/loadSupergraphSdlFromStorage.d.ts +4 -3
  19. package/dist/loadSupergraphSdlFromStorage.d.ts.map +1 -1
  20. package/dist/loadSupergraphSdlFromStorage.js +7 -3
  21. package/dist/loadSupergraphSdlFromStorage.js.map +1 -1
  22. package/dist/operationContext.js +0 -1
  23. package/dist/operationContext.js.map +1 -1
  24. package/dist/utilities/array.js +1 -1
  25. package/dist/utilities/array.js.map +1 -1
  26. package/package.json +8 -9
  27. package/src/__generated__/graphqlTypes.ts +13 -11
  28. package/src/__tests__/buildQueryPlan.test.ts +1 -1
  29. package/src/__tests__/executeQueryPlan.test.ts +572 -76
  30. package/src/__tests__/execution-utils.ts +2 -4
  31. package/src/__tests__/gateway/composedSdl.test.ts +1 -1
  32. package/src/__tests__/gateway/executor.test.ts +2 -0
  33. package/src/__tests__/gateway/lifecycle-hooks.test.ts +8 -4
  34. package/src/__tests__/gateway/opentelemetry.test.ts +1 -0
  35. package/src/__tests__/gateway/queryPlanCache.test.ts +3 -0
  36. package/src/__tests__/integration/aliases.test.ts +1 -0
  37. package/src/__tests__/integration/configuration.test.ts +3 -21
  38. package/src/__tests__/integration/logger.test.ts +1 -1
  39. package/src/__tests__/integration/networkRequests.test.ts +53 -28
  40. package/src/__tests__/integration/nockMocks.ts +33 -5
  41. package/src/__tests__/loadServicesFromRemoteEndpoint.test.ts +2 -2
  42. package/src/__tests__/loadSupergraphSdlFromStorage.test.ts +36 -6
  43. package/src/config.ts +8 -43
  44. package/src/core/__tests__/core.test.ts +6 -6
  45. package/src/datasources/types.ts +1 -1
  46. package/src/executeQueryPlan.ts +4 -7
  47. package/src/index.ts +22 -50
  48. package/src/loadServicesFromRemoteEndpoint.ts +1 -1
  49. package/src/loadSupergraphSdlFromStorage.ts +7 -4
  50. package/src/make-fetch-happen.d.ts +1 -1
  51. package/src/operationContext.ts +2 -2
  52. package/src/utilities/__tests__/cleanErrorOfInaccessibleElements.test.ts +1 -1
  53. package/src/utilities/array.ts +1 -1
  54. package/CHANGELOG.md +0 -452
  55. package/dist/legacyLoadServicesFromStorage.d.ts +0 -20
  56. package/dist/legacyLoadServicesFromStorage.d.ts.map +0 -1
  57. package/dist/legacyLoadServicesFromStorage.js +0 -62
  58. package/dist/legacyLoadServicesFromStorage.js.map +0 -1
  59. package/src/__tests__/integration/legacyNetworkRequests.test.ts +0 -279
  60. package/src/__tests__/integration/legacyNockMocks.ts +0 -113
  61. package/src/legacyLoadServicesFromStorage.ts +0 -170
@@ -30,11 +30,11 @@ describe('executeQueryPlan', () => {
30
30
  [serviceName: string]: LocalGraphQLDataSource;
31
31
  };
32
32
 
33
- let parseOp = (operation: string, operationSchema?: Schema): Operation => {
33
+ const parseOp = (operation: string, operationSchema?: Schema): Operation => {
34
34
  return parseOperation((operationSchema ?? schema), operation);
35
35
  }
36
36
 
37
- let buildPlan = (operation: string | Operation, operationQueryPlanner?: QueryPlanner, operationSchema?: Schema): QueryPlan => {
37
+ const buildPlan = (operation: string | Operation, operationQueryPlanner?: QueryPlanner, operationSchema?: Schema): QueryPlan => {
38
38
  const op = typeof operation === 'string' ? parseOp(operation, operationSchema): operation;
39
39
  return (operationQueryPlanner ?? queryPlanner).buildQueryPlan(op);
40
40
  }
@@ -88,6 +88,7 @@ describe('executeQueryPlan', () => {
88
88
  });
89
89
 
90
90
  function buildRequestContext(): GraphQLRequestContext {
91
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
91
92
  // @ts-ignore
92
93
  return {
93
94
  cache: undefined as any,
@@ -1116,102 +1117,409 @@ describe('executeQueryPlan', () => {
1116
1117
  });
1117
1118
  });
1118
1119
 
1119
- it('can query other subgraphs when the Query type is the type of a field', async () => {
1120
- const s1 = gql`
1121
- type Query {
1122
- getA: A
1123
- }
1120
+ describe('reusing root types', () => {
1121
+ it('can query other subgraphs when the Query type is the type of a field', async () => {
1122
+ const s1 = gql`
1123
+ type Query {
1124
+ getA: A
1125
+ }
1124
1126
 
1125
- type A {
1126
- q: Query
1127
- }
1128
- `;
1127
+ type A {
1128
+ q: Query
1129
+ }
1130
+ `;
1129
1131
 
1130
- const s2 = gql`
1131
- type Query {
1132
- one: Int
1133
- }
1134
- `;
1132
+ const s2 = gql`
1133
+ type Query {
1134
+ one: Int
1135
+ }
1136
+ `;
1135
1137
 
1136
- const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([
1137
- { name: 'S1', typeDefs: s1 },
1138
- { name: 'S2', typeDefs: s2 }
1139
- ]);
1138
+ const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([
1139
+ { name: 'S1', typeDefs: s1 },
1140
+ { name: 'S2', typeDefs: s2 }
1141
+ ]);
1140
1142
 
1141
- addResolversToSchema(serviceMap['S1'].schema, {
1142
- Query: {
1143
- getA() {
1144
- return {
1145
- getA: {
1146
- q: null
1147
- }
1148
- };
1143
+ addResolversToSchema(serviceMap['S1'].schema, {
1144
+ Query: {
1145
+ getA() {
1146
+ return {
1147
+ getA: {}
1148
+ };
1149
+ },
1149
1150
  },
1150
- },
1151
- A: {
1152
- q() {
1153
- return Object.create(null);
1151
+ A: {
1152
+ q() {
1153
+ return Object.create(null);
1154
+ }
1154
1155
  }
1155
- }
1156
- });
1156
+ });
1157
1157
 
1158
- addResolversToSchema(serviceMap['S2'].schema, {
1159
- Query: {
1160
- one() {
1161
- return 1;
1158
+ addResolversToSchema(serviceMap['S2'].schema, {
1159
+ Query: {
1160
+ one() {
1161
+ return 1;
1162
+ },
1162
1163
  },
1163
- },
1164
- });
1164
+ });
1165
1165
 
1166
- const operation = parseOp(`
1167
- query {
1168
- getA {
1169
- q {
1170
- one
1166
+ const operation = parseOp(`
1167
+ query {
1168
+ getA {
1169
+ q {
1170
+ one
1171
+ }
1171
1172
  }
1172
1173
  }
1173
- }
1174
- `, schema);
1174
+ `, schema);
1175
1175
 
1176
- const queryPlan = buildPlan(operation, queryPlanner);
1176
+ const queryPlan = buildPlan(operation, queryPlanner);
1177
1177
 
1178
- expect(queryPlan).toMatchInlineSnapshot(`
1179
- QueryPlan {
1180
- Sequence {
1181
- Fetch(service: "S1") {
1182
- {
1183
- getA {
1184
- q {
1185
- __typename
1178
+ expect(queryPlan).toMatchInlineSnapshot(`
1179
+ QueryPlan {
1180
+ Sequence {
1181
+ Fetch(service: "S1") {
1182
+ {
1183
+ getA {
1184
+ q {
1185
+ __typename
1186
+ }
1186
1187
  }
1187
1188
  }
1189
+ },
1190
+ Flatten(path: "getA.q") {
1191
+ Fetch(service: "S2") {
1192
+ {
1193
+ ... on Query {
1194
+ one
1195
+ }
1196
+ }
1197
+ },
1198
+ },
1199
+ },
1200
+ }
1201
+ `);
1202
+
1203
+ const response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
1204
+
1205
+ expect(response.data).toMatchInlineSnapshot(`
1206
+ Object {
1207
+ "getA": Object {
1208
+ "q": Object {
1209
+ "one": 1,
1210
+ },
1211
+ },
1212
+ }
1213
+ `);
1214
+ })
1215
+
1216
+ it('can query other subgraphs when the Query type is the type of a field after a mutation', async () => {
1217
+ const s1 = gql`
1218
+ type Query {
1219
+ one: Int
1220
+ }
1221
+
1222
+ type Mutation {
1223
+ mutateSomething: Query
1224
+ }
1225
+ `;
1226
+
1227
+ const s2 = gql`
1228
+ type Query {
1229
+ two: Int
1230
+ }
1231
+ `;
1232
+
1233
+ const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([
1234
+ { name: 'S1', typeDefs: s1 },
1235
+ { name: 'S2', typeDefs: s2 }
1236
+ ]);
1237
+
1238
+ let hasMutated = false;
1239
+
1240
+ addResolversToSchema(serviceMap['S1'].schema, {
1241
+ Query: {
1242
+ one() {
1243
+ return 1;
1244
+ },
1245
+ },
1246
+ Mutation: {
1247
+ mutateSomething() {
1248
+ hasMutated = true;
1249
+ return {};
1250
+ },
1251
+ }
1252
+ });
1253
+
1254
+ addResolversToSchema(serviceMap['S2'].schema, {
1255
+ Query: {
1256
+ two() {
1257
+ return 2;
1258
+ },
1259
+ },
1260
+ });
1261
+
1262
+ const operation = parseOp(`
1263
+ mutation {
1264
+ mutateSomething {
1265
+ one
1266
+ two
1188
1267
  }
1268
+ }
1269
+ `, schema);
1270
+
1271
+ const queryPlan = buildPlan(operation, queryPlanner);
1272
+
1273
+ expect(queryPlan).toMatchInlineSnapshot(`
1274
+ QueryPlan {
1275
+ Sequence {
1276
+ Fetch(service: "S1") {
1277
+ {
1278
+ mutateSomething {
1279
+ __typename
1280
+ one
1281
+ }
1282
+ }
1283
+ },
1284
+ Flatten(path: "mutateSomething") {
1285
+ Fetch(service: "S2") {
1286
+ {
1287
+ ... on Query {
1288
+ two
1289
+ }
1290
+ }
1291
+ },
1292
+ },
1293
+ },
1294
+ }
1295
+ `);
1296
+
1297
+ const response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
1298
+
1299
+ expect(hasMutated).toBeTruthy();
1300
+ expect(response.data).toMatchInlineSnapshot(`
1301
+ Object {
1302
+ "mutateSomething": Object {
1303
+ "one": 1,
1304
+ "two": 2,
1305
+ },
1306
+ }
1307
+ `);
1308
+ })
1309
+
1310
+ it('can mutate other subgraphs when the Mutation type is the type of a field', async () => {
1311
+ const s1 = gql`
1312
+ type Query {
1313
+ getA: A
1314
+ }
1315
+
1316
+ type Mutation {
1317
+ mutateOne: Int
1318
+ }
1319
+
1320
+ type A {
1321
+ m: Mutation
1322
+ }
1323
+ `;
1324
+
1325
+ const s2 = gql`
1326
+ type Mutation {
1327
+ mutateTwo: Int
1328
+ }
1329
+ `;
1330
+
1331
+ const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([
1332
+ { name: 'S1', typeDefs: s1 },
1333
+ { name: 'S2', typeDefs: s2 }
1334
+ ]);
1335
+
1336
+ let mutateOneCalled = false;
1337
+ let mutateTwoCalled = false;
1338
+
1339
+ addResolversToSchema(serviceMap['S1'].schema, {
1340
+ Query: {
1341
+ getA() {
1342
+ return {
1343
+ getA: {}
1344
+ };
1189
1345
  },
1190
- Flatten(path: "getA.q") {
1191
- Fetch(service: "S2") {
1346
+ },
1347
+ A: {
1348
+ m() {
1349
+ return Object.create(null);
1350
+ }
1351
+ },
1352
+ Mutation: {
1353
+ mutateOne() {
1354
+ mutateOneCalled = true;
1355
+ return 1;
1356
+ }
1357
+ }
1358
+ });
1359
+
1360
+ addResolversToSchema(serviceMap['S2'].schema, {
1361
+ Mutation: {
1362
+ mutateTwo() {
1363
+ mutateTwoCalled = true;
1364
+ return 2;
1365
+ },
1366
+ },
1367
+ });
1368
+
1369
+ const operation = parseOp(`
1370
+ query {
1371
+ getA {
1372
+ m {
1373
+ mutateOne
1374
+ mutateTwo
1375
+ }
1376
+ }
1377
+ }
1378
+ `, schema);
1379
+
1380
+ const queryPlan = buildPlan(operation, queryPlanner);
1381
+
1382
+ expect(queryPlan).toMatchInlineSnapshot(`
1383
+ QueryPlan {
1384
+ Sequence {
1385
+ Fetch(service: "S1") {
1192
1386
  {
1193
- ... on Query {
1194
- one
1387
+ getA {
1388
+ m {
1389
+ __typename
1390
+ mutateOne
1391
+ }
1195
1392
  }
1196
1393
  }
1197
1394
  },
1395
+ Flatten(path: "getA.m") {
1396
+ Fetch(service: "S2") {
1397
+ {
1398
+ ... on Mutation {
1399
+ mutateTwo
1400
+ }
1401
+ }
1402
+ },
1403
+ },
1198
1404
  },
1199
- },
1200
- }
1201
- `);
1202
-
1203
- const response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
1405
+ }
1406
+ `);
1204
1407
 
1205
- expect(response.data).toMatchInlineSnapshot(`
1206
- Object {
1207
- "getA": Object {
1208
- "q": Object {
1209
- "one": 1,
1408
+ const response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
1409
+ expect(mutateOneCalled).toBeTruthy();
1410
+ expect(mutateTwoCalled).toBeTruthy();
1411
+ expect(response.data).toMatchInlineSnapshot(`
1412
+ Object {
1413
+ "getA": Object {
1414
+ "m": Object {
1415
+ "mutateOne": 1,
1416
+ "mutateTwo": 2,
1417
+ },
1210
1418
  },
1211
- },
1212
- }
1419
+ }
1213
1420
  `);
1214
- })
1421
+ })
1422
+
1423
+ it('can mutate other subgraphs when the Mutation type is the type of a field after a mutation', async () => {
1424
+ const s1 = gql`
1425
+ type Query {
1426
+ one: Int
1427
+ }
1428
+
1429
+ type Mutation {
1430
+ mutateSomething: Mutation
1431
+ }
1432
+ `;
1433
+
1434
+ const s2 = gql`
1435
+ type Mutation {
1436
+ mutateTwo: Int
1437
+ }
1438
+ `;
1439
+
1440
+ const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([
1441
+ { name: 'S1', typeDefs: s1 },
1442
+ { name: 'S2', typeDefs: s2 }
1443
+ ]);
1444
+
1445
+ let somethingMutationCount = 0;
1446
+ let hasMutatedTwo = false;
1447
+
1448
+ addResolversToSchema(serviceMap['S1'].schema, {
1449
+ Query: {
1450
+ one() {
1451
+ return 1;
1452
+ },
1453
+ },
1454
+ Mutation: {
1455
+ mutateSomething() {
1456
+ ++somethingMutationCount;
1457
+ return {};
1458
+ },
1459
+ }
1460
+ });
1461
+
1462
+ addResolversToSchema(serviceMap['S2'].schema, {
1463
+ Mutation: {
1464
+ mutateTwo() {
1465
+ hasMutatedTwo = true;
1466
+ return 2;
1467
+ },
1468
+ },
1469
+ });
1470
+
1471
+ const operation = parseOp(`
1472
+ mutation {
1473
+ mutateSomething {
1474
+ mutateSomething {
1475
+ mutateTwo
1476
+ }
1477
+ }
1478
+ }
1479
+ `, schema);
1480
+
1481
+ const queryPlan = buildPlan(operation, queryPlanner);
1482
+
1483
+ expect(queryPlan).toMatchInlineSnapshot(`
1484
+ QueryPlan {
1485
+ Sequence {
1486
+ Fetch(service: "S1") {
1487
+ {
1488
+ mutateSomething {
1489
+ mutateSomething {
1490
+ __typename
1491
+ }
1492
+ }
1493
+ }
1494
+ },
1495
+ Flatten(path: "mutateSomething.mutateSomething") {
1496
+ Fetch(service: "S2") {
1497
+ {
1498
+ ... on Mutation {
1499
+ mutateTwo
1500
+ }
1501
+ }
1502
+ },
1503
+ },
1504
+ },
1505
+ }
1506
+ `);
1507
+
1508
+ const response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
1509
+
1510
+ expect(somethingMutationCount).toBe(2);
1511
+ expect(hasMutatedTwo).toBeTruthy();
1512
+ expect(response.data).toMatchInlineSnapshot(`
1513
+ Object {
1514
+ "mutateSomething": Object {
1515
+ "mutateSomething": Object {
1516
+ "mutateTwo": 2,
1517
+ },
1518
+ },
1519
+ }
1520
+ `);
1521
+ })
1522
+ });
1215
1523
 
1216
1524
  describe('interfaces on interfaces', () => {
1217
1525
  it('can execute queries on an interface only implemented by other interfaces', async () => {
@@ -1309,7 +1617,7 @@ describe('executeQueryPlan', () => {
1309
1617
  },
1310
1618
  });
1311
1619
 
1312
- let operation = parseOp(`
1620
+ const operation = parseOp(`
1313
1621
  query {
1314
1622
  allValues {
1315
1623
  a
@@ -1323,7 +1631,7 @@ describe('executeQueryPlan', () => {
1323
1631
  }
1324
1632
  `, schema);
1325
1633
 
1326
- let queryPlan = buildPlan(operation, queryPlanner);
1634
+ const queryPlan = buildPlan(operation, queryPlanner);
1327
1635
 
1328
1636
  expect(queryPlan).toMatchInlineSnapshot(`
1329
1637
  QueryPlan {
@@ -1378,7 +1686,7 @@ describe('executeQueryPlan', () => {
1378
1686
  }
1379
1687
  `);
1380
1688
 
1381
- let response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
1689
+ const response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
1382
1690
 
1383
1691
  expect(response.data).toMatchInlineSnapshot(`
1384
1692
  Object {
@@ -1642,4 +1950,192 @@ describe('executeQueryPlan', () => {
1642
1950
  `);
1643
1951
  });
1644
1952
  });
1953
+
1954
+ test('do not send subgraphs an interface they do not know', async () => {
1955
+ // This test validates that the issue described on https://github.com/apollographql/federation/issues/817 is fixed.
1956
+ const s1 = {
1957
+ name: 'S1',
1958
+ typeDefs: gql`
1959
+ type Query {
1960
+ myField: MyInterface
1961
+ }
1962
+
1963
+ interface MyInterface {
1964
+ name: String
1965
+ }
1966
+
1967
+ type MyTypeA implements MyInterface {
1968
+ name: String
1969
+ }
1970
+
1971
+ type MyTypeB implements MyInterface {
1972
+ name: String
1973
+ }
1974
+ `
1975
+ }
1976
+
1977
+ const s2 = {
1978
+ name: 'S2',
1979
+ typeDefs: gql`
1980
+ interface MyInterface {
1981
+ name: String
1982
+ }
1983
+
1984
+ type MyTypeC implements MyInterface {
1985
+ name: String
1986
+ }
1987
+ `
1988
+ }
1989
+
1990
+ const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([ s1, s2 ]);
1991
+
1992
+ addResolversToSchema(serviceMap['S1'].schema, {
1993
+ Query: {
1994
+ myField() {
1995
+ return { __typename: 'MyTypeA', name: "foo" };
1996
+ },
1997
+ },
1998
+ });
1999
+
2000
+ // First, we just query the field without conditions.
2001
+ // Note that there is no reason to type-explode this: clearly, `myField` will never return a `MyTypeC` since
2002
+ // it's resolved by S1 which doesn't know that type, but that doesn't impact the plan.
2003
+ let operation = parseOp(`
2004
+ query {
2005
+ myField {
2006
+ name
2007
+ }
2008
+ }
2009
+ `, schema);
2010
+ let queryPlan = buildPlan(operation, queryPlanner);
2011
+ expect(queryPlan).toMatchInlineSnapshot(`
2012
+ QueryPlan {
2013
+ Fetch(service: "S1") {
2014
+ {
2015
+ myField {
2016
+ __typename
2017
+ name
2018
+ }
2019
+ }
2020
+ },
2021
+ }
2022
+ `);
2023
+ let response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
2024
+ expect(response.data).toMatchInlineSnapshot(`
2025
+ Object {
2026
+ "myField": Object {
2027
+ "name": "foo",
2028
+ },
2029
+ }
2030
+ `);
2031
+
2032
+ // Now forcing the query planning to notice that `MyTypeC` can never happen and making
2033
+ // sure it doesn't ask it from S1, which doesn't know it.
2034
+ operation = parseOp(`
2035
+ query {
2036
+ myField {
2037
+ ... on MyTypeA {
2038
+ name
2039
+ }
2040
+ ... on MyTypeC {
2041
+ name
2042
+ }
2043
+ }
2044
+ }
2045
+ `, schema);
2046
+ queryPlan = buildPlan(operation, queryPlanner);
2047
+ expect(queryPlan).toMatchInlineSnapshot(`
2048
+ QueryPlan {
2049
+ Fetch(service: "S1") {
2050
+ {
2051
+ myField {
2052
+ __typename
2053
+ ... on MyTypeA {
2054
+ name
2055
+ }
2056
+ }
2057
+ }
2058
+ },
2059
+ }
2060
+ `);
2061
+
2062
+ response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
2063
+ expect(response.data).toMatchInlineSnapshot(`
2064
+ Object {
2065
+ "myField": Object {
2066
+ "name": "foo",
2067
+ },
2068
+ }
2069
+ `);
2070
+
2071
+
2072
+ // Testing only getting name for `MyTypeB`, which is known by S1, but not returned
2073
+ // by `myField` in practice (so the result is "empty").
2074
+ operation = parseOp(`
2075
+ query {
2076
+ myField {
2077
+ ... on MyTypeB {
2078
+ name
2079
+ }
2080
+ }
2081
+ }
2082
+ `, schema);
2083
+
2084
+ queryPlan = buildPlan(operation, queryPlanner);
2085
+ expect(queryPlan).toMatchInlineSnapshot(`
2086
+ QueryPlan {
2087
+ Fetch(service: "S1") {
2088
+ {
2089
+ myField {
2090
+ __typename
2091
+ ... on MyTypeB {
2092
+ name
2093
+ }
2094
+ }
2095
+ }
2096
+ },
2097
+ }
2098
+ `);
2099
+ response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
2100
+ expect(response.data).toMatchInlineSnapshot(`
2101
+ Object {
2102
+ "myField": Object {},
2103
+ }
2104
+ `);
2105
+
2106
+ operation = parseOp(`
2107
+ query {
2108
+ myField {
2109
+ ... on MyTypeC {
2110
+ name
2111
+ }
2112
+ }
2113
+ }
2114
+ `, schema);
2115
+
2116
+ // Lastly, same with only getting name for `MyTypeC`. It isn't known by S1 so the condition should not
2117
+ // be included in the query, but we should still query `myField` to know if it resolve to "something"
2118
+ // (and all we know it can't be a `MyTypeC`) or to `null`. In particular, the end response should be
2119
+ // the same than in the previous example with `MyTypeB` since from the end-use POV, this is the same
2120
+ // example.
2121
+ queryPlan = buildPlan(operation, queryPlanner);
2122
+ expect(queryPlan).toMatchInlineSnapshot(`
2123
+ QueryPlan {
2124
+ Fetch(service: "S1") {
2125
+ {
2126
+ myField {
2127
+ __typename
2128
+ }
2129
+ }
2130
+ },
2131
+ }
2132
+ `);
2133
+
2134
+ response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
2135
+ expect(response.data).toMatchInlineSnapshot(`
2136
+ Object {
2137
+ "myField": Object {},
2138
+ }
2139
+ `);
2140
+ });
1645
2141
  });