Skip to content

Commit

Permalink
simplify validation harness by extracting union types into approriate…
Browse files Browse the repository at this point in the history
… tests
  • Loading branch information
IvanGoncharov committed Jun 15, 2021
1 parent f9bf263 commit d6bc7d0
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 49 deletions.
61 changes: 56 additions & 5 deletions src/validation/__tests__/FieldsOnCorrectTypeRule-test.ts
Expand Up @@ -10,16 +10,49 @@ import { buildSchema } from '../../utilities/buildASTSchema';
import { validate } from '../validate';
import { FieldsOnCorrectTypeRule } from '../rules/FieldsOnCorrectTypeRule';

import { expectValidationErrors } from './harness';
import { expectValidationErrorsWithSchema } from './harness';

function expectErrors(queryStr: string) {
return expectValidationErrors(FieldsOnCorrectTypeRule, queryStr);
return expectValidationErrorsWithSchema(
testSchema,
FieldsOnCorrectTypeRule,
queryStr,
);
}

function expectValid(queryStr: string) {
expectErrors(queryStr).to.deep.equal([]);
}

const testSchema = buildSchema(`
interface Pet {
name: String
}
type Dog implements Pet {
name: String
nickname: String
barkVolume: Int
}
type Cat implements Pet {
name: String
nickname: String
meowVolume: Int
}
union CatOrDog = Cat | Dog
type Human {
name: String
pets: [Pet]
}
type Query {
human: Human
}
`);

