1
- import { existsSync , readdirSync , readFileSync } from 'fs' ;
1
+ import { readdirSync , readFileSync } from 'fs' ;
2
2
import { join } from 'path' ;
3
- import { ApolloGateway } from '@apollo/gateway' ;
4
3
import { normalizedExecutor } from '@graphql-tools/executor' ;
5
4
import {
6
5
ExecutionResult ,
9
8
MapperKind ,
10
9
mapSchema ,
11
10
} from '@graphql-tools/utils' ;
11
+ import { assertSingleExecutionValue } from '@internal/testing' ;
12
12
import {
13
13
buildSchema ,
14
14
getNamedType ,
@@ -19,86 +19,76 @@ import {
19
19
printSchema ,
20
20
validate ,
21
21
} from 'graphql' ;
22
- import { afterAll , beforeAll , describe , expect , it } from 'vitest' ;
22
+ import { createRouter } from 'graphql-federation-gateway-audit' ;
23
+ import { beforeAll , describe , expect , it } from 'vitest' ;
23
24
import { getStitchedSchemaFromSupergraphSdl } from '../src/supergraph' ;
24
25
25
26
describe ( 'Federation Compatibility' , ( ) => {
26
- if ( ! existsSync ( join ( __dirname , 'fixtures' , 'federation-compatibility' ) ) ) {
27
- console . warn ( 'Make sure you fetched the fixtures from the API first' ) ;
28
- it . skip ( 'skipping tests' , ( ) => { } ) ;
29
- return ;
30
- }
31
- const fixturesDir = join ( __dirname , 'fixtures' , 'federation-compatibility' ) ;
32
- readdirSync ( fixturesDir ) . forEach ( ( supergraphName ) => {
33
- const supergraphFixturesDir = join ( fixturesDir , supergraphName ) ;
34
- const supergraphSdlPath = join ( supergraphFixturesDir , 'supergraph.graphql' ) ;
35
- if ( ! existsSync ( supergraphSdlPath ) ) {
36
- return ;
27
+ const auditRouter = createRouter ( ) ;
28
+ const supergraphList = readdirSync (
29
+ join (
30
+ __dirname ,
31
+ '../../../node_modules/graphql-federation-gateway-audit/src/test-suites' ,
32
+ ) ,
33
+ ) ;
34
+ const supergraphSdlMap = new Map < string , string > ( ) ;
35
+ const supergraphTestMap = new Map < string , any > ( ) ;
36
+ beforeAll ( async ( ) => {
37
+ const supergraphPathListRes = await auditRouter . fetch (
38
+ 'http://localhost/supergraphs' ,
39
+ ) ;
40
+ if ( ! supergraphPathListRes . ok ) {
41
+ const error = await supergraphPathListRes . text ( ) ;
42
+ throw new Error ( `Failed to fetch supergraph list: ${ error } ` ) ;
43
+ }
44
+ const supergraphPathList = await supergraphPathListRes . json ( ) ;
45
+ for ( const supergraphPath of supergraphPathList ) {
46
+ if ( supergraphPath ) {
47
+ const supergraphRes = await auditRouter . fetch ( supergraphPath ) ;
48
+ const supergraphPathParts = supergraphPath . split ( '/' ) ;
49
+ const supergraphName =
50
+ supergraphPathParts [ supergraphPathParts . length - 2 ] ;
51
+ const supergraphSdl = await supergraphRes . text ( ) ;
52
+ supergraphSdlMap . set ( supergraphName , supergraphSdl ) ;
53
+ const testsPath = supergraphPath . replace ( '/supergraph' , '/tests' ) ;
54
+ const testsRes = await auditRouter . fetch ( testsPath ) ;
55
+ const testsContent = await testsRes . json ( ) ;
56
+ supergraphTestMap . set ( supergraphName , testsContent ) ;
57
+ }
37
58
}
59
+ } ) ;
60
+
61
+ for ( const supergraphName of supergraphList ) {
38
62
describe ( supergraphName , ( ) => {
39
- const supergraphSdl = readFileSync ( supergraphSdlPath , 'utf-8' ) ;
40
63
let stitchedSchema : GraphQLSchema ;
41
- // let apolloExecutor: Executor;
42
- // let apolloSubgraphCalls: Record<string, number> = {};
43
- let stitchingSubgraphCalls : Record < string , number > = { } ;
44
- let apolloGW : ApolloGateway ;
45
- beforeAll ( async ( ) => {
64
+ let supergraphSdl : string ;
65
+ const testFile = readFileSync (
66
+ join (
67
+ __dirname ,
68
+ '../../../node_modules/graphql-federation-gateway-audit/src/test-suites' ,
69
+ supergraphName ,
70
+ 'test.ts' ,
71
+ ) ,
72
+ 'utf-8' ,
73
+ ) ;
74
+ let tests : { query : string ; expected : any } [ ] = new Array < {
75
+ query : string ;
76
+ expected : any ;
77
+ } > ( testFile . match ( / c r e a t e T e s t \( / g) ?. length ?? 0 ) . fill ( {
78
+ query : '' ,
79
+ expected : { } ,
80
+ } ) ;
81
+ beforeAll ( ( ) => {
82
+ supergraphSdl = supergraphSdlMap . get ( supergraphName ) ! ;
83
+ tests = supergraphTestMap . get ( supergraphName ) ! ;
46
84
stitchedSchema = getStitchedSchemaFromSupergraphSdl ( {
47
85
supergraphSdl,
48
- onSubschemaConfig ( subschemaConfig ) {
49
- const actualExecutor = subschemaConfig . executor ;
50
- subschemaConfig . executor = function tracedExecutor ( execReq ) {
51
- stitchingSubgraphCalls [ subschemaConfig . name . toLowerCase ( ) ] =
52
- ( stitchingSubgraphCalls [ subschemaConfig . name ] || 0 ) + 1 ;
53
- return actualExecutor ( execReq ) ;
54
- } ;
86
+ httpExecutorOpts : {
87
+ fetch : auditRouter . fetch ,
55
88
} ,
56
89
batch : true ,
57
90
} ) ;
58
- /* apolloGW = new ApolloGateway({
59
- supergraphSdl,
60
- buildService({ name, url }) {
61
- const subgraphName = name;
62
- const actualService = new RemoteGraphQLDataSource({ url });
63
- return {
64
- process(options) {
65
- apolloSubgraphCalls[subgraphName.toLowerCase()] =
66
- (apolloSubgraphCalls[subgraphName.toLowerCase()] || 0) + 1;
67
- return actualService.process(options);
68
- },
69
- };
70
- },
71
- });
72
- const loadedGw = await apolloGW.load();
73
- apolloExecutor = function apolloExecutor(execReq) {
74
- const operationAST = getOperationAST(execReq.document, execReq.operationName);
75
- if (!operationAST) {
76
- throw new Error('Operation not found');
77
- }
78
- const printedDoc = print(execReq.document);
79
- return loadedGw.executor({
80
- request: {},
81
- logger: console,
82
- schema: loadedGw.schema,
83
- schemaHash: 'hash' as any,
84
- context: execReq.context as any,
85
- cache: new Map() as any,
86
- queryHash: 'hash' as any,
87
- document: execReq.document,
88
- source: printedDoc,
89
- operationName: execReq.operationName || null,
90
- operation: operationAST,
91
- metrics: {},
92
- overallCachePolicy: {},
93
- }) as ExecutionResult;
94
- }; */
95
- } ) ;
96
- afterAll ( async ( ) => {
97
- await apolloGW ?. stop ?.( ) ;
98
91
} ) ;
99
- const tests : { query : string ; expected : any } [ ] = JSON . parse (
100
- readFileSync ( join ( supergraphFixturesDir , 'tests.json' ) , 'utf-8' ) ,
101
- ) ;
102
92
it ( 'generates the expected schema' , ( ) => {
103
93
const inputSchema = buildSchema ( supergraphSdl , {
104
94
noLocation : true ,
@@ -153,26 +143,28 @@ describe('Federation Compatibility', () => {
153
143
printSchema ( sortedInputSchema ) . trim ( ) ,
154
144
) ;
155
145
} ) ;
156
- tests . forEach ( ( test , i ) => {
146
+ tests . forEach ( ( _ , i ) => {
157
147
describe ( `test-query-${ i } ` , ( ) => {
158
- let result : ExecutionResult ;
159
- beforeAll ( async ( ) => {
160
- // apolloSubgraphCalls = {};
161
- stitchingSubgraphCalls = { } ;
148
+ it ( 'gives the correct result' , async ( ) => {
149
+ const test = tests [ i ] ;
150
+ if ( ! test ) {
151
+ throw new Error ( `Test ${ i } not found` ) ;
152
+ }
162
153
const document = parse ( test . query , { noLocation : true } ) ;
163
154
const validationErrors = validate ( stitchedSchema , document ) ;
155
+ let result : ExecutionResult ;
164
156
if ( validationErrors . length > 0 ) {
165
157
result = {
166
158
errors : validationErrors ,
167
159
} ;
168
160
} else {
169
- result = ( await normalizedExecutor ( {
161
+ const execRes = await normalizedExecutor ( {
170
162
schema : stitchedSchema ,
171
163
document,
172
- } ) ) as ExecutionResult ;
164
+ } ) ;
165
+ assertSingleExecutionValue ( execRes ) ;
166
+ result = execRes ;
173
167
}
174
- } ) ;
175
- it ( 'gives the correct result' , ( ) => {
176
168
const received = {
177
169
data : result . data ?? null ,
178
170
errors : ! ! result . errors ?. length ,
@@ -195,5 +187,5 @@ describe('Federation Compatibility', () => {
195
187
} ) ;
196
188
} ) ;
197
189
} ) ;
198
- } ) ;
190
+ }
199
191
} ) ;
0 commit comments