@@ -4,6 +4,8 @@ const gql = require('graphql-tag');
44const { ApolloClient, InMemoryCache, createHttpLink } = require ( '@apollo/client/core' ) ;
55const { ParseServer } = require ( '../' ) ;
66const { ParseGraphQLServer } = require ( '../lib/GraphQL/ParseGraphQLServer' ) ;
7+ const Parse = require ( 'parse/node' ) ;
8+ const fetch = ( ...args ) => import ( 'node-fetch' ) . then ( ( { default : fetch } ) => fetch ( ...args ) ) ;
79
810describe ( 'ParseGraphQL Query Complexity' , ( ) => {
911 let parseServer ;
@@ -29,7 +31,11 @@ describe('ParseGraphQL Query Complexity', () => {
2931
3032 const httpLink = createHttpLink ( {
3133 uri : 'http://localhost:13378/graphql' ,
32- fetch : ( ...args ) => import ( 'node-fetch' ) . then ( ( { default : fetch } ) => fetch ( ...args ) ) ,
34+ fetch,
35+ headers : {
36+ 'X-Parse-Application-Id' : 'test' ,
37+ 'X-Parse-Javascript-Key' : 'test' ,
38+ } ,
3339 } ) ;
3440
3541 apolloClient = new ApolloClient ( {
@@ -57,20 +63,6 @@ describe('ParseGraphQL Query Complexity', () => {
5763 } ,
5864 } ) ;
5965
60- const createUserMutation = gql `
61- mutation {
62- createUser(input: { fields: { username: "testuser", password: "password123" } }) {
63- user {
64- objectId
65- username
66- createdAt
67- }
68- }
69- }
70- ` ;
71-
72- await apolloClient . mutate ( { mutation : createUserMutation } ) ;
73-
7466 const query = gql `
7567 query {
7668 users {
@@ -86,7 +78,7 @@ describe('ParseGraphQL Query Complexity', () => {
8678 ` ;
8779
8880 const result = await apolloClient . query ( { query } ) ;
89- expect ( result . data . users . edges . length ) . toBeGreaterThan ( 0 ) ;
81+ expect ( result . data . users ) . toBeDefined ( ) ;
9082 } ) ;
9183
9284 it ( 'should reject queries exceeding fields limit' , async ( ) => {
@@ -115,7 +107,7 @@ describe('ParseGraphQL Query Complexity', () => {
115107 await apolloClient . query ( { query } ) ;
116108 fail ( 'Should have thrown an error' ) ;
117109 } catch ( error ) {
118- expect ( error . message ) . toContain ( 'Number of fields selected exceeds maximum allowed' ) ;
110+ expect ( error . networkError . result . errors [ 0 ] . message ) . toContain ( 'Number of fields selected exceeds maximum allowed' ) ;
119111 }
120112 } ) ;
121113
@@ -130,6 +122,7 @@ describe('ParseGraphQL Query Complexity', () => {
130122 uri : 'http://localhost:13378/graphql' ,
131123 fetch : ( ...args ) => import ( 'node-fetch' ) . then ( ( { default : fetch } ) => fetch ( ...args ) ) ,
132124 headers : {
125+ 'X-Parse-Application-Id' : 'test' ,
133126 'X-Parse-Master-Key' : 'test' ,
134127 } ,
135128 } ) ;
@@ -148,7 +141,7 @@ describe('ParseGraphQL Query Complexity', () => {
148141 username
149142 createdAt
150143 updatedAt
151- sessionToken
144+ email
152145 }
153146 }
154147 }
@@ -164,45 +157,25 @@ describe('ParseGraphQL Query Complexity', () => {
164157 it ( 'should allow queries within depth limit' , async ( ) => {
165158 await reconfigureServer ( {
166159 maxGraphQLQueryComplexity : {
167- depth : 3 ,
168- } ,
169- } ) ;
170-
171- // Create test data with relationships
172- const createClassMutation = gql `
173- mutation {
174- createClass(input: { name: "Post", schemaFields: { addStrings: [{ name: "title" }] } }) {
175- class {
176- name
177- }
178- }
179- }
180- ` ;
181-
182- await apolloClient . mutate ( {
183- mutation : createClassMutation ,
184- context : {
185- headers : {
186- 'X-Parse-Master-Key' : 'test' ,
187- } ,
160+ depth : 4 ,
188161 } ,
189162 } ) ;
190163
191164 const query = gql `
192165 query {
193- posts {
166+ users {
194167 edges {
195168 node {
196169 objectId
197- title
170+ username
198171 }
199172 }
200173 }
201174 }
202175 ` ;
203176
204177 const result = await apolloClient . query ( { query } ) ;
205- expect ( result . data . posts ) . toBeDefined ( ) ;
178+ expect ( result . data . users ) . toBeDefined ( ) ;
206179 } ) ;
207180
208181 it ( 'should reject queries exceeding depth limit' , async ( ) => {
@@ -229,7 +202,7 @@ describe('ParseGraphQL Query Complexity', () => {
229202 await apolloClient . query ( { query } ) ;
230203 fail ( 'Should have thrown an error' ) ;
231204 } catch ( error ) {
232- expect ( error . message ) . toContain ( 'Query depth exceeds maximum allowed depth' ) ;
205+ expect ( error . networkError . result . errors [ 0 ] . message ) . toContain ( 'Query depth exceeds maximum allowed depth' ) ;
233206 }
234207 } ) ;
235208
@@ -244,6 +217,7 @@ describe('ParseGraphQL Query Complexity', () => {
244217 uri : 'http://localhost:13378/graphql' ,
245218 fetch : ( ...args ) => import ( 'node-fetch' ) . then ( ( { default : fetch } ) => fetch ( ...args ) ) ,
246219 headers : {
220+ 'X-Parse-Application-Id' : 'test' ,
247221 'X-Parse-Master-Key' : 'test' ,
248222 } ,
249223 } ) ;
@@ -283,6 +257,7 @@ describe('ParseGraphQL Query Complexity', () => {
283257 uri : 'http://localhost:13378/graphql' ,
284258 fetch : ( ...args ) => import ( 'node-fetch' ) . then ( ( { default : fetch } ) => fetch ( ...args ) ) ,
285259 headers : {
260+ 'X-Parse-Application-Id' : 'test' ,
286261 'X-Parse-Maintenance-Key' : 'maintenanceKey123' ,
287262 } ,
288263 } ) ;
@@ -315,12 +290,12 @@ describe('ParseGraphQL Query Complexity', () => {
315290 it ( 'should count fields in fragments correctly' , async ( ) => {
316291 await reconfigureServer ( {
317292 maxGraphQLQueryComplexity : {
318- fields : 5 ,
293+ fields : 10 ,
319294 } ,
320295 } ) ;
321296
322297 const query = gql `
323- fragment UserFields on User {
298+ fragment UserFields1 on User {
324299 objectId
325300 username
326301 createdAt
@@ -330,7 +305,7 @@ describe('ParseGraphQL Query Complexity', () => {
330305 users {
331306 edges {
332307 node {
333- ...UserFields
308+ ...UserFields1
334309 }
335310 }
336311 }
@@ -349,7 +324,7 @@ describe('ParseGraphQL Query Complexity', () => {
349324 } ) ;
350325
351326 const query = gql `
352- fragment UserFields on User {
327+ fragment UserFields2 on User {
353328 objectId
354329 username
355330 createdAt
@@ -360,7 +335,7 @@ describe('ParseGraphQL Query Complexity', () => {
360335 users {
361336 edges {
362337 node {
363- ...UserFields
338+ ...UserFields2
364339 }
365340 }
366341 }
@@ -371,14 +346,14 @@ describe('ParseGraphQL Query Complexity', () => {
371346 await apolloClient . query ( { query } ) ;
372347 fail ( 'Should have thrown an error' ) ;
373348 } catch ( error ) {
374- expect ( error . message ) . toContain ( 'Number of fields selected exceeds maximum allowed' ) ;
349+ expect ( error . networkError . result . errors [ 0 ] . message ) . toContain ( 'Number of fields selected exceeds maximum allowed' ) ;
375350 }
376351 } ) ;
377352
378353 it ( 'should handle inline fragments correctly' , async ( ) => {
379354 await reconfigureServer ( {
380355 maxGraphQLQueryComplexity : {
381- fields : 5 ,
356+ fields : 10 ,
382357 } ,
383358 } ) ;
384359
@@ -402,41 +377,36 @@ describe('ParseGraphQL Query Complexity', () => {
402377 expect ( result . data . users ) . toBeDefined ( ) ;
403378 } ) ;
404379
405- it ( 'should handle cyclic fragment references (GraphQL validation prevents actual cycles) ' , async ( ) => {
380+ it ( 'should reject inline fragments exceeding fields limit ' , async ( ) => {
406381 await reconfigureServer ( {
407382 maxGraphQLQueryComplexity : {
408- fields : 10 ,
383+ fields : 3 ,
409384 } ,
410385 } ) ;
411386
412- // Note: GraphQL's NoFragmentCycles validation rule prevents actual cycles
413- // This test verifies that our complexity calculation doesn't break when
414- // fragments reference each other (as long as there's no actual cycle)
415387 const query = gql `
416- fragment UserBasicInfo on User {
417- objectId
418- username
419- }
420-
421- fragment UserDetailedInfo on User {
422- ...UserBasicInfo
423- createdAt
424- updatedAt
425- }
426-
427388 query {
428389 users {
429390 edges {
430391 node {
431- ...UserDetailedInfo
392+ ... on User {
393+ objectId
394+ username
395+ createdAt
396+ updatedAt
397+ }
432398 }
433399 }
434400 }
435401 }
436402 ` ;
437403
438- const result = await apolloClient . query ( { query } ) ;
439- expect ( result . data . users ) . toBeDefined ( ) ;
404+ try {
405+ await apolloClient . query ( { query } ) ;
406+ fail ( 'Should have thrown an error' ) ;
407+ } catch ( error ) {
408+ expect ( error . networkError . result . errors [ 0 ] . message ) . toContain ( 'Number of fields selected exceeds maximum allowed' ) ;
409+ }
440410 } ) ;
441411
442412 it ( 'should reject actual cyclic fragment definitions with GraphQL validation error' , async ( ) => {
@@ -446,8 +416,6 @@ describe('ParseGraphQL Query Complexity', () => {
446416 } ,
447417 } ) ;
448418
449- // This will fail at GraphQL parsing/validation level before our complexity check
450- // because GraphQL has built-in NoFragmentCycles rule
451419 const queryString = `
452420 fragment FragmentA on User {
453421 objectId
@@ -471,13 +439,11 @@ describe('ParseGraphQL Query Complexity', () => {
471439 ` ;
472440
473441 try {
474- // Try to parse the query with cyclic fragments
475442 const query = gql ( queryString ) ;
476443 await apolloClient . query ( { query } ) ;
477444 fail ( 'Should have thrown an error due to cyclic fragments' ) ;
478445 } catch ( error ) {
479- // GraphQL validation should catch this before complexity calculation
480- expect ( error . message ) . toMatch ( / c y c l e | C a n n o t s p r e a d f r a g m e n t / i) ;
446+ expect ( error . networkError ?. result ?. errors ?. [ 0 ] ?. message ) . toEqual ( 'Cannot spread fragment "FragmentA" within itself via "FragmentB".' ) ;
481447 }
482448 } ) ;
483449 } ) ;
@@ -486,8 +452,8 @@ describe('ParseGraphQL Query Complexity', () => {
486452 it ( 'should validate both depth and fields limits' , async ( ) => {
487453 await reconfigureServer ( {
488454 maxGraphQLQueryComplexity : {
489- depth : 3 ,
490- fields : 5 ,
455+ depth : 4 ,
456+ fields : 10 ,
491457 } ,
492458 } ) ;
493459
@@ -534,7 +500,7 @@ describe('ParseGraphQL Query Complexity', () => {
534500 await apolloClient . query ( { query } ) ;
535501 fail ( 'Should have thrown an error' ) ;
536502 } catch ( error ) {
537- expect ( error . message ) . toContain ( 'Number of fields selected exceeds maximum allowed' ) ;
503+ expect ( error . networkError . result . errors [ 0 ] . message ) . toContain ( 'Number of fields selected exceeds maximum allowed' ) ;
538504 }
539505 } ) ;
540506 } ) ;
@@ -552,9 +518,7 @@ describe('ParseGraphQL Query Complexity', () => {
552518 username
553519 createdAt
554520 updatedAt
555- sessionToken
556- authData
557- ACL
521+ email
558522 }
559523 }
560524 }
0 commit comments