@apollo/gateway 2.3.3 → 2.4.0-alpha.0
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/executeQueryPlan.d.ts.map +1 -1
- package/dist/executeQueryPlan.js +38 -12
- package/dist/executeQueryPlan.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -9
- package/dist/index.js.map +1 -1
- package/dist/resultShaping.d.ts.map +1 -1
- package/dist/resultShaping.js +4 -2
- package/dist/resultShaping.js.map +1 -1
- package/package.json +6 -6
- package/src/__tests__/executeQueryPlan.conditions.test.ts +1488 -0
- package/src/__tests__/executeQueryPlan.test.ts +28 -16
- package/src/__tests__/execution-utils.ts +3 -3
- package/src/__tests__/gateway/buildService.test.ts +17 -13
- package/src/__tests__/gateway/endToEnd.test.ts +91 -94
- package/src/__tests__/gateway/queryPlanCache.test.ts +18 -19
- package/src/__tests__/gateway/queryPlannerConfig.test.ts +101 -0
- package/src/__tests__/gateway/reporting.test.ts +23 -45
- package/src/__tests__/gateway/supergraphSdl.test.ts +5 -3
- package/src/__tests__/gateway/testUtils.ts +89 -0
- package/src/__tests__/integration/aliases.test.ts +5 -5
- package/src/__tests__/integration/boolean.test.ts +9 -9
- package/src/__tests__/integration/managed.test.ts +10 -9
- package/src/__tests__/resultShaping.test.ts +75 -3
- package/src/executeQueryPlan.ts +58 -18
- package/src/index.ts +10 -5
- package/src/resultShaping.ts +8 -4
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import gql from 'graphql-tag';
|
|
2
|
+
import { startSubgraphsAndGateway, Services } from './testUtils'
|
|
3
|
+
|
|
4
|
+
let services: Services;
|
|
5
|
+
|
|
6
|
+
afterEach(async () => {
|
|
7
|
+
if (services) {
|
|
8
|
+
await services.stop();
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe('`debug.bypassPlannerForSingleSubgraph` config', () => {
|
|
13
|
+
const subgraph = {
|
|
14
|
+
name: 'A',
|
|
15
|
+
url: 'https://A',
|
|
16
|
+
typeDefs: gql`
|
|
17
|
+
type Query {
|
|
18
|
+
a: A
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type A {
|
|
22
|
+
b: B
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type B {
|
|
26
|
+
x: Int
|
|
27
|
+
y: String
|
|
28
|
+
}
|
|
29
|
+
`,
|
|
30
|
+
resolvers: {
|
|
31
|
+
Query: {
|
|
32
|
+
a: () => ({
|
|
33
|
+
b: {
|
|
34
|
+
x: 1,
|
|
35
|
+
y: 'foo',
|
|
36
|
+
}
|
|
37
|
+
}),
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const query = `
|
|
43
|
+
{
|
|
44
|
+
a {
|
|
45
|
+
b {
|
|
46
|
+
x
|
|
47
|
+
y
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
const expectedResult = `
|
|
54
|
+
Object {
|
|
55
|
+
"data": Object {
|
|
56
|
+
"a": Object {
|
|
57
|
+
"b": Object {
|
|
58
|
+
"x": 1,
|
|
59
|
+
"y": "foo",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
it('is disabled by default', async () => {
|
|
67
|
+
services = await startSubgraphsAndGateway([subgraph]);
|
|
68
|
+
|
|
69
|
+
const response = await services.queryGateway(query);
|
|
70
|
+
const result = await response.json();
|
|
71
|
+
expect(result).toMatchInlineSnapshot(expectedResult);
|
|
72
|
+
|
|
73
|
+
const queryPlanner = services.gateway.__testing().queryPlanner!;
|
|
74
|
+
// If the query planner is genuinely used, we shoud have evaluated 1 plan.
|
|
75
|
+
expect(queryPlanner.lastGeneratedPlanStatistics()?.evaluatedPlanCount).toBe(1);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('works when enabled', async () => {
|
|
79
|
+
services = await startSubgraphsAndGateway(
|
|
80
|
+
[subgraph],
|
|
81
|
+
{
|
|
82
|
+
gatewayConfig: {
|
|
83
|
+
queryPlannerConfig: {
|
|
84
|
+
debug: {
|
|
85
|
+
bypassPlannerForSingleSubgraph: true,
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const response = await services.queryGateway(query);
|
|
93
|
+
const result = await response.json();
|
|
94
|
+
expect(result).toMatchInlineSnapshot(expectedResult);
|
|
95
|
+
|
|
96
|
+
const queryPlanner = services.gateway.__testing().queryPlanner!;
|
|
97
|
+
// The `bypassPlannerForSingleSubgraph` doesn't evaluate anything. It's use is the only case where `evaluatedPlanCount` can be 0.
|
|
98
|
+
expect(queryPlanner.lastGeneratedPlanStatistics()?.evaluatedPlanCount).toBe(0);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import { gunzipSync } from 'zlib';
|
|
2
2
|
import nock from 'nock';
|
|
3
3
|
import gql from 'graphql-tag';
|
|
4
|
-
import {
|
|
5
|
-
import { ApolloServer } from 'apollo-server';
|
|
6
|
-
import { ApolloServerPluginUsageReporting } from 'apollo-server-core';
|
|
4
|
+
import { ApolloServerPluginUsageReporting } from '@apollo/server/plugin/usageReporting';
|
|
7
5
|
import { execute } from '@apollo/client/link/core';
|
|
8
6
|
import { toPromise } from '@apollo/client/link/utils';
|
|
9
7
|
import { createHttpLink } from '@apollo/client/link/http';
|
|
10
8
|
import fetch from 'node-fetch';
|
|
11
|
-
import { ApolloGateway } from '../..';
|
|
12
9
|
import { Plugin, Config, Refs } from 'pretty-format';
|
|
13
10
|
import { Report, Trace } from '@apollo/usage-reporting-protobuf';
|
|
14
11
|
import { fixtures } from 'apollo-federation-integration-testsuite';
|
|
15
12
|
import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
|
|
16
|
-
import { GraphQLSchemaModule } from '@apollo/subgraph/src/schema-helper';
|
|
17
13
|
import resolvable, { Resolvable } from '@josephg/resolvable';
|
|
14
|
+
import { startSubgraphsAndGateway, Services } from './testUtils';
|
|
18
15
|
|
|
19
16
|
// Normalize specific fields that change often (eg timestamps) to static values,
|
|
20
17
|
// to make snapshot testing viable. (If these helpers are more generally
|
|
@@ -80,17 +77,8 @@ expect.addSnapshotSerializer(
|
|
|
80
77
|
}),
|
|
81
78
|
);
|
|
82
79
|
|
|
83
|
-
async function startFederatedServer(modules: GraphQLSchemaModule[]) {
|
|
84
|
-
const schema = buildSubgraphSchema(modules);
|
|
85
|
-
const server = new ApolloServer({ schema });
|
|
86
|
-
const { url } = await server.listen({ port: 0 });
|
|
87
|
-
return { url, server };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
80
|
describe('reporting', () => {
|
|
91
|
-
let
|
|
92
|
-
let gatewayServer: ApolloServer;
|
|
93
|
-
let gatewayUrl: string;
|
|
81
|
+
let services: Services;
|
|
94
82
|
let reportPromise: Resolvable<any>;
|
|
95
83
|
|
|
96
84
|
beforeEach(async () => {
|
|
@@ -104,38 +92,27 @@ describe('reporting', () => {
|
|
|
104
92
|
return 'ok';
|
|
105
93
|
});
|
|
106
94
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
},
|
|
124
|
-
plugins: [
|
|
125
|
-
ApolloServerPluginUsageReporting({
|
|
126
|
-
sendReportsImmediately: true,
|
|
127
|
-
}),
|
|
128
|
-
],
|
|
129
|
-
});
|
|
130
|
-
({ url: gatewayUrl } = await gatewayServer.listen({ port: 0 }));
|
|
95
|
+
services = await startSubgraphsAndGateway(
|
|
96
|
+
fixtures,
|
|
97
|
+
{
|
|
98
|
+
gatewayServerConfig: {
|
|
99
|
+
apollo: {
|
|
100
|
+
key: 'service:foo:bar',
|
|
101
|
+
graphRef: 'foo@current',
|
|
102
|
+
},
|
|
103
|
+
plugins: [
|
|
104
|
+
ApolloServerPluginUsageReporting({
|
|
105
|
+
sendReportsImmediately: true,
|
|
106
|
+
}),
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
);
|
|
131
111
|
});
|
|
132
112
|
|
|
133
113
|
afterEach(async () => {
|
|
134
|
-
|
|
135
|
-
await
|
|
136
|
-
}
|
|
137
|
-
if (gatewayServer) {
|
|
138
|
-
await gatewayServer.stop();
|
|
114
|
+
if (services) {
|
|
115
|
+
await services.stop();
|
|
139
116
|
}
|
|
140
117
|
|
|
141
118
|
nockAfterEach();
|
|
@@ -157,7 +134,7 @@ describe('reporting', () => {
|
|
|
157
134
|
`;
|
|
158
135
|
|
|
159
136
|
const result = await toPromise(
|
|
160
|
-
execute(createHttpLink({ uri: gatewayUrl, fetch: fetch as any }), {
|
|
137
|
+
execute(createHttpLink({ uri: services.gatewayUrl, fetch: fetch as any }), {
|
|
161
138
|
query,
|
|
162
139
|
}),
|
|
163
140
|
);
|
|
@@ -632,6 +609,7 @@ describe('reporting', () => {
|
|
|
632
609
|
],
|
|
633
610
|
},
|
|
634
611
|
},
|
|
612
|
+
"tracesPreAggregated": false,
|
|
635
613
|
}
|
|
636
614
|
`);
|
|
637
615
|
});
|
|
@@ -6,13 +6,15 @@ import {
|
|
|
6
6
|
} from '@apollo/gateway';
|
|
7
7
|
import { accounts, fixturesWithUpdate } from 'apollo-federation-integration-testsuite';
|
|
8
8
|
import { createHash } from '@apollo/utils.createhash';
|
|
9
|
-
import { ApolloServer } from 'apollo
|
|
9
|
+
import { ApolloServer } from '@apollo/server';
|
|
10
|
+
import { startStandaloneServer } from '@apollo/server/standalone';
|
|
10
11
|
import type { Logger } from '@apollo/utils.logger';
|
|
11
12
|
import { getTestingSupergraphSdl } from '../execution-utils';
|
|
12
13
|
import { mockAllServicesHealthCheckSuccess } from '../integration/nockMocks';
|
|
13
14
|
import resolvable from '@josephg/resolvable';
|
|
14
15
|
import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
|
|
15
16
|
import nock from 'nock';
|
|
17
|
+
import { unwrapSingleResultKind } from '../gateway/testUtils';
|
|
16
18
|
|
|
17
19
|
async function getSupergraphSdlGatewayServer() {
|
|
18
20
|
const server = new ApolloServer({
|
|
@@ -26,7 +28,7 @@ async function getSupergraphSdlGatewayServer() {
|
|
|
26
28
|
}),
|
|
27
29
|
});
|
|
28
30
|
|
|
29
|
-
await server
|
|
31
|
+
await startStandaloneServer(server, { listen: { port: 0 } });
|
|
30
32
|
return server;
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -67,7 +69,7 @@ describe('Using supergraphSdl static configuration', () => {
|
|
|
67
69
|
query: '{ me { username } }',
|
|
68
70
|
});
|
|
69
71
|
|
|
70
|
-
expect(result.data).toMatchInlineSnapshot(`
|
|
72
|
+
expect(unwrapSingleResultKind(result).data).toMatchInlineSnapshot(`
|
|
71
73
|
Object {
|
|
72
74
|
"me": Object {
|
|
73
75
|
"username": "@jbaxleyiii",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { buildSubgraphSchema } from '@apollo/subgraph';
|
|
2
|
+
import {
|
|
3
|
+
ApolloServer,
|
|
4
|
+
ApolloServerOptionsWithGateway,
|
|
5
|
+
BaseContext,
|
|
6
|
+
GraphQLResponse,
|
|
7
|
+
} from '@apollo/server';
|
|
8
|
+
import { startStandaloneServer } from '@apollo/server/standalone';
|
|
9
|
+
import { ApolloServerPluginInlineTrace } from '@apollo/server/plugin/inlineTrace';
|
|
10
|
+
import { GraphQLSchemaModule } from '@apollo/subgraph/src/schema-helper';
|
|
11
|
+
import { ApolloGateway, GatewayConfig } from '../..';
|
|
12
|
+
import { ServiceDefinition } from '@apollo/federation-internals';
|
|
13
|
+
import fetch, { Response } from 'node-fetch';
|
|
14
|
+
import { assert } from '@apollo/federation-internals';
|
|
15
|
+
|
|
16
|
+
export class Services {
|
|
17
|
+
constructor(
|
|
18
|
+
readonly subgraphServers: ApolloServer[],
|
|
19
|
+
readonly gateway: ApolloGateway,
|
|
20
|
+
readonly gatewayServer: ApolloServer,
|
|
21
|
+
readonly gatewayUrl: string,
|
|
22
|
+
) {
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async queryGateway(query: string): Promise<Response> {
|
|
26
|
+
return fetch(this.gatewayUrl, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
headers: {
|
|
29
|
+
'Content-Type': 'application/json',
|
|
30
|
+
},
|
|
31
|
+
body: JSON.stringify({ query }),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async stop() {
|
|
36
|
+
for (const server of this.subgraphServers) {
|
|
37
|
+
await server.stop();
|
|
38
|
+
}
|
|
39
|
+
await this.gatewayServer.stop();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function startFederatedServer(modules: GraphQLSchemaModule[]) {
|
|
44
|
+
const schema = buildSubgraphSchema(modules);
|
|
45
|
+
const server = new ApolloServer({
|
|
46
|
+
schema,
|
|
47
|
+
// Manually installing the inline trace plugin means it doesn't log a message.
|
|
48
|
+
plugins: [ApolloServerPluginInlineTrace()],
|
|
49
|
+
});
|
|
50
|
+
const { url } = await startStandaloneServer(server, { listen: { port: 0 } });
|
|
51
|
+
return { url, server };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function startSubgraphsAndGateway(
|
|
55
|
+
servicesDefs: ServiceDefinition[],
|
|
56
|
+
config?: {
|
|
57
|
+
gatewayConfig?: GatewayConfig;
|
|
58
|
+
gatewayServerConfig?: Partial<ApolloServerOptionsWithGateway<BaseContext>>;
|
|
59
|
+
},
|
|
60
|
+
): Promise<Services> {
|
|
61
|
+
const backendServers = [];
|
|
62
|
+
const serviceList = [];
|
|
63
|
+
for (const serviceDef of servicesDefs) {
|
|
64
|
+
const { server, url } = await startFederatedServer([serviceDef]);
|
|
65
|
+
backendServers.push(server);
|
|
66
|
+
serviceList.push({ name: serviceDef.name, url });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const gateway = new ApolloGateway({
|
|
70
|
+
serviceList,
|
|
71
|
+
...config?.gatewayConfig,
|
|
72
|
+
});
|
|
73
|
+
const gatewayServer = new ApolloServer({
|
|
74
|
+
gateway,
|
|
75
|
+
...config?.gatewayServerConfig,
|
|
76
|
+
});
|
|
77
|
+
const { url: gatewayUrl } = await startStandaloneServer(gatewayServer, {
|
|
78
|
+
listen: { port: 0 },
|
|
79
|
+
});
|
|
80
|
+
return new Services(backendServers, gateway, gatewayServer, gatewayUrl);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function unwrapSingleResultKind(response: GraphQLResponse) {
|
|
84
|
+
assert(
|
|
85
|
+
response.body.kind === 'single',
|
|
86
|
+
`Expected single result, got ${response.body.kind}`,
|
|
87
|
+
);
|
|
88
|
+
return response.body.singleResult;
|
|
89
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { execute } from '../execution-utils';
|
|
2
|
-
import {
|
|
2
|
+
import { ApolloServer } from '@apollo/server';
|
|
3
3
|
import { buildSubgraphSchema } from '@apollo/subgraph';
|
|
4
4
|
import { LocalGraphQLDataSource } from '../../datasources/LocalGraphQLDataSource';
|
|
5
5
|
import { ApolloGateway } from '../../';
|
|
6
6
|
import { fixtures } from 'apollo-federation-integration-testsuite';
|
|
7
|
+
import { unwrapSingleResultKind } from '../gateway/testUtils';
|
|
7
8
|
|
|
8
9
|
it('supports simple aliases', async () => {
|
|
9
10
|
const query = `#graphql
|
|
@@ -155,9 +156,8 @@ it('supports aliases when using ApolloServer', async () => {
|
|
|
155
156
|
},
|
|
156
157
|
});
|
|
157
158
|
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
const server = new ApolloServer({ schema, executor });
|
|
159
|
+
const server = new ApolloServer({ gateway });
|
|
160
|
+
await server.start();
|
|
161
161
|
|
|
162
162
|
const upc = '1';
|
|
163
163
|
|
|
@@ -172,7 +172,7 @@ it('supports aliases when using ApolloServer', async () => {
|
|
|
172
172
|
variables: { upc },
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
-
expect(result.data).toEqual({
|
|
175
|
+
expect(unwrapSingleResultKind(result).data).toEqual({
|
|
176
176
|
product: {
|
|
177
177
|
title: 'Table',
|
|
178
178
|
},
|
|
@@ -4,8 +4,6 @@ import { astSerializer, queryPlanSerializer } from 'apollo-federation-integratio
|
|
|
4
4
|
expect.addSnapshotSerializer(astSerializer);
|
|
5
5
|
expect.addSnapshotSerializer(queryPlanSerializer);
|
|
6
6
|
|
|
7
|
-
// TODO: right now the query planner doesn't prune known skip and include points
|
|
8
|
-
// eventually we want to do this to prevent downstream fetches that aren't needed
|
|
9
7
|
describe('@skip', () => {
|
|
10
8
|
it('supports @skip when a boolean condition is met', async () => {
|
|
11
9
|
const query = `#graphql
|
|
@@ -35,8 +33,8 @@ describe('@skip', () => {
|
|
|
35
33
|
],
|
|
36
34
|
});
|
|
37
35
|
|
|
38
|
-
expect(queryPlan).toCallService('accounts');
|
|
39
36
|
expect(queryPlan).toCallService('reviews');
|
|
37
|
+
expect(queryPlan).not.toCallService('accounts');
|
|
40
38
|
});
|
|
41
39
|
|
|
42
40
|
it('supports @skip when a boolean condition is met (variable driven)', async () => {
|
|
@@ -122,7 +120,7 @@ describe('@skip', () => {
|
|
|
122
120
|
`;
|
|
123
121
|
|
|
124
122
|
const skip = false;
|
|
125
|
-
const { data, queryPlan } = await execute({
|
|
123
|
+
const { data, queryPlan, operation } = await execute({
|
|
126
124
|
query,
|
|
127
125
|
variables: { skip },
|
|
128
126
|
});
|
|
@@ -137,8 +135,9 @@ describe('@skip', () => {
|
|
|
137
135
|
],
|
|
138
136
|
});
|
|
139
137
|
|
|
140
|
-
|
|
141
|
-
expect(queryPlan).toCallService('reviews');
|
|
138
|
+
const variables = { definitions: operation.variableDefinitions, values: {skip} };
|
|
139
|
+
expect(queryPlan).toCallService('reviews', variables);
|
|
140
|
+
expect(queryPlan).toCallService('accounts', variables);
|
|
142
141
|
});
|
|
143
142
|
});
|
|
144
143
|
|
|
@@ -258,7 +257,7 @@ describe('@include', () => {
|
|
|
258
257
|
`;
|
|
259
258
|
|
|
260
259
|
const include = true;
|
|
261
|
-
const { data, queryPlan } = await execute({
|
|
260
|
+
const { data, queryPlan, operation } = await execute({
|
|
262
261
|
query,
|
|
263
262
|
variables: { include },
|
|
264
263
|
});
|
|
@@ -273,7 +272,8 @@ describe('@include', () => {
|
|
|
273
272
|
],
|
|
274
273
|
});
|
|
275
274
|
|
|
276
|
-
|
|
277
|
-
expect(queryPlan).toCallService('
|
|
275
|
+
const variables = { definitions: operation.variableDefinitions, values: {include} };
|
|
276
|
+
expect(queryPlan).toCallService('accounts', variables);
|
|
277
|
+
expect(queryPlan).toCallService('reviews', variables);
|
|
278
278
|
});
|
|
279
279
|
});
|
|
@@ -2,8 +2,9 @@ import mockedEnv from 'mocked-env';
|
|
|
2
2
|
import fetcher from 'make-fetch-happen';
|
|
3
3
|
|
|
4
4
|
import { ApolloGateway, UplinkSupergraphManager } from '@apollo/gateway';
|
|
5
|
-
import { ApolloServer } from 'apollo
|
|
6
|
-
import {
|
|
5
|
+
import { ApolloServer } from '@apollo/server';
|
|
6
|
+
import { startStandaloneServer } from '@apollo/server/standalone';
|
|
7
|
+
import { ApolloServerPluginUsageReportingDisabled } from '@apollo/server/plugin/disabled';
|
|
7
8
|
import type { FetcherRequestInit } from '@apollo/utils.fetcher';
|
|
8
9
|
|
|
9
10
|
import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
|
|
@@ -62,7 +63,7 @@ describe('minimal gateway', () => {
|
|
|
62
63
|
gateway,
|
|
63
64
|
plugins: [ApolloServerPluginUsageReportingDisabled()],
|
|
64
65
|
});
|
|
65
|
-
await server
|
|
66
|
+
await startStandaloneServer(server, { listen: { port: 0 } });
|
|
66
67
|
expect(gateway.supergraphManager).toBeInstanceOf(UplinkSupergraphManager);
|
|
67
68
|
});
|
|
68
69
|
|
|
@@ -80,7 +81,7 @@ describe('minimal gateway', () => {
|
|
|
80
81
|
gateway,
|
|
81
82
|
plugins: [ApolloServerPluginUsageReportingDisabled()],
|
|
82
83
|
});
|
|
83
|
-
await server
|
|
84
|
+
await startStandaloneServer(server, { listen: { port: 0 } });
|
|
84
85
|
expect(gateway.supergraphManager).toBeInstanceOf(UplinkSupergraphManager);
|
|
85
86
|
const uplinkManager = gateway.supergraphManager as UplinkSupergraphManager;
|
|
86
87
|
expect(uplinkManager.uplinkEndpoints).toEqual([uplinkEndpoint]);
|
|
@@ -100,7 +101,7 @@ describe('minimal gateway', () => {
|
|
|
100
101
|
gateway,
|
|
101
102
|
plugins: [ApolloServerPluginUsageReportingDisabled()],
|
|
102
103
|
});
|
|
103
|
-
await server
|
|
104
|
+
await startStandaloneServer(server, { listen: { port: 0 } });
|
|
104
105
|
expect(gateway.supergraphManager).toBeInstanceOf(UplinkSupergraphManager);
|
|
105
106
|
const uplinkManager = gateway.supergraphManager as UplinkSupergraphManager;
|
|
106
107
|
expect(uplinkManager.uplinkEndpoints).toEqual([
|
|
@@ -127,7 +128,7 @@ describe('minimal gateway', () => {
|
|
|
127
128
|
gateway,
|
|
128
129
|
plugins: [ApolloServerPluginUsageReportingDisabled()],
|
|
129
130
|
});
|
|
130
|
-
await server
|
|
131
|
+
await startStandaloneServer(server, { listen: { port: 0 } });
|
|
131
132
|
|
|
132
133
|
expect(calls).toEqual(1);
|
|
133
134
|
});
|
|
@@ -180,7 +181,7 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
180
181
|
|
|
181
182
|
const supergraphSchema = getTestingSupergraphSdl();
|
|
182
183
|
let hasFired;
|
|
183
|
-
|
|
184
|
+
const uplinkManager = new UplinkSupergraphManager({
|
|
184
185
|
apiKey,
|
|
185
186
|
graphRef,
|
|
186
187
|
logger,
|
|
@@ -246,7 +247,7 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
246
247
|
.reply(500);
|
|
247
248
|
|
|
248
249
|
let hasFired;
|
|
249
|
-
|
|
250
|
+
const uplinkManager = new UplinkSupergraphManager({
|
|
250
251
|
apiKey,
|
|
251
252
|
graphRef,
|
|
252
253
|
logger,
|
|
@@ -285,7 +286,7 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
285
286
|
.reply(500);
|
|
286
287
|
|
|
287
288
|
let hasFired;
|
|
288
|
-
|
|
289
|
+
const uplinkManager = new UplinkSupergraphManager({
|
|
289
290
|
apiKey,
|
|
290
291
|
graphRef,
|
|
291
292
|
logger,
|
|
@@ -249,7 +249,7 @@ describe('gateway post-processing', () => {
|
|
|
249
249
|
}
|
|
250
250
|
`);
|
|
251
251
|
|
|
252
|
-
|
|
252
|
+
const res = computeResponse({
|
|
253
253
|
operation: operationNonNullable,
|
|
254
254
|
input,
|
|
255
255
|
introspectionHandling,
|
|
@@ -280,7 +280,7 @@ describe('gateway post-processing', () => {
|
|
|
280
280
|
}
|
|
281
281
|
`);
|
|
282
282
|
|
|
283
|
-
|
|
283
|
+
const res = computeResponse({
|
|
284
284
|
operation: operationNonNullable,
|
|
285
285
|
input,
|
|
286
286
|
introspectionHandling,
|
|
@@ -365,7 +365,7 @@ describe('gateway post-processing', () => {
|
|
|
365
365
|
`);
|
|
366
366
|
|
|
367
367
|
const input = {
|
|
368
|
-
"x": 'foo',
|
|
368
|
+
"x": 'foo',
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
const operation = parseOperation(schema, `
|
|
@@ -530,4 +530,76 @@ describe('gateway post-processing', () => {
|
|
|
530
530
|
}
|
|
531
531
|
`);
|
|
532
532
|
});
|
|
533
|
+
|
|
534
|
+
test('Handles defaulted `if` conditions', () => {
|
|
535
|
+
const schema = buildSchemaFromAST(gql`
|
|
536
|
+
type Query {
|
|
537
|
+
hello: String!
|
|
538
|
+
}
|
|
539
|
+
`);
|
|
540
|
+
|
|
541
|
+
const input = {
|
|
542
|
+
skipped: 'world',
|
|
543
|
+
included: 'world',
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
const operation = parseOperation(schema, `#graphql
|
|
547
|
+
query DefaultedIfCondition($if: Boolean = true) {
|
|
548
|
+
skipped: hello @skip(if: $if)
|
|
549
|
+
included: hello @include(if: $if)
|
|
550
|
+
}
|
|
551
|
+
`);
|
|
552
|
+
|
|
553
|
+
expect(
|
|
554
|
+
computeResponse({
|
|
555
|
+
operation,
|
|
556
|
+
input,
|
|
557
|
+
introspectionHandling,
|
|
558
|
+
}),
|
|
559
|
+
).toMatchInlineSnapshot(`
|
|
560
|
+
Object {
|
|
561
|
+
"data": Object {
|
|
562
|
+
"included": "world",
|
|
563
|
+
},
|
|
564
|
+
"errors": Array [],
|
|
565
|
+
}
|
|
566
|
+
`);
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
test('Provided variables overwrite defaulted variable values', () => {
|
|
570
|
+
const schema = buildSchemaFromAST(gql`
|
|
571
|
+
type Query {
|
|
572
|
+
hello: String!
|
|
573
|
+
}
|
|
574
|
+
`);
|
|
575
|
+
|
|
576
|
+
const input = {
|
|
577
|
+
skipped: 'world',
|
|
578
|
+
included: 'world',
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
const operation = parseOperation(schema, `#graphql
|
|
582
|
+
# note that the default conditional is inverted from the previous test
|
|
583
|
+
query DefaultedIfCondition($if: Boolean = false) {
|
|
584
|
+
skipped: hello @skip(if: $if)
|
|
585
|
+
included: hello @include(if: $if)
|
|
586
|
+
}
|
|
587
|
+
`);
|
|
588
|
+
|
|
589
|
+
expect(
|
|
590
|
+
computeResponse({
|
|
591
|
+
operation,
|
|
592
|
+
input,
|
|
593
|
+
variables: { if: true },
|
|
594
|
+
introspectionHandling,
|
|
595
|
+
}),
|
|
596
|
+
).toMatchInlineSnapshot(`
|
|
597
|
+
Object {
|
|
598
|
+
"data": Object {
|
|
599
|
+
"included": "world",
|
|
600
|
+
},
|
|
601
|
+
"errors": Array [],
|
|
602
|
+
}
|
|
603
|
+
`);
|
|
604
|
+
});
|
|
533
605
|
})
|