Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplify validation harness by extracting union types into approriate… #3180

Merged
merged 1 commit into from Jun 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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", "Mammal", "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