Skip to content

Commit 4349a67

Browse files
authored
Merge pull request #61 from oslabs-beta/sh/test-suite-updates
Update test suite to better handle lists, variables and arguments
2 parents 1b0ac1b + 5577180 commit 4349a67

File tree

9 files changed

+346
-75
lines changed

9 files changed

+346
-75
lines changed

src/@types/buildTypeWeights.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ export interface TypeWeightConfig {
1717
scalar?: number;
1818
connection?: number;
1919
}
20+
21+
type Variables = {
22+
[index: string]: readonly unknown;
23+
};

src/analysis/ASTnodefunctions.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
SelectionNode,
99
ArgumentNode,
1010
} from 'graphql';
11-
import { FieldWeight, TypeWeightObject } from '../@types/buildTypeWeights';
11+
import { FieldWeight, TypeWeightObject, Variables } from '../@types/buildTypeWeights';
1212

1313
// TODO: handle variables and arguments
1414
// ! this is not functional
@@ -48,7 +48,7 @@ const getArgObj = (args: ArgumentNode[]): { [index: string]: any } => {
4848
export function fieldNode(
4949
node: FieldNode,
5050
typeWeights: TypeWeightObject,
51-
variables: any | undefined,
51+
variables: Variables,
5252
parentName: string
5353
): number {
5454
let complexity = 0;
@@ -73,6 +73,8 @@ export function fieldNode(
7373
// if the feild weight is a number, add the number to the total complexity
7474
complexity += fieldWeight;
7575
} else if (node.arguments) {
76+
// BUG: This code is reached when fieldWeight is undefined, which could result from an invalid query or this type
77+
// missing from the typeWeight object. If left unhandled an error is thrown
7678
// otherwise the the feild weight is a list, invoke the function with variables
7779
// TODO: calculate the complexity for lists with arguments and varibales
7880
// ! this is not functional
@@ -86,7 +88,7 @@ export function fieldNode(
8688
export function selectionNode(
8789
node: SelectionNode,
8890
typeWeights: TypeWeightObject,
89-
variables: any | undefined,
91+
variables: Variables,
9092
parentName: string
9193
): number {
9294
let complexity = 0;
@@ -103,7 +105,7 @@ export function selectionNode(
103105
export function selectionSetNode(
104106
node: SelectionSetNode,
105107
typeWeights: TypeWeightObject,
106-
variables: any | undefined,
108+
variables: Variables,
107109
parentName: string
108110
): number {
109111
let complexity = 0;
@@ -119,7 +121,7 @@ export function selectionSetNode(
119121
export function definitionNode(
120122
node: DefinitionNode,
121123
typeWeights: TypeWeightObject,
122-
variables: any | undefined
124+
variables: Variables
123125
): number {
124126
let complexity = 0;
125127
// check the kind property against the set of definiton nodes that are possible
@@ -145,7 +147,7 @@ export function definitionNode(
145147
export function documentNode(
146148
node: DocumentNode,
147149
typeWeights: TypeWeightObject,
148-
variables: any | undefined
150+
variables: Variables
149151
): number {
150152
let complexity = 0;
151153
// iterate through 'definitions' array on the document node

src/analysis/buildTypeWeights.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ function parseQuery(
8383
// If query has an argument matching one of the limiting keywords and resolves to a list then the weight of the query
8484
// should be dependent on both the weight of the resolved type and the limiting argument.
8585
// FIXME: Can nonnull wrap list types?
86+
// BUG: Lists need to be accounted for in all types not just queries
8687
if (KEYWORDS.includes(arg.name) && isListType(resolveType)) {
8788
// Get the type that comprises the list
8889
const listType = resolveType.ofType;

src/analysis/typeComplexityAnalysis.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { DocumentNode } from 'graphql';
2-
import { TypeWeightObject } from '../@types/buildTypeWeights';
2+
import { TypeWeightObject, Variables } from '../@types/buildTypeWeights';
33
import { documentNode } from './ASTnodefunctions';
44

55
/**
@@ -9,12 +9,12 @@ import { documentNode } from './ASTnodefunctions';
99
* TO DO: extend the functionality to work for mutations and subscriptions and directives
1010
*
1111
* @param {string} queryAST
12-
* @param {any | undefined} varibales
12+
* @param {Variables} variables
1313
* @param {TypeWeightObject} typeWeights
1414
*/
1515
function getQueryTypeComplexity(
1616
queryAST: DocumentNode,
17-
variables: any | undefined,
17+
variables: Variables,
1818
typeWeights: TypeWeightObject
1919
): number {
2020
let complexity = 0;

test/analysis/buildTypeWeights.test.ts

Lines changed: 150 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'ts-jest';
12
import { buildSchema } from 'graphql';
23
import { GraphQLSchema } from 'graphql/type/schema';
34
import buildTypeWeightsFromSchema from '../../src/analysis/buildTypeWeights';
@@ -196,45 +197,159 @@ describe('Test buildTypeWeightsFromSchema function', () => {
196197
});
197198
});
198199

199-
test('fields returning lists of objects of determinate size', () => {
200-
schema = buildSchema(`
201-
type Query {
202-
reviews(episode: Episode!, first: Int): [Review]
203-
}
204-
type Review {
205-
episode: Episode
206-
stars: Int!
207-
commentary: String
208-
}
209-
enum Episode {
210-
NEWHOPE
211-
EMPIRE
212-
JEDI
213-
}`);
200+
describe('fields returning lists of objects of determinate size and...', () => {
201+
test('args include limiting keywords: "first", "last", "limit"', () => {
202+
schema = buildSchema(`
203+
type Query {
204+
reviews(episode: Episode!, first: Int): [Review]
205+
heroes(episode: Episode!, last: Int): [Review]
206+
villains(episode: Episode!, limit: Int): [Review]
207+
}
208+
type Review {
209+
episode: Episode
210+
stars: Int!
211+
commentary: String
212+
}
213+
enum Episode {
214+
NEWHOPE
215+
EMPIRE
216+
JEDI
217+
}`);
218+
219+
expect(buildTypeWeightsFromSchema(schema)).toEqual({
220+
query: {
221+
weight: 1,
222+
fields: {
223+
reviews: expect.any(Function),
224+
heroes: expect.any(Function),
225+
villains: expect.any(Function),
226+
},
227+
},
228+
review: {
229+
weight: 1,
230+
fields: {
231+
stars: 0,
232+
commentary: 0,
233+
},
234+
},
235+
episode: {
236+
weight: 0,
237+
fields: {},
238+
},
239+
});
240+
});
214241

215-
expect(buildTypeWeightsFromSchema(schema)).toEqual({
216-
query: {
217-
weight: 1,
218-
fields: {
219-
reviews: expect.any(Function), // TODO: Test this function separately
242+
xtest('are not on the Query type', () => {
243+
schema = buildSchema(`
244+
type Query {
245+
reviews(episode: Episode!, first: Int): [Movie]
246+
}
247+
type Movie {
248+
episode: Episode
249+
stars: Int!
250+
commentary: String
251+
heroes(episode: Episode!, last: Int): [Character]
252+
villains(episode: Episode!, limit: Int): [Character]
253+
}
254+
type Character {
255+
name: String!
256+
}
257+
enum Episode {
258+
NEWHOPE
259+
EMPIRE
260+
JEDI
261+
}`);
262+
263+
expect(buildTypeWeightsFromSchema(schema)).toEqual({
264+
query: {
265+
weight: 1,
266+
fields: {
267+
reviews: expect.any(Function),
268+
},
220269
},
221-
},
222-
review: {
223-
weight: 1,
224-
fields: {
225-
stars: 0,
226-
commentary: 0,
270+
movie: {
271+
weight: 1,
272+
fields: {
273+
stars: 0,
274+
commentary: 0,
275+
heroes: expect.any(Function),
276+
villains: expect.any(Function),
277+
},
227278
},
228-
},
229-
episode: {
230-
weight: 0,
231-
fields: {},
232-
},
279+
character: {
280+
weight: 1,
281+
fields: {
282+
name: 0,
283+
},
284+
},
285+
episode: {
286+
weight: 0,
287+
fields: {},
288+
},
289+
});
290+
});
291+
292+
xtest('the list resolves to an enum or scalar', () => {
293+
schema = buildSchema(`
294+
type Query {
295+
episodes(first: Int): [Episode]
296+
heroes(episode: Episode!, first: Int = 3): [Int]
297+
villains(episode: Episode!, limit: Int! = 1): [String]
298+
}
299+
enum Episode {
300+
NEWHOPE
301+
EMPIRE
302+
JEDI
303+
}`);
304+
305+
expect(buildTypeWeightsFromSchema(schema)).toEqual({
306+
query: {
307+
weight: 1,
308+
fields: {
309+
episodes: 0,
310+
heroes: 0,
311+
villains: 0,
312+
},
313+
},
314+
episode: {
315+
weight: 0,
316+
fields: {},
317+
},
318+
});
319+
});
320+
321+
xtest('the list resolves to an enum or scalar and a custom scalar weight was configured', () => {
322+
schema = buildSchema(`
323+
type Query {
324+
episodes(first: Int): [Episode]
325+
heroes(episode: Episode!, first: Int = 3): [Int]
326+
villains(episode: Episode!, limit: Int! = 1): [String]
327+
}
328+
enum Episode {
329+
NEWHOPE
330+
EMPIRE
331+
JEDI
332+
}`);
333+
334+
expect(buildTypeWeightsFromSchema(schema, { scalar: 11 })).toEqual({
335+
query: {
336+
weight: 1,
337+
fields: {
338+
episodes: 11,
339+
heroes: 11,
340+
villains: 11,
341+
},
342+
},
343+
episode: {
344+
weight: 0,
345+
fields: {},
346+
},
347+
});
233348
});
234349
});
235350

236-
// TODO: need to figure out how to handle this situation. Skip for now.
237-
// The field friends returns a list of an unknown number of objects.
351+
// FIXME: need to figure out how to handle this situation. Skip for now.
352+
// The field 'friends' returns a list of an unknown number of objects.
238353
xtest('fields returning lists of objects of indeterminate size', () => {
239354
schema = buildSchema(`
240355
type Human {
@@ -248,7 +363,6 @@ describe('Test buildTypeWeightsFromSchema function', () => {
248363
human: {
249364
weight: 1,
250365
fields: {
251-
// TODO: Test this function separately.
252366
friends: expect.any(Function),
253367
},
254368
},
@@ -329,7 +443,7 @@ describe('Test buildTypeWeightsFromSchema function', () => {
329443
});
330444
});
331445

332-
// TODO: Tests should be written to acount for the additional scenarios possible in a schema
446+
// TODO: Tests should be written to account for the additional scenarios possible in a schema
333447
// Mutation type
334448
// Input types (a part of mutations?)
335449
// Subscription type
@@ -453,6 +567,6 @@ describe('Test buildTypeWeightsFromSchema function', () => {
453567
});
454568

455569
// TODO: throw validation error if schema is invalid
456-
test('schema is invalid', () => {});
570+
xtest('schema is invalid', () => {});
457571
});
458572
});

0 commit comments

Comments
 (0)