@apollo/gateway 2.4.5 → 2.4.6
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.
- package/dist/__generated__/graphqlTypes.d.ts +19 -1
- package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
- package/dist/__generated__/graphqlTypes.js +1 -0
- package/dist/__generated__/graphqlTypes.js.map +1 -1
- package/package.json +4 -4
- package/src/__generated__/graphqlTypes.ts +33 -2
- package/src/__mocks__/tsconfig.json +0 -7
- package/src/__tests__/.gitkeep +0 -0
- package/src/__tests__/CucumberREADME.md +0 -96
- package/src/__tests__/build-query-plan.feature +0 -1471
- package/src/__tests__/buildQueryPlan.test.ts +0 -1225
- package/src/__tests__/executeQueryPlan.conditions.test.ts +0 -1488
- package/src/__tests__/executeQueryPlan.introspection.test.ts +0 -140
- package/src/__tests__/executeQueryPlan.test.ts +0 -6140
- package/src/__tests__/execution-utils.ts +0 -124
- package/src/__tests__/gateway/__snapshots__/opentelemetry.test.ts.snap +0 -195
- package/src/__tests__/gateway/buildService.test.ts +0 -249
- package/src/__tests__/gateway/endToEnd.test.ts +0 -486
- package/src/__tests__/gateway/executor.test.ts +0 -96
- package/src/__tests__/gateway/extensions.test.ts +0 -37
- package/src/__tests__/gateway/lifecycle-hooks.test.ts +0 -239
- package/src/__tests__/gateway/opentelemetry.test.ts +0 -123
- package/src/__tests__/gateway/queryPlanCache.test.ts +0 -231
- package/src/__tests__/gateway/queryPlannerConfig.test.ts +0 -101
- package/src/__tests__/gateway/reporting.test.ts +0 -616
- package/src/__tests__/gateway/supergraphSdl.test.ts +0 -396
- package/src/__tests__/gateway/testUtils.ts +0 -89
- package/src/__tests__/integration/abstract-types.test.ts +0 -1861
- package/src/__tests__/integration/aliases.test.ts +0 -180
- package/src/__tests__/integration/boolean.test.ts +0 -279
- package/src/__tests__/integration/complex-key.test.ts +0 -197
- package/src/__tests__/integration/configuration.test.ts +0 -404
- package/src/__tests__/integration/custom-directives.test.ts +0 -174
- package/src/__tests__/integration/execution-style.test.ts +0 -35
- package/src/__tests__/integration/fragments.test.ts +0 -237
- package/src/__tests__/integration/list-key.test.ts +0 -128
- package/src/__tests__/integration/logger.test.ts +0 -122
- package/src/__tests__/integration/managed.test.ts +0 -319
- package/src/__tests__/integration/merge-arrays.test.ts +0 -34
- package/src/__tests__/integration/multiple-key.test.ts +0 -327
- package/src/__tests__/integration/mutations.test.ts +0 -287
- package/src/__tests__/integration/networkRequests.test.ts +0 -542
- package/src/__tests__/integration/nockMocks.ts +0 -157
- package/src/__tests__/integration/provides.test.ts +0 -77
- package/src/__tests__/integration/requires.test.ts +0 -359
- package/src/__tests__/integration/scope.test.ts +0 -557
- package/src/__tests__/integration/single-service.test.ts +0 -119
- package/src/__tests__/integration/unions.test.ts +0 -79
- package/src/__tests__/integration/value-types.test.ts +0 -382
- package/src/__tests__/integration/variables.test.ts +0 -120
- package/src/__tests__/nockAssertions.ts +0 -20
- package/src/__tests__/queryPlanCucumber.test.ts +0 -55
- package/src/__tests__/resultShaping.test.ts +0 -605
- package/src/__tests__/testSetup.ts +0 -1
- package/src/__tests__/tsconfig.json +0 -8
- package/src/core/__tests__/core.test.ts +0 -412
- package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +0 -51
- package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +0 -574
- package/src/schema-helper/__tests__/addExtensions.test.ts +0 -70
- package/src/supergraphManagers/IntrospectAndCompose/__tests__/IntrospectAndCompose.test.ts +0 -364
- package/src/supergraphManagers/IntrospectAndCompose/__tests__/loadServicesFromRemoteEndpoint.test.ts +0 -40
- package/src/supergraphManagers/UplinkSupergraphManager/__tests__/UplinkSupergraphManager.test.ts +0 -65
- package/src/supergraphManagers/UplinkSupergraphManager/__tests__/loadSupergraphSdlFromStorage.test.ts +0 -511
- package/src/utilities/__tests__/deepMerge.test.ts +0 -77
|
@@ -1,486 +0,0 @@
|
|
|
1
|
-
import { fixtures } from 'apollo-federation-integration-testsuite';
|
|
2
|
-
import { buildSchema, ObjectType } from '@apollo/federation-internals';
|
|
3
|
-
import gql from 'graphql-tag';
|
|
4
|
-
import { printSchema } from 'graphql';
|
|
5
|
-
import { startSubgraphsAndGateway, Services } from './testUtils'
|
|
6
|
-
import { InMemoryLRUCache } from '@apollo/utils.keyvaluecache';
|
|
7
|
-
import { QueryPlan } from '@apollo/query-planner';
|
|
8
|
-
import { createHash } from '@apollo/utils.createhash';
|
|
9
|
-
|
|
10
|
-
function approximateObjectSize<T>(obj: T): number {
|
|
11
|
-
return Buffer.byteLength(JSON.stringify(obj), 'utf8');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
let services: Services;
|
|
15
|
-
|
|
16
|
-
afterEach(async () => {
|
|
17
|
-
if (services) {
|
|
18
|
-
await services.stop();
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
describe('caching', () => {
|
|
24
|
-
const cache = new InMemoryLRUCache<QueryPlan>({maxSize: Math.pow(2, 20) * (30), sizeCalculation: approximateObjectSize});
|
|
25
|
-
beforeEach(async () => {
|
|
26
|
-
services = await startSubgraphsAndGateway(fixtures, { gatewayConfig: { queryPlannerConfig: { cache } } });
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it(`cached query plan`, async () => {
|
|
30
|
-
const query = `
|
|
31
|
-
query {
|
|
32
|
-
me {
|
|
33
|
-
name {
|
|
34
|
-
first
|
|
35
|
-
last
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
topProducts {
|
|
39
|
-
name
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
`;
|
|
43
|
-
|
|
44
|
-
await services.queryGateway(query);
|
|
45
|
-
const queryHash:string = createHash('sha256').update(query).digest('hex');
|
|
46
|
-
expect(await cache.get(queryHash)).toBeTruthy();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it(`cache control`, async () => {
|
|
50
|
-
const query = `
|
|
51
|
-
query {
|
|
52
|
-
me {
|
|
53
|
-
name {
|
|
54
|
-
first
|
|
55
|
-
last
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
topProducts {
|
|
59
|
-
name
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
`;
|
|
63
|
-
|
|
64
|
-
const response = await services.queryGateway(query);
|
|
65
|
-
const result = await response.json();
|
|
66
|
-
expect(result).toMatchInlineSnapshot(`
|
|
67
|
-
Object {
|
|
68
|
-
"data": Object {
|
|
69
|
-
"me": Object {
|
|
70
|
-
"name": Object {
|
|
71
|
-
"first": "Ada",
|
|
72
|
-
"last": "Lovelace",
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
"topProducts": Array [
|
|
76
|
-
Object {
|
|
77
|
-
"name": "Table",
|
|
78
|
-
},
|
|
79
|
-
Object {
|
|
80
|
-
"name": "Couch",
|
|
81
|
-
},
|
|
82
|
-
Object {
|
|
83
|
-
"name": "Chair",
|
|
84
|
-
},
|
|
85
|
-
Object {
|
|
86
|
-
"name": "Structure and Interpretation of Computer Programs (1996)",
|
|
87
|
-
},
|
|
88
|
-
Object {
|
|
89
|
-
"name": "Object Oriented Software Construction (1997)",
|
|
90
|
-
},
|
|
91
|
-
],
|
|
92
|
-
},
|
|
93
|
-
}
|
|
94
|
-
`);
|
|
95
|
-
expect(response.headers.get('cache-control')).toBe('max-age=30, private');
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it(`cache control, uncacheable`, async () => {
|
|
99
|
-
const query = `
|
|
100
|
-
query {
|
|
101
|
-
me {
|
|
102
|
-
name {
|
|
103
|
-
first
|
|
104
|
-
last
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
topProducts {
|
|
108
|
-
name
|
|
109
|
-
... on Book {
|
|
110
|
-
details { # This field has no cache policy.
|
|
111
|
-
pages
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
`;
|
|
117
|
-
|
|
118
|
-
const response = await services.queryGateway(query);
|
|
119
|
-
const result = await response.json();
|
|
120
|
-
expect(result).toMatchInlineSnapshot(`
|
|
121
|
-
Object {
|
|
122
|
-
"data": Object {
|
|
123
|
-
"me": Object {
|
|
124
|
-
"name": Object {
|
|
125
|
-
"first": "Ada",
|
|
126
|
-
"last": "Lovelace",
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
"topProducts": Array [
|
|
130
|
-
Object {
|
|
131
|
-
"name": "Table",
|
|
132
|
-
},
|
|
133
|
-
Object {
|
|
134
|
-
"name": "Couch",
|
|
135
|
-
},
|
|
136
|
-
Object {
|
|
137
|
-
"name": "Chair",
|
|
138
|
-
},
|
|
139
|
-
Object {
|
|
140
|
-
"details": null,
|
|
141
|
-
"name": "Structure and Interpretation of Computer Programs (1996)",
|
|
142
|
-
},
|
|
143
|
-
Object {
|
|
144
|
-
"details": null,
|
|
145
|
-
"name": "Object Oriented Software Construction (1997)",
|
|
146
|
-
},
|
|
147
|
-
],
|
|
148
|
-
},
|
|
149
|
-
}
|
|
150
|
-
`);
|
|
151
|
-
expect(response.headers.get('cache-control')).toBe('no-store');
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Tests for a number of specific features end-to-end.
|
|
157
|
-
* Note that those features have (or at least should have) much thorough test coverage in the various places
|
|
158
|
-
* that handle them more directly, and those tests largely duplicate other test, but it's meant to ensure we
|
|
159
|
-
* have basic end-to-end testing, thus ensuring those feature don't break in places we didn't expect.
|
|
160
|
-
*/
|
|
161
|
-
describe('end-to-end features', () => {
|
|
162
|
-
it('@tag renaming', async () => {
|
|
163
|
-
const subgraphA = {
|
|
164
|
-
name: 'A',
|
|
165
|
-
url: 'https://A',
|
|
166
|
-
typeDefs: gql`
|
|
167
|
-
extend schema
|
|
168
|
-
@link(
|
|
169
|
-
url: "https://specs.apollo.dev/federation/v2.0"
|
|
170
|
-
import: ["@key", { name: "@tag", as: "@federationTag" }]
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
type Query {
|
|
174
|
-
t: T
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
type T @key(fields: "k") {
|
|
178
|
-
k: ID
|
|
179
|
-
x: Int @federationTag(name: "Important")
|
|
180
|
-
}
|
|
181
|
-
`,
|
|
182
|
-
resolvers: {
|
|
183
|
-
Query: {
|
|
184
|
-
t: () => ({
|
|
185
|
-
k: 42,
|
|
186
|
-
x: 1,
|
|
187
|
-
}),
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
const subgraphB = {
|
|
193
|
-
name: 'B',
|
|
194
|
-
url: 'https://B',
|
|
195
|
-
typeDefs: gql`
|
|
196
|
-
extend schema
|
|
197
|
-
@link(
|
|
198
|
-
url: "https://specs.apollo.dev/federation/v2.0"
|
|
199
|
-
import: ["@key", { name: "@tag", as: "@federationTag" }]
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
type T @key(fields: "k") {
|
|
203
|
-
k: ID
|
|
204
|
-
y: Int @federationTag(name: "Less Important")
|
|
205
|
-
}
|
|
206
|
-
`,
|
|
207
|
-
resolvers: {
|
|
208
|
-
T: {
|
|
209
|
-
__resolveReference: ({ k }: { k: string }) => {
|
|
210
|
-
return k === '42' ? { y: 2 } : undefined;
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
services = await startSubgraphsAndGateway([subgraphA, subgraphB]);
|
|
217
|
-
|
|
218
|
-
const query = `
|
|
219
|
-
{
|
|
220
|
-
t {
|
|
221
|
-
x
|
|
222
|
-
y
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
`;
|
|
226
|
-
|
|
227
|
-
const response = await services.queryGateway(query);
|
|
228
|
-
const result = await response.json();
|
|
229
|
-
expect(result).toMatchInlineSnapshot(`
|
|
230
|
-
Object {
|
|
231
|
-
"data": Object {
|
|
232
|
-
"t": Object {
|
|
233
|
-
"x": 1,
|
|
234
|
-
"y": 2,
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
}
|
|
238
|
-
`);
|
|
239
|
-
|
|
240
|
-
const supergraphSdl = services.gateway.__testing().supergraphSdl;
|
|
241
|
-
expect(supergraphSdl).toBeDefined();
|
|
242
|
-
const supergraph = buildSchema(supergraphSdl!);
|
|
243
|
-
const typeT = supergraph.type('T') as ObjectType;
|
|
244
|
-
expect(
|
|
245
|
-
typeT.field('x')?.appliedDirectivesOf('federationTag').toString(),
|
|
246
|
-
).toStrictEqual('@federationTag(name: "Important")');
|
|
247
|
-
expect(
|
|
248
|
-
typeT.field('y')?.appliedDirectivesOf('federationTag').toString(),
|
|
249
|
-
).toStrictEqual('@federationTag(name: "Less Important")');
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('handles fed1 schema', async () => {
|
|
253
|
-
const subgraphA = {
|
|
254
|
-
name: 'A',
|
|
255
|
-
url: 'https://A',
|
|
256
|
-
typeDefs: gql`
|
|
257
|
-
type Query {
|
|
258
|
-
t: T
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
type T @key(fields: "k") {
|
|
262
|
-
k: ID
|
|
263
|
-
x: Int
|
|
264
|
-
}
|
|
265
|
-
`,
|
|
266
|
-
resolvers: {
|
|
267
|
-
Query: {
|
|
268
|
-
t: () => ({
|
|
269
|
-
k: 42,
|
|
270
|
-
x: 1,
|
|
271
|
-
}),
|
|
272
|
-
},
|
|
273
|
-
},
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
const subgraphB = {
|
|
277
|
-
name: 'B',
|
|
278
|
-
url: 'https://B',
|
|
279
|
-
typeDefs: gql`
|
|
280
|
-
type T @key(fields: "k") {
|
|
281
|
-
k: ID
|
|
282
|
-
y: Int
|
|
283
|
-
}
|
|
284
|
-
`,
|
|
285
|
-
resolvers: {
|
|
286
|
-
T: {
|
|
287
|
-
__resolveReference: ({ k }: { k: string }) => {
|
|
288
|
-
return k === '42' ? { y: 2 } : undefined;
|
|
289
|
-
},
|
|
290
|
-
},
|
|
291
|
-
},
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
services = await startSubgraphsAndGateway([subgraphA, subgraphB]);
|
|
295
|
-
|
|
296
|
-
const query = `
|
|
297
|
-
{
|
|
298
|
-
t {
|
|
299
|
-
x
|
|
300
|
-
y
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
`;
|
|
304
|
-
|
|
305
|
-
const response = await services.queryGateway(query);
|
|
306
|
-
const result = await response.json();
|
|
307
|
-
expect(result).toMatchInlineSnapshot(`
|
|
308
|
-
Object {
|
|
309
|
-
"data": Object {
|
|
310
|
-
"t": Object {
|
|
311
|
-
"x": 1,
|
|
312
|
-
"y": 2,
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
}
|
|
316
|
-
`);
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
it('removals of @inaccessible', async () => {
|
|
320
|
-
const subgraphA = {
|
|
321
|
-
name: 'A',
|
|
322
|
-
url: 'https://A',
|
|
323
|
-
typeDefs: gql`
|
|
324
|
-
extend schema
|
|
325
|
-
@link(
|
|
326
|
-
url: "https://specs.apollo.dev/federation/v2.0"
|
|
327
|
-
import: ["@key", "@shareable", "@inaccessible"]
|
|
328
|
-
)
|
|
329
|
-
|
|
330
|
-
type Query {
|
|
331
|
-
t: T
|
|
332
|
-
f(e: E): Int
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
enum E {
|
|
336
|
-
FOO
|
|
337
|
-
BAR @inaccessible
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
type T @key(fields: "k") {
|
|
341
|
-
k: ID
|
|
342
|
-
a: Int @inaccessible
|
|
343
|
-
b: Int
|
|
344
|
-
c: String @shareable
|
|
345
|
-
}
|
|
346
|
-
`,
|
|
347
|
-
resolvers: {
|
|
348
|
-
Query: {
|
|
349
|
-
t: () => ({
|
|
350
|
-
k: 42,
|
|
351
|
-
a: 1,
|
|
352
|
-
b: 2,
|
|
353
|
-
c: 3,
|
|
354
|
-
}),
|
|
355
|
-
f: (_: any, args: any) => {
|
|
356
|
-
return args.e === 'FOO' ? 0 : 1;
|
|
357
|
-
},
|
|
358
|
-
},
|
|
359
|
-
},
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
const subgraphB = {
|
|
363
|
-
name: 'B',
|
|
364
|
-
url: 'https://B',
|
|
365
|
-
typeDefs: gql`
|
|
366
|
-
extend schema
|
|
367
|
-
@link(
|
|
368
|
-
url: "https://specs.apollo.dev/federation/v2.0"
|
|
369
|
-
import: ["@key", "@shareable", "@inaccessible"]
|
|
370
|
-
)
|
|
371
|
-
|
|
372
|
-
type T @key(fields: "k") {
|
|
373
|
-
k: ID
|
|
374
|
-
c: String @shareable @inaccessible
|
|
375
|
-
d: String
|
|
376
|
-
}
|
|
377
|
-
`,
|
|
378
|
-
resolvers: {
|
|
379
|
-
T: {
|
|
380
|
-
__resolveReference: ({ k }: { k: string }) => {
|
|
381
|
-
return k === '42' ? { c: 'foo', d: 'bar' } : undefined;
|
|
382
|
-
},
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
services = await startSubgraphsAndGateway([subgraphA, subgraphB]);
|
|
388
|
-
|
|
389
|
-
const q1 = `
|
|
390
|
-
{
|
|
391
|
-
t {
|
|
392
|
-
b
|
|
393
|
-
d
|
|
394
|
-
}
|
|
395
|
-
f(e: FOO)
|
|
396
|
-
}
|
|
397
|
-
`;
|
|
398
|
-
|
|
399
|
-
const resp1 = await services.queryGateway(q1);
|
|
400
|
-
const res1 = await resp1.json();
|
|
401
|
-
expect(res1).toMatchInlineSnapshot(`
|
|
402
|
-
Object {
|
|
403
|
-
"data": Object {
|
|
404
|
-
"f": 0,
|
|
405
|
-
"t": Object {
|
|
406
|
-
"b": 2,
|
|
407
|
-
"d": "bar",
|
|
408
|
-
},
|
|
409
|
-
},
|
|
410
|
-
}
|
|
411
|
-
`);
|
|
412
|
-
|
|
413
|
-
// Make sure the exposed API doesn't have any @inaccessible elements.
|
|
414
|
-
expect(printSchema(services.gateway.schema!)).toMatchInlineSnapshot(`
|
|
415
|
-
"enum E {
|
|
416
|
-
FOO
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
type Query {
|
|
420
|
-
t: T
|
|
421
|
-
f(e: E): Int
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
type T {
|
|
425
|
-
k: ID
|
|
426
|
-
b: Int
|
|
427
|
-
d: String
|
|
428
|
-
}"
|
|
429
|
-
`);
|
|
430
|
-
|
|
431
|
-
// Lastly, make sure querying inaccessible things is rejected
|
|
432
|
-
const q2 = `
|
|
433
|
-
{
|
|
434
|
-
f(e: BAR)
|
|
435
|
-
}
|
|
436
|
-
`;
|
|
437
|
-
const resp2 = await services.queryGateway(q2);
|
|
438
|
-
const res2 = await resp2.json();
|
|
439
|
-
expect(res2).toMatchInlineSnapshot(`
|
|
440
|
-
Object {
|
|
441
|
-
"errors": Array [
|
|
442
|
-
Object {
|
|
443
|
-
"extensions": Object {
|
|
444
|
-
"code": "GRAPHQL_VALIDATION_FAILED",
|
|
445
|
-
},
|
|
446
|
-
"locations": Array [
|
|
447
|
-
Object {
|
|
448
|
-
"column": 14,
|
|
449
|
-
"line": 3,
|
|
450
|
-
},
|
|
451
|
-
],
|
|
452
|
-
"message": "Value \\"BAR\\" does not exist in \\"E\\" enum.",
|
|
453
|
-
},
|
|
454
|
-
],
|
|
455
|
-
}
|
|
456
|
-
`);
|
|
457
|
-
|
|
458
|
-
const q3 = `
|
|
459
|
-
{
|
|
460
|
-
t {
|
|
461
|
-
a
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
`;
|
|
465
|
-
const resp3 = await services.queryGateway(q3);
|
|
466
|
-
const res3 = await resp3.json();
|
|
467
|
-
expect(res3).toMatchInlineSnapshot(`
|
|
468
|
-
Object {
|
|
469
|
-
"errors": Array [
|
|
470
|
-
Object {
|
|
471
|
-
"extensions": Object {
|
|
472
|
-
"code": "GRAPHQL_VALIDATION_FAILED",
|
|
473
|
-
},
|
|
474
|
-
"locations": Array [
|
|
475
|
-
Object {
|
|
476
|
-
"column": 11,
|
|
477
|
-
"line": 4,
|
|
478
|
-
},
|
|
479
|
-
],
|
|
480
|
-
"message": "Cannot query field \\"a\\" on type \\"T\\". Did you mean \\"b\\", \\"d\\", or \\"k\\"?",
|
|
481
|
-
},
|
|
482
|
-
],
|
|
483
|
-
}
|
|
484
|
-
`);
|
|
485
|
-
});
|
|
486
|
-
});
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import nock from 'nock';
|
|
2
|
-
import gql from 'graphql-tag';
|
|
3
|
-
import { ApolloGateway } from '../../';
|
|
4
|
-
import { accounts, fixtures } from 'apollo-federation-integration-testsuite';
|
|
5
|
-
import type { Logger } from '@apollo/utils.logger';
|
|
6
|
-
import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
|
|
7
|
-
|
|
8
|
-
let logger: {
|
|
9
|
-
warn: jest.MockedFunction<Logger['warn']>;
|
|
10
|
-
debug: jest.MockedFunction<Logger['debug']>;
|
|
11
|
-
error: jest.MockedFunction<Logger['error']>;
|
|
12
|
-
info: jest.MockedFunction<Logger['info']>;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
beforeEach(nockBeforeEach);
|
|
16
|
-
afterEach(nockAfterEach);
|
|
17
|
-
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
logger = {
|
|
20
|
-
warn: jest.fn(),
|
|
21
|
-
debug: jest.fn(),
|
|
22
|
-
error: jest.fn(),
|
|
23
|
-
info: jest.fn(),
|
|
24
|
-
};
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe('ApolloGateway executor', () => {
|
|
28
|
-
it('validates requests prior to execution', async () => {
|
|
29
|
-
const gateway = new ApolloGateway({
|
|
30
|
-
localServiceList: fixtures,
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const { executor } = await gateway.load();
|
|
34
|
-
|
|
35
|
-
const source = `#graphql
|
|
36
|
-
query InvalidVariables($first: Int!) {
|
|
37
|
-
topReviews(first: $first) {
|
|
38
|
-
body
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
`;
|
|
42
|
-
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
44
|
-
// @ts-ignore
|
|
45
|
-
const { errors } = await executor({
|
|
46
|
-
source,
|
|
47
|
-
document: gql(source),
|
|
48
|
-
request: {
|
|
49
|
-
variables: { first: '3' },
|
|
50
|
-
},
|
|
51
|
-
queryHash: 'hashed',
|
|
52
|
-
context: {},
|
|
53
|
-
cache: {} as any,
|
|
54
|
-
logger,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
expect(errors![0].message).toMatch(
|
|
58
|
-
'Variable "$first" got invalid value "3";',
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should not crash if variables are not provided', async () => {
|
|
63
|
-
const me = { birthDate: '1988-10-21' };
|
|
64
|
-
|
|
65
|
-
nock(accounts.url).post('/').reply(200, { data: { me } });
|
|
66
|
-
|
|
67
|
-
const gateway = new ApolloGateway({
|
|
68
|
-
localServiceList: fixtures,
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const { executor } = await gateway.load();
|
|
72
|
-
|
|
73
|
-
const source = `#graphql
|
|
74
|
-
query Me($locale: String) {
|
|
75
|
-
me {
|
|
76
|
-
birthDate(locale: $locale)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
`;
|
|
80
|
-
|
|
81
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
82
|
-
// @ts-ignore
|
|
83
|
-
const { errors, data } = await executor({
|
|
84
|
-
source,
|
|
85
|
-
document: gql(source),
|
|
86
|
-
request: {},
|
|
87
|
-
queryHash: 'hashed',
|
|
88
|
-
context: {},
|
|
89
|
-
cache: {} as any,
|
|
90
|
-
logger,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
expect(errors).toBeFalsy();
|
|
94
|
-
expect(data).toEqual({ me });
|
|
95
|
-
});
|
|
96
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { ApolloGateway } from '@apollo/gateway';
|
|
2
|
-
import resolvable from '@josephg/resolvable';
|
|
3
|
-
import { GraphQLSchema } from 'graphql';
|
|
4
|
-
import { getTestingSupergraphSdl } from '../execution-utils';
|
|
5
|
-
const { version } = require('../../../package.json');
|
|
6
|
-
|
|
7
|
-
describe('addExtensions', () => {
|
|
8
|
-
let gateway: ApolloGateway;
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
gateway = new ApolloGateway({
|
|
12
|
-
supergraphSdl: getTestingSupergraphSdl(),
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterEach(async () => {
|
|
17
|
-
await gateway.stop();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('has extensions on loaded schemas', async () => {
|
|
21
|
-
const { schema } = await gateway.load();
|
|
22
|
-
expect(schema.extensions).toEqual({ apollo: { gateway: { version: version } } });
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('has extensions on schema updates', async () => {
|
|
26
|
-
const schemaChangeBlocker = resolvable<{
|
|
27
|
-
apiSchema: GraphQLSchema;
|
|
28
|
-
coreSupergraphSdl: string;
|
|
29
|
-
}>();
|
|
30
|
-
|
|
31
|
-
gateway.onSchemaLoadOrUpdate(schemaChangeBlocker.resolve);
|
|
32
|
-
gateway.load();
|
|
33
|
-
|
|
34
|
-
const { apiSchema } = await schemaChangeBlocker;
|
|
35
|
-
expect(apiSchema.extensions).toEqual({ apollo: { gateway: { version: version } } });
|
|
36
|
-
});
|
|
37
|
-
});
|