diff --git a/test/analysis/buildTypeWeights.test.ts b/test/analysis/buildTypeWeights.test.ts index 4a94e06..0f31137 100644 --- a/test/analysis/buildTypeWeights.test.ts +++ b/test/analysis/buildTypeWeights.test.ts @@ -489,6 +489,103 @@ describe('Test buildTypeWeightsFromSchema function', () => { }); }); + xdescribe('Not null operator (!) is used', () => { + test('on a scalar, enum or object type', () => { + schema = buildSchema(` + type Human{ + homePlanet: String! + age: Int! + isHero: Boolean! + droids: Droid! + episode: Episode! + } + type Droid { + primaryFunction: String + } + enum Episode { + NEWHOPE + EMPIRE + JEDI + } + `); + + expect(buildTypeWeightsFromSchema(schema)).toEqual({ + human: { + weight: 1, + fields: { + homePlanet: { + weight: 0, + }, + age: { + weight: 0, + }, + isHero: { + weight: 0, + }, + droids: { + resolveTo: 'droid', + }, + episode: { + resolveTo: 'episode', + }, + }, + }, + droid: { + weight: 1, + fields: { + primaryFunction: { + weight: 0, + }, + }, + }, + episode: { + weight: 0, + fields: {}, + }, + }); + }); + + test('on list types', () => { + schema = buildSchema(` + type Planet{ + droids(first: Int!): [Droid]! + heroDroids(first: Int!): [Droid!] + villainDroids(first: Int!):[Droid!]! + } + type Droid { + primaryFunction: String + }`); + + expect(buildTypeWeightsFromSchema(schema)).toEqual({ + planet: { + weight: 1, + fields: { + droids: { + resolveTo: 'droid', + weight: expect.any(Function), + }, + heroDroids: { + resolveTo: 'droid', + weight: expect.any(Function), + }, + villainDroids: { + resolveTo: 'droid', + weight: expect.any(Function), + }, + }, + }, + droid: { + weight: 1, + fields: { + primaryFunction: { + weight: 0, + }, + }, + }, + }); + }); + }); + // TODO: Tests should be written to account for the additional scenarios possible in a schema // Mutation type // Input types (a part of mutations?) diff --git a/test/analysis/typeComplexityAnalysis.test.ts b/test/analysis/typeComplexityAnalysis.test.ts index fa1d89f..f50df69 100644 --- a/test/analysis/typeComplexityAnalysis.test.ts +++ b/test/analysis/typeComplexityAnalysis.test.ts @@ -13,6 +13,7 @@ import { TypeWeightObject, Variables } from '../../src/@types/buildTypeWeights'; droid(id: ID!): Droid human(id: ID!): Human scalars: Scalars + nonNull: [Droid!]! } enum Episode { @@ -100,6 +101,7 @@ import { TypeWeightObject, Variables } from '../../src/@types/buildTypeWeights'; const mockWeightFunction = jest.fn(); const mockHumanFriendsFunction = jest.fn(); const mockDroidFriendsFunction = jest.fn(); +const nonNullMockWeightFunction = jest.fn(); // this object is created by the schema above for use in all the tests below const typeWeights: TypeWeightObject = { @@ -130,6 +132,10 @@ const typeWeights: TypeWeightObject = { scalars: { resolveTo: 'scalars', }, + nonNull: { + resolveTo: 'droid', + weight: nonNullMockWeightFunction, + }, }, }, episode: { @@ -333,6 +339,14 @@ describe('Test getQueryTypeComplexity function', () => { expect(mockWeightFunction.mock.calls[1].length).toBe(3); // calling with arguments and variables }); + test('with bounded lists including non-null operators', () => { + query = `query {nonNull(episode: EMPIRE, first: 3) { name, id } }`; + nonNullMockWeightFunction.mockReturnValueOnce(3); + expect(getQueryTypeComplexity(parse(query), {}, typeWeights)).toBe(4); // 1 Query + 3 reviews + expect(nonNullMockWeightFunction.mock.calls.length).toBe(1); + expect(nonNullMockWeightFunction.mock.calls[0].length).toBe(3); + }); + describe('with nested lists', () => { test('and simple nesting', () => { query = `query { human(id: 1) { name, friends(first: 5) { name, friends(first: 3){ name }}}} `; diff --git a/test/analysis/weightFunction.test.ts b/test/analysis/weightFunction.test.ts index cac1a47..16eeea1 100644 --- a/test/analysis/weightFunction.test.ts +++ b/test/analysis/weightFunction.test.ts @@ -18,8 +18,10 @@ describe('Weight Function correctly parses Argument Nodes if', () => { type Query { reviews(episode: Episode!, first: Int = 5): [Review] heroes(episode: Episode!, first: Int): [Review] - villains(episode: Episode!, limit: Int! = 3): [Review] - characters(episode: Episode!, limit: Int!): [Review] + villains(episode: Episode!, limit: Int! = 3): [Review]! + characters(episode: Episode!, limit: Int!): [Review!] + droids(episode: Episode!, limit: Int!): [Review!]! + } type Review { episode: Episode @@ -82,6 +84,20 @@ describe('Weight Function correctly parses Argument Nodes if', () => { }); }); + xtest('the list is defined with non-null operators (!)', () => { + const villainsQuery = `query { villains(episode: NEWHOPE, limit: 3) { stars, episode } }`; + const willainsQueryAST: DocumentNode = parse(villainsQuery); + expect(getQueryTypeComplexity(willainsQueryAST, {}, typeWeights)).toBe(4); + + const charQuery = `query { characters(episode: NEWHOPE, limit: 3) { stars, episode } }`; + const charQueryAST: DocumentNode = parse(charQuery); + expect(getQueryTypeComplexity(charQueryAST, {}, typeWeights)).toBe(4); + + const droidsQuery = `droidsQuery { droids(episode: NEWHOPE, limit: 3) { stars, episode } }`; + const droidsQueryAST: DocumentNode = parse(droidsQuery); + expect(getQueryTypeComplexity(droidsQueryAST, {}, typeWeights)).toBe(4); + }); + test('a custom object weight was configured', () => { const customTypeWeights: TypeWeightObject = buildTypeWeightsFromSchema(schema, { object: 3,