describe('Validate: Fields on correct type', () => {
it('Object field selection', () => {
expectValid(`
Expand Down Expand Up @@ -237,7 +270,7 @@ describe('Validate: Fields on correct type', () => {
`).to.deep.equal([
{
message:
'Cannot query field "name" on type "CatOrDog". Did you mean to use an inline fragment on "Being", "Pet", "Canine", "Cat", or "Dog"?',
'Cannot query field "name" on type "CatOrDog". Did you mean to use an inline fragment on "Pet", "Cat", or "Dog"?',
locations: [{ line: 3, column: 9 }],
},
]);
Expand Down Expand Up @@ -332,7 +365,7 @@ describe('Validate: Fields on correct type', () => {
});

it('Sort type suggestions based on inheritance order', () => {
const schema = buildSchema(`
const interfaceSchema = buildSchema(`
interface T { bar: String }
type Query { t: T }
Expand All @@ -352,9 +385,27 @@ describe('Validate: Fields on correct type', () => {
}
`);

expectErrorMessage(schema, '{ t { foo } }').to.equal(
expectErrorMessage(interfaceSchema, '{ t { foo } }').to.equal(
'Cannot query field "foo" on type "T". Did you mean to use an inline fragment on "Z", "Y", or "X"?',
);

const unionSchema = buildSchema(`
interface Animal { name: String }
interface Mammal implements Animal { name: String }
interface Canine implements Animal & Mammal { name: String }
type Dog implements Animal & Mammal & Canine { name: String }
interface Feline implements Animal & Mammal { name: String }
type Cat implements Animal & Mammal & Feline { name: String }
union CatOrDog = Cat | Dog
type Query { catOrDog: CatOrDog }
`);

expectErrorMessage(unionSchema, '{ catOrDog { name } }').to.equal(
'Cannot query field "name" on type "CatOrDog". Did you mean to use an inline fragment on "Animal", "Mamal", "Canine", "Dog", or "Feline"?',
);
});

it('Limits lots of type suggestions', () => {
Expand Down
57 changes: 55 additions & 2 deletions src/validation/__tests__/PossibleFragmentSpreadsRule-test.ts
@@ -1,17 +1,70 @@
import { describe, it } from 'mocha';

import { buildSchema } from '../../utilities/buildASTSchema';

import { PossibleFragmentSpreadsRule } from '../rules/PossibleFragmentSpreadsRule';

import { expectValidationErrors } from './harness';
import { expectValidationErrorsWithSchema } from './harness';

function expectErrors(queryStr: string) {
return expectValidationErrors(PossibleFragmentSpreadsRule, queryStr);
return expectValidationErrorsWithSchema(
testSchema,
PossibleFragmentSpreadsRule,
queryStr,
);
}

function expectValid(queryStr: string) {
expectErrors(queryStr).to.deep.equal([]);
}

const testSchema = buildSchema(`
interface Being {
name: String
}
interface Pet implements Being {
name: String
}
type Dog implements Being & Pet {
name: String
barkVolume: Int
}
type Cat implements Being & Pet {
name: String
meowVolume: Int
}
union CatOrDog = Cat | Dog
interface Intelligent {
iq: Int
}
type Human implements Being & Intelligent {
name: String
pets: [Pet]
iq: Int
}
type Alien implements Being & Intelligent {
name: String
iq: Int
}
union DogOrHuman = Dog | Human
union HumanOrAlien = Human | Alien
type Query {
catOrDog: CatOrDog
dogOrHuman: DogOrHuman
humanOrAlien: HumanOrAlien
}
`);

describe('Validate: Possible fragment spreads', () => {
it('of the same object', () => {
expectValid(`
Expand Down
32 changes: 5 additions & 27 deletions src/validation/__tests__/harness.ts
Expand Up @@ -12,20 +12,16 @@ import { validate, validateSDL } from '../validate';
import type { ValidationRule, SDLValidationRule } from '../ValidationContext';

export const testSchema: GraphQLSchema = buildSchema(`
interface Being {
name(surname: Boolean): String
}
interface Mammal {
mother: Mammal
father: Mammal
}
interface Pet implements Being {
interface Pet {
name(surname: Boolean): String
}
interface Canine implements Mammal & Being {
interface Canine implements Mammal {
name(surname: Boolean): String
mother: Canine
father: Canine
Expand All @@ -37,7 +33,7 @@ export const testSchema: GraphQLSchema = buildSchema(`
DOWN
}
type Dog implements Being & Pet & Mammal & Canine {
type Dog implements Pet & Mammal & Canine {
name(surname: Boolean): String
nickname: String
barkVolume: Int
Expand All @@ -49,7 +45,7 @@ export const testSchema: GraphQLSchema = buildSchema(`
father: Dog
}
type Cat implements Being & Pet {
type Cat implements Pet {
name(surname: Boolean): String
nickname: String
meows: Boolean
Expand All @@ -59,27 +55,12 @@ export const testSchema: GraphQLSchema = buildSchema(`
union CatOrDog = Cat | Dog
interface Intelligent {
iq: Int
}
type Human implements Being & Intelligent {
type Human {
name(surname: Boolean): String
pets: [Pet]
relatives: [Human]
iq: Int
}
type Alien implements Being & Intelligent {
name(surname: Boolean): String
numEyes: Int
iq: Int
}
union DogOrHuman = Dog | Human
union HumanOrAlien = Human | Alien
enum FurColor {
BROWN
BLACK
Expand Down Expand Up @@ -120,13 +101,10 @@ export const testSchema: GraphQLSchema = buildSchema(`
type QueryRoot {
human(id: ID): Human
alien: Alien
dog: Dog
cat: Cat
pet: Pet
catOrDog: CatOrDog
dogOrHuman: DogOrHuman
humanOrAlien: HumanOrAlien
complicatedArgs: ComplicatedArgs
}
Expand Down
34 changes: 19 additions & 15 deletions src/validation/__tests__/validation-test.ts
Expand Up @@ -23,12 +23,14 @@ describe('Validate: Supports full validation', () => {
it('validates queries', () => {
const doc = parse(`
query {
catOrDog {
... on Cat {
furColor
}
... on Dog {
isHouseTrained
human {
pets {
... on Cat {
meowsVolume
}
... on Dog {
barkVolume
}
}
}
}
Expand Down Expand Up @@ -60,12 +62,14 @@ describe('Validate: Supports full validation', () => {

const doc = parse(`
query {
catOrDog {
... on Cat {
furColor
}
... on Dog {
isHouseTrained
human {
pets {
... on Cat {
meowsVolume
}
... on Dog {
barkVolume
}
}
}
}
Expand All @@ -75,9 +79,9 @@ describe('Validate: Supports full validation', () => {
const errorMessages = errors.map((error) => error.message);

expect(errorMessages).to.deep.equal([
'Cannot query field "catOrDog" on type "QueryRoot". Did you mean "catOrDog"?',
'Cannot query field "furColor" on type "Cat". Did you mean "furColor"?',
'Cannot query field "isHouseTrained" on type "Dog". Did you mean "isHouseTrained"?',
'Cannot query field "human" on type "QueryRoot". Did you mean "human"?',
'Cannot query field "meowsVolume" on type "Cat". Did you mean "meowsVolume"?',
'Cannot query field "barkVolume" on type "Dog". Did you mean "barkVolume"?',
]);
});

Expand Down

0 comments on commit d6bc7d0

Please sign in to comment.