From 2651a6eff85aee8debabdc079208df079e4e7404 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Tue, 5 Jul 2022 20:52:35 -0400 Subject: [PATCH 01/18] added object resolution to fragment tests --- test/analysis/typeComplexityAnalysis.test.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 78894d0..9489f95 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -101,6 +101,7 @@ import { TypeWeightObject, Variables } from '../../src/@types/buildTypeWeights'; const mockWeightFunction = jest.fn(); const mockHumanFriendsFunction = jest.fn(); const mockDroidFriendsFunction = jest.fn(); +const mockCharacterFriendsFunction = jest.fn(); const nonNullMockWeightFunction = jest.fn(); // this object is created by the schema above for use in all the tests below @@ -130,7 +131,7 @@ const typeWeights: TypeWeightObject = { fields: { id: 0, name: 0, - // FIXME: add the function definition for the 'friends' field which returns a list + friends: mockCharacterFriendsFunction, }, }, human: { @@ -248,9 +249,14 @@ describe('Test getQueryTypeComplexity function', () => { fragment comparisonFields on Character { name appearsIn + friends(first: 3) { + name + } } }`; - expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); // Query 1 + 2*(character 1 + appearsIn/episode 1) + mockCharacterFriendsFunction.mockReturnValue(3); + // Query 1 + 2*(character 1 + appearsIn/episode 1 + 3 * friends/character 1) + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(11); }); xtest('with inline fragments', () => { @@ -260,13 +266,18 @@ describe('Test getQueryTypeComplexity function', () => { name ... on Droid { primaryFunction + friends(first: 3) { + name + } } ... on Human { homeplanet } } }`; - expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(2); // Query 1 + hero/character 1) + mockDroidFriendsFunction.mockReturnValueOnce(3); + // Query 1 + hero/character 1 + 3 * friends/character 1) + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); }); /** From 0f0c8dd524dddc49b3f7f1ede1ae9075318617a0 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sat, 9 Jul 2022 16:25:45 -0400 Subject: [PATCH 02/18] corrected fragment text with object --- test/analysis/typeComplexityAnalysis.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 9489f95..f8a284a 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -235,7 +235,9 @@ describe('Test getQueryTypeComplexity function', () => { expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(2); // Query 1 + hero/character 1 }); - xtest('with fragments', () => { + // TODO: Test fragment with variable + // TODO: Test fragment with object + test('with fragments', () => { query = ` query { leftComparison: hero(episode: EMPIRE) { @@ -255,8 +257,8 @@ describe('Test getQueryTypeComplexity function', () => { } }`; mockCharacterFriendsFunction.mockReturnValue(3); - // Query 1 + 2*(character 1 + appearsIn/episode 1 + 3 * friends/character 1) - expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(11); + // Query 1 + 2*(character 1 + appearsIn/episode 0 + 3 * friends/character 1) + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(9); }); xtest('with inline fragments', () => { From 8bda4974e23e344158c7e4167111bc1f83c05a93 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sat, 9 Jul 2022 17:00:45 -0400 Subject: [PATCH 03/18] add fragment tests for fragements with variables/nesting and fragments with complexity 0 --- test/analysis/typeComplexityAnalysis.test.ts | 83 +++++++++++++++----- 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 4fff35a..70d7343 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -276,30 +276,73 @@ describe('Test getQueryTypeComplexity function', () => { expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(2); // Query 1 + hero/character 1 }); - // TODO: Test fragment with variable - // TODO: Test fragment with object - test('with fragments', () => { - query = ` - query { - leftComparison: hero(episode: EMPIRE) { - ...comparisonFields + xdescribe('with fragments', () => { + test('that have a complexity of zero', () => { + query = ` + query { + leftComparison: hero(episode: EMPIRE) { + ...comparisonFields + } + rightComparison: hero(episode: JEDI) { + ...comparisonFields + } } - rightComparison: hero(episode: JEDI) { - ...comparisonFields + + fragment comparisonFields on Character { + name + appearsIn + }`; + // Query 1 + 2*(appearsIn/episode 0 + name/string 0) + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(3); + }); + + test('that contain an object and a non-zero complexity', () => { + query = ` + query { + leftComparison: hero(episode: EMPIRE) { + ...comparisonFields + } + rightComparison: hero(episode: JEDI) { + ...comparisonFields + } } - } - - fragment comparisonFields on Character { - name - appearsIn - friends(first: 3) { + + fragment comparisonFields on Character { name + appearsIn + friends(first: 3) { + name + } + }`; + mockCharacterFriendsFunction.mockReturnValue(3); + variables = { first: 3 }; + // Query 1 + 2*(character 1 + appearsIn/episode 0 + 3 * friends/character 1) + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(9); + }); + + test('that use a variable', () => { + query = ` + query { + leftComparison: hero(episode: EMPIRE) { + ...comparisonFields + } + rightComparison: hero(episode: JEDI) { + ...comparisonFields + } } - } - }`; - mockCharacterFriendsFunction.mockReturnValue(3); - // Query 1 + 2*(character 1 + appearsIn/episode 0 + 3 * friends/character 1) - expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(9); + + fragment comparisonFields on Character { + name + appearsIn + friends(first: $first) { + name + } + }`; + mockCharacterFriendsFunction.mockReturnValue(3); + variables = { first: 3 }; + // Query 1 + 2*(character 1 + appearsIn/episode 0 + 3 * friends/character 1) + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(9); + }); }); xtest('with inline fragments', () => { From c4f47995027ba5b0b42d74816104c1657ff938d0 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sat, 9 Jul 2022 21:45:41 -0400 Subject: [PATCH 04/18] additional tests for inline fragments on unions and interfaces --- test/analysis/typeComplexityAnalysis.test.ts | 194 +++++++++++++++++-- 1 file changed, 174 insertions(+), 20 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 70d7343..f5e007f 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -7,6 +7,7 @@ import { TypeWeightObject, Variables } from '../../src/@types/buildTypeWeights'; * type Query { hero(episode: Episode): Character + heroUnion(episode: Episode): SearchResult reviews(episode: Episode!, first: Int): [Review] search(text: String): [SearchResult] character(id: ID!): Character @@ -117,6 +118,9 @@ const typeWeights: TypeWeightObject = { hero: { resolveTo: 'character', }, + heroUnion: { + resolveTo: 'SearchResult', + }, search: { resolveTo: 'searchresult', weight: jest.fn(), // FIXME: Unbounded list result @@ -345,25 +349,175 @@ describe('Test getQueryTypeComplexity function', () => { }); }); - xtest('with inline fragments', () => { - query = ` - query { - hero(episode: EMPIRE) { - name - ... on Droid { - primaryFunction - friends(first: 3) { - name - } - } - ... on Human { - homeplanet - } - } - }`; - mockDroidFriendsFunction.mockReturnValueOnce(3); - // Query 1 + hero/character 1 + 3 * friends/character 1) - expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + xdescribe('with inline fragments', () => { + // FIXME: Does SearchResult resolve to Character since Human and + // Droid implement Character? What do we see during type weight parsing + // FIXME: Are unions of Objects and (Scalars or Scalars and Scalars possible) + describe('on union types', () => { + test('that have a complexity of zero', () => { + query = ` + query { + heroUnion(episode: EMPIRE) { + name + ... on Droid { + primaryFunction + } + ... on Human { + homePlanet + } + } + }`; + // Query 1 + 1 hero + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(2); + }); + + test('that have differing complexities', () => { + query = ` + query { + heroUnion(episode: EMPIRE) { + name + ... on Droid { + primaryFunction + } + ... on Human { + homePlanet + friends(first: 3) { + name + } + } + } + }`; + // Query 1 + 1 hero + max(Droid 0, Human 3) = 5 + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + }); + + test('that contain an object and a non-zero complexity', () => { + query = ` + query { + heroUnion(episode: EMPIRE) { + name + friends(first: 3) { + name + } + ... on Droid { + primaryFunction + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValue(3); + variables = { first: 3 }; + // Query 1 + 1 hero + 3 friends/character + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + }); + + test('that use a variable', () => { + query = ` + query { + heroUnion(episode: EMPIRE) { + name + ... on Droid { + primaryFunction + friends(first: $first) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValue(3); + variables = { first: 3 }; + // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + }); + }); + + describe('on interface types', () => { + test('that have a complexity of zero', () => { + query = ` + query { + hero(episode: EMPIRE) { + name + ... on Droid { + primaryFunction + } + ... on Human { + homePlanet + } + } + }`; + // Query 1 + 1 hero + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(2); + }); + + test('that have differing complexities', () => { + query = ` + query { + hero(episode: EMPIRE) { + name + ... on Droid { + primaryFunction + } + ... on Human { + homePlanet + friends(first: 3) { + name + } + } + } + }`; + // Query 1 + 1 hero + max(Droid 0, Human 3) = 5 + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + }); + + test('that contain an object and a non-zero complexity', () => { + query = ` + query { + hero(episode: EMPIRE) { + name + friends(first: 3) { + name + } + ... on Droid { + primaryFunction + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValue(3); + variables = { first: 3 }; + // Query 1 + 1 hero + 3 friends/character + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + }); + + test('that use a variable', () => { + query = ` + query { + hero(episode: EMPIRE) { + name + ... on Droid { + primaryFunction + friends(first: $first) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValue(3); + variables = { first: 3 }; + // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + }); + }); }); /** @@ -438,7 +592,7 @@ describe('Test getQueryTypeComplexity function', () => { expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); // 1 Query + 4 search results }); - // todo: directives @skip, @include and custom directives + // TODO: directives @skip, @include and custom directives }); xdescribe('Calculates the correct type complexity for mutations', () => {}); From efd16abdd88fca2e593368a8dd2c4b3dda6b6e2d Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sat, 9 Jul 2022 22:21:00 -0400 Subject: [PATCH 05/18] updated weight function mocks for inline fragment tests --- test/analysis/typeComplexityAnalysis.test.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index f5e007f..589382b 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -157,7 +157,7 @@ const typeWeights: TypeWeightObject = { appearsIn: { resolveTo: 'episode' }, friends: { resolveTo: 'character', - weight: mockHumanFriendsFunction, + weight: mockCharacterFriendsFunction, }, scalarList: { weight: 0, @@ -349,10 +349,7 @@ describe('Test getQueryTypeComplexity function', () => { }); }); - xdescribe('with inline fragments', () => { - // FIXME: Does SearchResult resolve to Character since Human and - // Droid implement Character? What do we see during type weight parsing - // FIXME: Are unions of Objects and (Scalars or Scalars and Scalars possible) + describe('with inline fragments', () => { describe('on union types', () => { test('that have a complexity of zero', () => { query = ` @@ -388,6 +385,7 @@ describe('Test getQueryTypeComplexity function', () => { } }`; // Query 1 + 1 hero + max(Droid 0, Human 3) = 5 + mockHumanFriendsFunction.mockReturnValueOnce(3); expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); }); @@ -429,7 +427,7 @@ describe('Test getQueryTypeComplexity function', () => { } } }`; - mockCharacterFriendsFunction.mockReturnValue(3); + mockDroidFriendsFunction.mockReturnValueOnce(3); variables = { first: 3 }; // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); @@ -471,6 +469,7 @@ describe('Test getQueryTypeComplexity function', () => { } }`; // Query 1 + 1 hero + max(Droid 0, Human 3) = 5 + mockHumanFriendsFunction.mockReturnValueOnce(3); expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); }); @@ -491,8 +490,8 @@ describe('Test getQueryTypeComplexity function', () => { } }`; mockCharacterFriendsFunction.mockReturnValue(3); - variables = { first: 3 }; // Query 1 + 1 hero + 3 friends/character + mockHumanFriendsFunction.mockReturnValueOnce(3); expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); }); @@ -512,7 +511,7 @@ describe('Test getQueryTypeComplexity function', () => { } } }`; - mockCharacterFriendsFunction.mockReturnValue(3); + mockDroidFriendsFunction.mockReturnValue(3); variables = { first: 3 }; // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); From d6a96b7e944e5d1f56fc0673ff8e5742598a0974 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sat, 9 Jul 2022 22:23:38 -0400 Subject: [PATCH 06/18] disabled inline fragment tests --- test/analysis/typeComplexityAnalysis.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 589382b..7d03814 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -349,7 +349,7 @@ describe('Test getQueryTypeComplexity function', () => { }); }); - describe('with inline fragments', () => { + xdescribe('with inline fragments', () => { describe('on union types', () => { test('that have a complexity of zero', () => { query = ` From 5b4148dcae27962000ff29a154f32c64e86fd54c Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sat, 9 Jul 2022 22:48:43 -0400 Subject: [PATCH 07/18] corrected function mock used for character frieds and updated nested list tests accordingly --- test/analysis/typeComplexityAnalysis.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 7d03814..b532633 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -559,9 +559,11 @@ describe('Test getQueryTypeComplexity function', () => { describe('with nested lists', () => { test('and simple nesting', () => { query = `query { human(id: 1) { name, friends(first: 5) { name, friends(first: 3){ name }}}} `; - mockHumanFriendsFunction.mockReturnValueOnce(3).mockReturnValueOnce(20); + mockCharacterFriendsFunction.mockReturnValueOnce(3); + mockHumanFriendsFunction.mockReturnValueOnce(20); expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(22); // 1 Query + 1 human/character + (5 friends/character X (1 friend + 3 friends/characters)) - expect(mockHumanFriendsFunction.mock.calls.length).toBe(2); + expect(mockCharacterFriendsFunction.mock.calls.length).toBe(1); + expect(mockHumanFriendsFunction.mock.calls.length).toBe(1); }); test('and inner scalar lists', () => { From aa9788ab5ac99ac59adfe068d6fae4330d59a756 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sun, 10 Jul 2022 12:26:01 -0400 Subject: [PATCH 08/18] corrected heroUnion in typeWeight object in complexity tests --- test/analysis/typeComplexityAnalysis.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index b532633..6afde41 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -119,7 +119,7 @@ const typeWeights: TypeWeightObject = { resolveTo: 'character', }, heroUnion: { - resolveTo: 'SearchResult', + resolveTo: 'searchresult', }, search: { resolveTo: 'searchresult', From ecb8f762c82394d0207c2dd18b980ecdc562b28f Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sun, 10 Jul 2022 14:30:58 -0400 Subject: [PATCH 09/18] cleaned up function mocks in typeWeight test suite --- test/analysis/typeComplexityAnalysis.test.ts | 248 ++++++++++--------- 1 file changed, 130 insertions(+), 118 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 6afde41..0d25f45 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -99,133 +99,145 @@ import { TypeWeightObject, Variables } from '../../src/@types/buildTypeWeights'; to character, human and droid */ -const mockWeightFunction = jest.fn(); -const mockHumanFriendsFunction = jest.fn(); -const mockDroidFriendsFunction = jest.fn(); -const mockCharacterFriendsFunction = jest.fn(); -const nonNullMockWeightFunction = jest.fn(); +// Mocks typed with +let mockWeightFunction: jest.Mock; +let mockHumanFriendsFunction: jest.Mock; +let mockDroidFriendsFunction: jest.Mock; +let mockCharacterFriendsFunction: jest.Mock; +let nonNullMockWeightFunction: jest.Mock; // this object is created by the schema above for use in all the tests below -const typeWeights: TypeWeightObject = { - query: { - // object type - weight: 1, - fields: { - reviews: { - resolveTo: 'review', - weight: mockWeightFunction, - }, - hero: { - resolveTo: 'character', - }, - heroUnion: { - resolveTo: 'searchresult', +let typeWeights: TypeWeightObject; + +describe('Test getQueryTypeComplexity function', () => { + beforeEach(() => { + // Reset mocks before each test to avoid errors when running tests in parallel + mockWeightFunction = jest.fn(); + mockHumanFriendsFunction = jest.fn(); + mockDroidFriendsFunction = jest.fn(); + mockCharacterFriendsFunction = jest.fn(); + nonNullMockWeightFunction = jest.fn(); + + typeWeights = { + query: { + // object type + weight: 1, + fields: { + reviews: { + resolveTo: 'review', + weight: mockWeightFunction, + }, + hero: { + resolveTo: 'character', + }, + heroUnion: { + resolveTo: 'searchresult', + }, + search: { + resolveTo: 'searchresult', + weight: jest.fn(), // FIXME: Unbounded list result + }, + character: { + resolveTo: 'character', + }, + droid: { + resolveTo: 'droid', + }, + human: { + resolveTo: 'human', + }, + scalars: { + resolveTo: 'scalars', + }, + nonNull: { + resolveTo: 'droid', + weight: nonNullMockWeightFunction, + }, + }, }, - search: { - resolveTo: 'searchresult', - weight: jest.fn(), // FIXME: Unbounded list result + episode: { + // enum + weight: 0, + fields: {}, }, character: { - resolveTo: 'character', - }, - droid: { - resolveTo: 'droid', + // interface + weight: 1, + fields: { + id: { weight: 0 }, + name: { weight: 0 }, + appearsIn: { resolveTo: 'episode' }, + friends: { + resolveTo: 'character', + weight: mockCharacterFriendsFunction, + }, + scalarList: { + weight: 0, + }, + }, }, human: { - resolveTo: 'human', - }, - scalars: { - resolveTo: 'scalars', + // implements an interface + weight: 1, + fields: { + id: { weight: 0 }, + name: { weight: 0 }, + appearsIn: { resolveTo: 'episode' }, + homePlanet: { weight: 0 }, + friends: { + resolveTo: 'character', + weight: mockHumanFriendsFunction, + }, + }, }, - nonNull: { - resolveTo: 'droid', - weight: nonNullMockWeightFunction, + droid: { + // implements an interface + weight: 1, + fields: { + id: { weight: 0 }, + name: { weight: 0 }, + appearsIn: { resolveTo: 'episode' }, + primaryFunction: { weight: 0 }, + friends: { + resolveTo: 'character', + weight: mockDroidFriendsFunction, + }, + }, }, - }, - }, - episode: { - // enum - weight: 0, - fields: {}, - }, - character: { - // interface - weight: 1, - fields: { - id: { weight: 0 }, - name: { weight: 0 }, - appearsIn: { resolveTo: 'episode' }, - friends: { - resolveTo: 'character', - weight: mockCharacterFriendsFunction, + review: { + weight: 1, + fields: { + episode: { resolveTo: 'episode' }, + stars: { weight: 0 }, + commentary: { weight: 0 }, + }, }, - scalarList: { - weight: 0, + searchresult: { + // union type + weight: 1, + fields: {}, }, - }, - }, - human: { - // implements an interface - weight: 1, - fields: { - id: { weight: 0 }, - name: { weight: 0 }, - appearsIn: { resolveTo: 'episode' }, - homePlanet: { weight: 0 }, - friends: { - resolveTo: 'character', - weight: mockHumanFriendsFunction, + scalars: { + weight: 1, // object weight is 1, all scalar feilds have weight 0 + fields: { + num: { weight: 0 }, + id: { weight: 0 }, + float: { weight: 0 }, + bool: { weight: 0 }, + string: { weight: 0 }, + test: { resolveTo: 'test' }, + }, }, - }, - }, - droid: { - // implements an interface - weight: 1, - fields: { - id: { weight: 0 }, - name: { weight: 0 }, - appearsIn: { resolveTo: 'episode' }, - primaryFunction: { weight: 0 }, - friends: { - resolveTo: 'character', - weight: mockDroidFriendsFunction, + test: { + weight: 1, + fields: { + name: { weight: 0 }, + scalars: { resolveTo: 'scalars' }, + }, }, - }, - }, - review: { - weight: 1, - fields: { - episode: { resolveTo: 'episode' }, - stars: { weight: 0 }, - commentary: { weight: 0 }, - }, - }, - searchresult: { - // union type - weight: 1, - fields: {}, - }, - scalars: { - weight: 1, // object weight is 1, all scalar feilds have weight 0 - fields: { - num: { weight: 0 }, - id: { weight: 0 }, - float: { weight: 0 }, - bool: { weight: 0 }, - string: { weight: 0 }, - test: { resolveTo: 'test' }, - }, - }, - test: { - weight: 1, - fields: { - name: { weight: 0 }, - scalars: { resolveTo: 'scalars' }, - }, - }, -}; + }; + }); -describe('Test getQueryTypeComplexity function', () => { afterEach(() => { jest.clearAllMocks(); }); @@ -318,7 +330,7 @@ describe('Test getQueryTypeComplexity function', () => { name } }`; - mockCharacterFriendsFunction.mockReturnValue(3); + mockCharacterFriendsFunction.mockReturnValueOnce(3); variables = { first: 3 }; // Query 1 + 2*(character 1 + appearsIn/episode 0 + 3 * friends/character 1) expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(9); @@ -342,7 +354,7 @@ describe('Test getQueryTypeComplexity function', () => { name } }`; - mockCharacterFriendsFunction.mockReturnValue(3); + mockCharacterFriendsFunction.mockReturnValueOnce(3); variables = { first: 3 }; // Query 1 + 2*(character 1 + appearsIn/episode 0 + 3 * friends/character 1) expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(9); @@ -405,7 +417,7 @@ describe('Test getQueryTypeComplexity function', () => { } } }`; - mockCharacterFriendsFunction.mockReturnValue(3); + mockCharacterFriendsFunction.mockReturnValueOnce(3); variables = { first: 3 }; // Query 1 + 1 hero + 3 friends/character expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); @@ -489,7 +501,7 @@ describe('Test getQueryTypeComplexity function', () => { } } }`; - mockCharacterFriendsFunction.mockReturnValue(3); + mockCharacterFriendsFunction.mockReturnValueOnce(3); // Query 1 + 1 hero + 3 friends/character mockHumanFriendsFunction.mockReturnValueOnce(3); expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); @@ -511,7 +523,7 @@ describe('Test getQueryTypeComplexity function', () => { } } }`; - mockDroidFriendsFunction.mockReturnValue(3); + mockDroidFriendsFunction.mockReturnValueOnce(3); variables = { first: 3 }; // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); From 5169bb22a509cf624920bb8f6971041ac3bbd709 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sun, 10 Jul 2022 15:07:10 -0400 Subject: [PATCH 10/18] added test to ensure fragment complexity isn't cached between queries --- test/analysis/typeComplexityAnalysis.test.ts | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 0d25f45..8cc75ff 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -359,6 +359,50 @@ describe('Test getQueryTypeComplexity function', () => { // Query 1 + 2*(character 1 + appearsIn/episode 0 + 3 * friends/character 1) expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(9); }); + + test('recalculates fragment complexity for individual queries', () => { + query = ` + query { + leftComparison: hero(episode: EMPIRE) { + ...comparisonFields + } + rightComparison: hero(episode: JEDI) { + ...comparisonFields + } + } + + fragment comparisonFields on Character { + name + appearsIn + friends(first: 3) { + name + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + + variables = { first: 3 }; + // Query 1 + 2*(character 1 + appearsIn/episode 0 + 3 * friends/character 1) + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(9); + + query = ` + query { + leftComparison: hero(episode: EMPIRE) { + ...comparisonFields + } + rightComparison: hero(episode: JEDI) { + ...comparisonFields + } + } + + fragment comparisonFields on Character { + name + appearsIn + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + variables = { first: 3 }; + // Query 1 + 2*(character 1 + 0 selectionCost) + expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(3); + }); }); xdescribe('with inline fragments', () => { From ca6a114dde775a937fac5a23a15cc7cb08e2d566 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sun, 10 Jul 2022 16:42:44 -0400 Subject: [PATCH 11/18] expanded fragment tests to include cases for fragments without a type condition, directives and multiple applicable fragments. created separate typeWeight object for union tests on fragments for clarity --- test/analysis/typeComplexityAnalysis.test.ts | 195 ++++++++++++++++++- 1 file changed, 191 insertions(+), 4 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 8cc75ff..ff33632 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -36,6 +36,7 @@ import { TypeWeightObject, Variables } from '../../src/@types/buildTypeWeights'; name: String! homePlanet: String friends(first: Int): [Character] + humanFriends(first: Int): [Human] appearsIn: [Episode]! } @@ -188,6 +189,10 @@ describe('Test getQueryTypeComplexity function', () => { resolveTo: 'character', weight: mockHumanFriendsFunction, }, + humanFriends: { + resolveTo: 'human', + weight: mockHumanFriendsFunction, + }, }, }, droid: { @@ -407,10 +412,65 @@ describe('Test getQueryTypeComplexity function', () => { xdescribe('with inline fragments', () => { describe('on union types', () => { + beforeAll(() => { + // type Query { + // hero(episode: Episode): Character + // } + // type Character = Human | Droid + // + // type Human { + // name: String! + // homePlanet: String + // friends(first: Int): [Character] + // humanFriends(first: Int): [Human] + // } + // + // type Droid implements Character { + // name: String! + // primaryFunction: String + // friends(first: Int): [Character] + // } + typeWeights = { + query: { + weight: 1, + fields: { + hero: { + resolveTo: 'character', + }, + }, + }, + human: { + weight: 1, + fields: { + name: { weight: 0 }, + homePlanet: { weight: 0 }, + friends: { + resolveTo: 'character', + weight: mockCharacterFriendsFunction, + }, + humanFriends: { + resolveTo: 'human', + weight: mockHumanFriendsFunction, + }, + }, + }, + droid: { + weight: 1, + fields: { + name: { weight: 0 }, + primaryFunction: { weight: 0 }, + friends: { + resolveTo: 'character', + weight: mockDroidFriendsFunction, + }, + }, + }, + }; + }); test('that have a complexity of zero', () => { query = ` query { - heroUnion(episode: EMPIRE) { + hero(episode: EMPIRE) { name ... on Droid { primaryFunction @@ -427,7 +487,7 @@ describe('Test getQueryTypeComplexity function', () => { test('that have differing complexities', () => { query = ` query { - heroUnion(episode: EMPIRE) { + hero(episode: EMPIRE) { name ... on Droid { primaryFunction @@ -448,7 +508,7 @@ describe('Test getQueryTypeComplexity function', () => { test('that contain an object and a non-zero complexity', () => { query = ` query { - heroUnion(episode: EMPIRE) { + hero(episode: EMPIRE) { name friends(first: 3) { name @@ -470,7 +530,7 @@ describe('Test getQueryTypeComplexity function', () => { test('that use a variable', () => { query = ` query { - heroUnion(episode: EMPIRE) { + hero(episode: EMPIRE) { name ... on Droid { primaryFunction @@ -488,6 +548,69 @@ describe('Test getQueryTypeComplexity function', () => { // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); }); + + test('that do not have a TypeCondition', () => { + query = ` + query { + hero(episode: EMPIRE) { + ... { + name + friends(first: 3) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + // Query 1 + 1 hero + max(Character 3, Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); + + xtest('that include a directive', () => { + query = ` + query { + hero(episode: EMPIRE) { + ...@include(if: true) { + name + friends(first: 3) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + // Query 1 + 1 hero + max(...Character 3, ...Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); + + test('and multiple fragments apply to the selection set', () => { + query = ` + query { + hero(episode: EMPIRE) { + ...@include(if: true) { + name + friends(first: 3) { + name + } + } + ... on Human { + humanFriends(first: 2) { + name + } + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + mockHumanFriendsFunction.mockReturnValueOnce(2); + // Query 1 + 1 hero + ...Character 3 + ...Human 2 = 7 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(7); + }); }); describe('on interface types', () => { @@ -572,6 +695,70 @@ describe('Test getQueryTypeComplexity function', () => { // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); }); + + test('that do not have a TypeCondition', () => { + query = ` + query { + hero(episode: EMPIRE) { + ... { + name + ScalarList(first: 1) + friends(first: 3) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + // Query 1 + 1 hero + max(Character 3, Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); + + xtest('that include a directive', () => { + query = ` + query { + hero(episode: EMPIRE) { + ...@include(if: true) { + name + friends(first: 3) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + // Query 1 + 1 hero + max(...Character 3, ...Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); + + test('and multiple fragments apply to the selection set', () => { + query = ` + query { + hero(episode: EMPIRE) { + ...@include(if: true) { + name + friends(first: 3) { + name + } + } + ... on Human { + humanFriends(first: 2) { + name + } + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + mockHumanFriendsFunction.mockReturnValueOnce(2); + // Query 1 + 1 hero + ...Character 3 + ...Human 2 = 7 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); }); }); From 02e221b63d91ca9bdb6cdb067aa5d28e69912aef Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sun, 10 Jul 2022 16:42:44 -0400 Subject: [PATCH 12/18] expanded fragment tests to include cases for fragments without a type condition, directives and multiple applicable fragments. created separate typeWeight object for union tests on fragments for clarity --- test/analysis/typeComplexityAnalysis.test.ts | 190 ++++++++++++++++++- 1 file changed, 186 insertions(+), 4 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 8cc75ff..4e585ca 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -407,10 +407,65 @@ describe('Test getQueryTypeComplexity function', () => { xdescribe('with inline fragments', () => { describe('on union types', () => { + beforeAll(() => { + // type Query { + // hero(episode: Episode): Character + // } + // type Character = Human | Droid + // + // type Human { + // name: String! + // homePlanet: String + // friends(first: Int): [Character] + // humanFriends(first: Int): [Human] + // } + // + // type Droid implements Character { + // name: String! + // primaryFunction: String + // friends(first: Int): [Character] + // } + typeWeights = { + query: { + weight: 1, + fields: { + hero: { + resolveTo: 'character', + }, + }, + }, + human: { + weight: 1, + fields: { + name: { weight: 0 }, + homePlanet: { weight: 0 }, + friends: { + resolveTo: 'character', + weight: mockCharacterFriendsFunction, + }, + humanFriends: { + resolveTo: 'human', + weight: mockHumanFriendsFunction, + }, + }, + }, + droid: { + weight: 1, + fields: { + name: { weight: 0 }, + primaryFunction: { weight: 0 }, + friends: { + resolveTo: 'character', + weight: mockDroidFriendsFunction, + }, + }, + }, + }; + }); test('that have a complexity of zero', () => { query = ` query { - heroUnion(episode: EMPIRE) { + hero(episode: EMPIRE) { name ... on Droid { primaryFunction @@ -427,7 +482,7 @@ describe('Test getQueryTypeComplexity function', () => { test('that have differing complexities', () => { query = ` query { - heroUnion(episode: EMPIRE) { + hero(episode: EMPIRE) { name ... on Droid { primaryFunction @@ -448,7 +503,7 @@ describe('Test getQueryTypeComplexity function', () => { test('that contain an object and a non-zero complexity', () => { query = ` query { - heroUnion(episode: EMPIRE) { + hero(episode: EMPIRE) { name friends(first: 3) { name @@ -470,7 +525,7 @@ describe('Test getQueryTypeComplexity function', () => { test('that use a variable', () => { query = ` query { - heroUnion(episode: EMPIRE) { + hero(episode: EMPIRE) { name ... on Droid { primaryFunction @@ -488,6 +543,69 @@ describe('Test getQueryTypeComplexity function', () => { // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); }); + + test('that do not have a TypeCondition', () => { + query = ` + query { + hero(episode: EMPIRE) { + ... { + name + friends(first: 3) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + // Query 1 + 1 hero + max(Character 3, Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); + + xtest('that include a directive', () => { + query = ` + query { + hero(episode: EMPIRE) { + ...@include(if: true) { + name + friends(first: 3) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + // Query 1 + 1 hero + max(...Character 3, ...Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); + + test('and multiple fragments apply to the selection set', () => { + query = ` + query { + hero(episode: EMPIRE) { + ...@include(if: true) { + name + friends(first: 3) { + name + } + } + ... on Human { + humanFriends(first: 2) { + name + } + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + mockHumanFriendsFunction.mockReturnValueOnce(2); + // Query 1 + 1 hero + ...Character 3 + ...Human 2 = 7 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(7); + }); }); describe('on interface types', () => { @@ -572,6 +690,70 @@ describe('Test getQueryTypeComplexity function', () => { // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); }); + + test('that do not have a TypeCondition', () => { + query = ` + query { + hero(episode: EMPIRE) { + ... { + name + ScalarList(first: 1) + friends(first: 3) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + // Query 1 + 1 hero + max(Character 3, Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); + + xtest('that include a directive', () => { + query = ` + query { + hero(episode: EMPIRE) { + ...@include(if: true) { + name + friends(first: 3) { + name + } + } + ... on Human { + homePlanet + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + // Query 1 + 1 hero + max(...Character 3, ...Human 0) = 5 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); + + test('and multiple fragments apply to the selection set', () => { + query = ` + query { + hero(episode: EMPIRE) { + ...@include(if: true) { + name + friends(first: 3) { + name + } + } + ... on Human { + humanFriends(first: 2) { + name + } + } + } + }`; + mockCharacterFriendsFunction.mockReturnValueOnce(3); + mockHumanFriendsFunction.mockReturnValueOnce(2); + // Query 1 + 1 hero + ...Character 3 + ...Human 2 = 7 + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + }); }); }); From c9b53f0d098f2c42a03c3b03cad681a8e381328a Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sun, 10 Jul 2022 17:08:20 -0400 Subject: [PATCH 13/18] minor correction to inline fragment on interface tests --- test/analysis/typeComplexityAnalysis.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index ff33632..ac5c8b4 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -172,6 +172,10 @@ describe('Test getQueryTypeComplexity function', () => { resolveTo: 'character', weight: mockCharacterFriendsFunction, }, + humanFriends: { + resolveTo: 'human', + weight: mockHumanFriendsFunction, + }, scalarList: { weight: 0, }, @@ -702,7 +706,7 @@ describe('Test getQueryTypeComplexity function', () => { hero(episode: EMPIRE) { ... { name - ScalarList(first: 1) + scalarList(first: 1) friends(first: 3) { name } From 88e4e0326d6949b91ea1bd0bad343e55505e69e9 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sun, 10 Jul 2022 17:11:28 -0400 Subject: [PATCH 14/18] inline fragment test correction --- test/analysis/typeComplexityAnalysis.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index ac5c8b4..607131a 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -761,7 +761,7 @@ describe('Test getQueryTypeComplexity function', () => { mockCharacterFriendsFunction.mockReturnValueOnce(3); mockHumanFriendsFunction.mockReturnValueOnce(2); // Query 1 + 1 hero + ...Character 3 + ...Human 2 = 7 - expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(7); }); }); }); From 71dd46be4677b8e7908b35a36b5223acaf6f1869 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sun, 10 Jul 2022 17:24:50 -0400 Subject: [PATCH 15/18] updated uniontypeweight object --- test/analysis/typeComplexityAnalysis.test.ts | 31 ++++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 607131a..9c4f3d5 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -414,8 +414,9 @@ describe('Test getQueryTypeComplexity function', () => { }); }); - xdescribe('with inline fragments', () => { + describe('with inline fragments', () => { describe('on union types', () => { + let unionTypeWeights: TypeWeightObject; beforeAll(() => { // type Query { // hero(episode: Episode): Character @@ -434,7 +435,7 @@ describe('Test getQueryTypeComplexity function', () => { // primaryFunction: String // friends(first: Int): [Character] // } - typeWeights = { + unionTypeWeights = { query: { weight: 1, fields: { @@ -443,6 +444,10 @@ describe('Test getQueryTypeComplexity function', () => { }, }, }, + character: { + weight: 1, + fields: {}, + }, human: { weight: 1, fields: { @@ -485,7 +490,9 @@ describe('Test getQueryTypeComplexity function', () => { } }`; // Query 1 + 1 hero - expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(2); + expect(getQueryTypeComplexity(parse(query), variables, unionTypeWeights)).toBe( + 2 + ); }); test('that have differing complexities', () => { @@ -506,7 +513,9 @@ describe('Test getQueryTypeComplexity function', () => { }`; // Query 1 + 1 hero + max(Droid 0, Human 3) = 5 mockHumanFriendsFunction.mockReturnValueOnce(3); - expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + expect(getQueryTypeComplexity(parse(query), variables, unionTypeWeights)).toBe( + 5 + ); }); test('that contain an object and a non-zero complexity', () => { @@ -528,7 +537,9 @@ describe('Test getQueryTypeComplexity function', () => { mockCharacterFriendsFunction.mockReturnValueOnce(3); variables = { first: 3 }; // Query 1 + 1 hero + 3 friends/character - expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + expect(getQueryTypeComplexity(parse(query), variables, unionTypeWeights)).toBe( + 5 + ); }); test('that use a variable', () => { @@ -550,7 +561,9 @@ describe('Test getQueryTypeComplexity function', () => { mockDroidFriendsFunction.mockReturnValueOnce(3); variables = { first: 3 }; // Query 1 + 1 hero + max(Droid 3, Human 0) = 5 - expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); + expect(getQueryTypeComplexity(parse(query), variables, unionTypeWeights)).toBe( + 5 + ); }); test('that do not have a TypeCondition', () => { @@ -570,7 +583,7 @@ describe('Test getQueryTypeComplexity function', () => { }`; mockCharacterFriendsFunction.mockReturnValueOnce(3); // Query 1 + 1 hero + max(Character 3, Human 0) = 5 - expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + expect(getQueryTypeComplexity(parse(query), {}, unionTypeWeights)).toBe(5); }); xtest('that include a directive', () => { @@ -590,7 +603,7 @@ describe('Test getQueryTypeComplexity function', () => { }`; mockCharacterFriendsFunction.mockReturnValueOnce(3); // Query 1 + 1 hero + max(...Character 3, ...Human 0) = 5 - expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(5); + expect(getQueryTypeComplexity(parse(query), {}, unionTypeWeights)).toBe(5); }); test('and multiple fragments apply to the selection set', () => { @@ -613,7 +626,7 @@ describe('Test getQueryTypeComplexity function', () => { mockCharacterFriendsFunction.mockReturnValueOnce(3); mockHumanFriendsFunction.mockReturnValueOnce(2); // Query 1 + 1 hero + ...Character 3 + ...Human 2 = 7 - expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(7); + expect(getQueryTypeComplexity(parse(query), {}, unionTypeWeights)).toBe(7); }); }); From 0aad5bf886d08bd3e41aeb0c602b39c0f1c58e23 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Sun, 10 Jul 2022 17:48:23 -0400 Subject: [PATCH 16/18] disabled fragment tests --- test/analysis/typeComplexityAnalysis.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 9c4f3d5..2dbca58 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -414,7 +414,7 @@ describe('Test getQueryTypeComplexity function', () => { }); }); - describe('with inline fragments', () => { + xdescribe('with inline fragments', () => { describe('on union types', () => { let unionTypeWeights: TypeWeightObject; beforeAll(() => { From 77d99ee8a99ddaac53a1ebf195155e2c2f788ece Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Tue, 12 Jul 2022 12:42:45 -0400 Subject: [PATCH 17/18] corrected infline fragment test per pr comments --- test/analysis/typeComplexityAnalysis.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 2dbca58..034a4e0 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -512,7 +512,7 @@ describe('Test getQueryTypeComplexity function', () => { } }`; // Query 1 + 1 hero + max(Droid 0, Human 3) = 5 - mockHumanFriendsFunction.mockReturnValueOnce(3); + mockCharacterFriendsFunction.mockReturnValueOnce(3); expect(getQueryTypeComplexity(parse(query), variables, unionTypeWeights)).toBe( 5 ); From bcb3b6d7eba6d98254e0b35522617e31c9959f95 Mon Sep 17 00:00:00 2001 From: Stephan Halarewicz Date: Wed, 13 Jul 2022 22:14:01 -0400 Subject: [PATCH 18/18] updated differing complexity tests for inline fragments so both fragments have a complexity > 0 --- test/analysis/typeComplexityAnalysis.test.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index 034a4e0..da1d512 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -502,6 +502,9 @@ describe('Test getQueryTypeComplexity function', () => { name ... on Droid { primaryFunction + friends(first: 1) { + name + } } ... on Human { homePlanet @@ -511,8 +514,9 @@ describe('Test getQueryTypeComplexity function', () => { } } }`; - // Query 1 + 1 hero + max(Droid 0, Human 3) = 5 + // Query 1 + 1 hero + max(Droid 2, Human 3) = 5 mockCharacterFriendsFunction.mockReturnValueOnce(3); + mockDroidFriendsFunction.mockReturnValueOnce(1); expect(getQueryTypeComplexity(parse(query), variables, unionTypeWeights)).toBe( 5 ); @@ -655,6 +659,9 @@ describe('Test getQueryTypeComplexity function', () => { name ... on Droid { primaryFunction + friends(first: 2) { + name + } } ... on Human { homePlanet @@ -666,6 +673,7 @@ describe('Test getQueryTypeComplexity function', () => { }`; // Query 1 + 1 hero + max(Droid 0, Human 3) = 5 mockHumanFriendsFunction.mockReturnValueOnce(3); + mockDroidFriendsFunction.mockReturnValueOnce(2); expect(getQueryTypeComplexity(parse(query), variables, typeWeights)).toBe(5); });