diff --git a/src/@types/buildTypeWeights.d.ts b/src/@types/buildTypeWeights.d.ts index 8591cce..cb1a9fe 100644 --- a/src/@types/buildTypeWeights.d.ts +++ b/src/@types/buildTypeWeights.d.ts @@ -1,14 +1,14 @@ interface Fields { - [index: string]: number; + readonly [index: string]: number | ((arg: number, type: Type) => number); } interface Type { - weight: number; - fields: Fields; + readonly weight: number; + readonly fields: Fields; } interface TypeWeightObject { - [index: string]: Type; + readonly [index: string]: Type; } interface TypeWeightConfig { diff --git a/test/analysis/buildTypeWeights.test.ts b/test/analysis/buildTypeWeights.test.ts index 1463668..5ded759 100644 --- a/test/analysis/buildTypeWeights.test.ts +++ b/test/analysis/buildTypeWeights.test.ts @@ -2,6 +2,18 @@ import { buildSchema } from 'graphql'; import { GraphQLSchema } from 'graphql/type/schema'; import buildTypeWeightsFromSchema from '../../src/analysis/buildTypeWeights'; +// these types allow the tests to overwite properties on the typeWeightObject +interface TestFields { + [index: string]: number; +} +interface TestType { + weight: number; + fields: TestFields; +} +interface TestTypeWeightObject { + [index: string]: TestType; +} + xdescribe('Test buildTypeWeightsFromSchema function', () => { let schema: GraphQLSchema; @@ -28,11 +40,14 @@ xdescribe('Test buildTypeWeightsFromSchema function', () => { test('multiple types', () => { schema = buildSchema(` + type Query { + user: User, + movie: Movie, + } type User { name: String email: String } - type Movie { name: String director: String @@ -40,6 +55,10 @@ xdescribe('Test buildTypeWeightsFromSchema function', () => { `); expect(buildTypeWeightsFromSchema(schema)).toEqual({ + Query: { + weight: 1, + fields: {}, + }, User: { weight: 1, fields: { @@ -63,12 +82,10 @@ xdescribe('Test buildTypeWeightsFromSchema function', () => { user: User movie: Movie } - type User { name: String - email: String + film: Movie } - type Movie { name: String director: User @@ -121,29 +138,220 @@ xdescribe('Test buildTypeWeightsFromSchema function', () => { }); }); + test('types with arguments', () => { + schema = buildSchema(` + type Query { + character(id: ID!): Character + } + type Character { + id: ID! + name: String! + }`); + expect(buildTypeWeightsFromSchema(schema)).toEqual({ + Query: { + weight: 1, + fields: {}, + }, + Character: { + weight: 1, + fields: { + id: 0, + name: 0, + }, + }, + }); + }); + + test('enum types', () => { + schema = buildSchema(` + type Query { + hero(episode: Episode): Character + } + type Character { + id: ID! + name: String! + } + enum Episode { + NEWHOPE + EMPIRE + JEDI + }`); + expect(buildTypeWeightsFromSchema(schema)).toEqual({ + Query: { + weight: 1, + fields: {}, + }, + Character: { + weight: 1, + fields: { + id: 0, + name: 0, + }, + }, + Episode: { + weight: 0, + fields: {}, + }, + }); + }); + + test('fields returning lists of objects of determinate size', () => { + schema = buildSchema(` + type Query { + reviews(episode: Episode!, first: Int): [Review] + } + type Review { + episode: Episode + stars: Int! + commentary: String + } + enum Episode { + NEWHOPE + EMPIRE + JEDI + }`); + expect(buildTypeWeightsFromSchema(schema)).toEqual({ + Query: { + weight: 1, + fields: { + // FIXME: check the best solution during implementation and update the tests here. + reviews: (arg: number, type: Type) => arg * type.weight, + // code from PR review -> reviews: (type) => args[multiplierName] * typeWeightObject[type].weight + }, + }, + Review: { + weight: 1, + fields: { + stars: 0, + commentary: 0, + }, + }, + Episode: { + weight: 0, + fields: {}, + }, + }); + }); + + // TODO: need to figure out how to handle this situation. Skip for now. + // The field friends returns a list of an unknown number of objects. + xtest('fields returning lists of objects of indetermitae size', () => { + schema = buildSchema(` + type Human { + id: ID! + name: String! + homePlanet: String + friends: [Human] + } + `); + expect(buildTypeWeightsFromSchema(schema)).toEqual({ + Human: { + weight: 1, + fields: { + // FIXME: check the best solution during implementation and update the tests here. + friends: (arg: number, type: Type) => arg * type.weight, + }, + }, + }); + }); + + test('interface types', () => { + schema = buildSchema(` + interface Character { + id: ID! + name: String! + } + + type Human implements Character { + id: ID! + name: String! + homePlanet: String + } + + type Droid implements Character { + id: ID! + name: String! + primaryFunction: String + }`); + expect(buildTypeWeightsFromSchema(schema)).toEqual({ + Character: { + weight: 1, + fields: { + id: 0, + name: 0, + }, + }, + Human: { + weight: 1, + fields: { + id: 0, + name: 0, + homePlanet: 0, + }, + }, + Droid: { + weight: 1, + fields: { + id: 0, + name: 0, + primaryFunction: 0, + }, + }, + Episode: { + weight: 0, + fields: {}, + }, + }); + }); + + test('union tyes', () => { + schema = buildSchema(` + union SearchResult = Human | Droid + type Human{ + homePlanet: String + } + type Droid { + primaryFunction: String + }`); + expect(buildTypeWeightsFromSchema(schema)).toEqual({ + SearchResult: { + weight: 1, + fields: {}, + }, + human: { + weight: 1, + fields: { + homePlanet: 0, + }, + }, + droid: { + weight: 1, + fields: { + primaryFunction: 0, + }, + }, + }); + }); + // TODO: Tests should be written to acount for the additional scenarios possible in a schema // Mutation type + // Input types (a part of mutations?) // Subscription type - // List type - // Enem types - // Interface - // Unions - // Input types }); describe('changes "type weight object" type weights with user configuration of...', () => { - let expectedOutput: TypeWeightObject; + let expectedOutput: TestTypeWeightObject; beforeEach(() => { schema = buildSchema(` type Query { - user: User - movie: Movie + user(id: ID!): User + movie(id: ID!): Movie } type User { name: String - email: String + film: Movie } type Movie { @@ -163,7 +371,6 @@ xdescribe('Test buildTypeWeightsFromSchema function', () => { weight: 1, fields: { name: 0, - email: 0, }, }, Movie: { @@ -202,7 +409,6 @@ xdescribe('Test buildTypeWeightsFromSchema function', () => { }); expectedOutput.user.fields.name = 2; - expectedOutput.user.fields.email = 2; expectedOutput.movie.fields.name = 2; expect(typeWeightObject).toEqual({ expectedOutput }); @@ -249,5 +455,8 @@ xdescribe('Test buildTypeWeightsFromSchema function', () => { 'negative' ); }); + + // TODO: throw validation error if schema is invalid + test('schema is invalid', () => {}); }); });