-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat:
validateEnums
+ ensure non-nulls
with `validateEnums` option it will fail if it finds a value outside of the enum elements + it will fail if it encounters a null on a non-null field fix #2 #7
- Loading branch information
Showing
4 changed files
with
304 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
import { | ||
ApolloLink, | ||
DocumentNode, | ||
execute, | ||
getOperationName, | ||
GraphQLRequest, | ||
Observable | ||
} from "apollo-link"; | ||
import { graphql } from "graphql"; | ||
import gql from "graphql-tag"; | ||
import { makeExecutableSchema } from "graphql-tools"; | ||
import { withScalars } from ".."; | ||
|
||
const typeDefs = gql` | ||
type Query { | ||
first: MyEnum | ||
second: MyEnum! | ||
third: MyEnum | ||
} | ||
enum MyEnum { | ||
a | ||
b | ||
c | ||
} | ||
`; | ||
|
||
const resolvers = { | ||
Query: { | ||
first: () => "a", | ||
second: () => "b", | ||
third: () => null | ||
} | ||
}; | ||
|
||
const schema = makeExecutableSchema({ | ||
typeDefs, | ||
resolvers | ||
}); | ||
|
||
const querySource = ` | ||
query MyQuery { | ||
first | ||
second | ||
third | ||
otherFirst: first | ||
otherSecond: second | ||
otherThird: third | ||
} | ||
`; | ||
|
||
const queryDocument: DocumentNode = gql` | ||
${querySource} | ||
`; | ||
const queryOperationName = getOperationName(queryDocument); | ||
if (!queryOperationName) throw new Error("invalid query operation name"); | ||
|
||
const request: GraphQLRequest = { | ||
query: queryDocument, | ||
variables: {}, | ||
operationName: queryOperationName | ||
}; | ||
|
||
const validResponse = { | ||
data: { | ||
first: "a", | ||
second: "b", | ||
third: null, | ||
otherFirst: "a", | ||
otherSecond: "b", | ||
otherThird: null | ||
} | ||
}; | ||
|
||
const invalidResponse = { | ||
data: { | ||
first: "a", | ||
second: "b", | ||
third: null, | ||
otherFirst: "invalid", | ||
otherSecond: "b", | ||
otherThird: null | ||
} | ||
}; | ||
|
||
const badNullsWithAliasResponse = { | ||
data: { | ||
first: null, | ||
second: "b", | ||
third: null, | ||
otherFirst: null, | ||
otherSecond: null, | ||
otherThird: null | ||
} | ||
}; | ||
const badNullsResponse = { | ||
data: { | ||
first: null, | ||
second: null, | ||
third: null, | ||
otherFirst: null, | ||
otherSecond: "b", | ||
otherThird: null | ||
} | ||
}; | ||
|
||
describe("enum returned directly from first level queries", () => { | ||
it("ensure the response fixture is valid (ensure that in the response we have the RAW, the Server is converting from Date to STRING)", async () => { | ||
expect.assertions(1); | ||
const queryResponse = await graphql(schema, querySource); | ||
expect(queryResponse).toEqual(validResponse); | ||
}); | ||
|
||
describe("with valid enum values", () => { | ||
it("validateEnums false (or missing) => return response", done => { | ||
const link = ApolloLink.from([ | ||
withScalars({ schema, validateEnums: false }), | ||
new ApolloLink(() => { | ||
return Observable.of(validResponse); | ||
}) | ||
]); | ||
|
||
const observable = execute(link, request); | ||
observable.subscribe(value => { | ||
expect(value).toEqual(validResponse); | ||
done(); | ||
}); | ||
expect.assertions(1); | ||
}); | ||
|
||
it("validateEnums false (or missing) => return response", done => { | ||
const link = ApolloLink.from([ | ||
withScalars({ schema, validateEnums: true }), | ||
new ApolloLink(() => { | ||
return Observable.of(validResponse); | ||
}) | ||
]); | ||
|
||
const observable = execute(link, request); | ||
observable.subscribe(value => { | ||
expect(value).toEqual(validResponse); | ||
done(); | ||
}); | ||
expect.assertions(1); | ||
}); | ||
}); | ||
|
||
describe("with invalid enum values", () => { | ||
it("validateEnums false (or missing) => return invalid response", done => { | ||
const link = ApolloLink.from([ | ||
withScalars({ schema, validateEnums: false }), | ||
new ApolloLink(() => { | ||
return Observable.of(invalidResponse); | ||
}) | ||
]); | ||
|
||
const observable = execute(link, request); | ||
observable.subscribe(value => { | ||
expect(value).toEqual(invalidResponse); | ||
done(); | ||
}); | ||
expect.assertions(1); | ||
}); | ||
|
||
it("validateEnums true => return error", done => { | ||
const link = ApolloLink.from([ | ||
withScalars({ schema, validateEnums: true }), | ||
new ApolloLink(() => { | ||
return Observable.of(invalidResponse); | ||
}) | ||
]); | ||
|
||
const observable = execute(link, request); | ||
observable.subscribe(value => { | ||
expect(value).toEqual({ | ||
errors: [ | ||
{ | ||
message: `enum "MyEnum" with invalid value` | ||
} | ||
] | ||
}); | ||
done(); | ||
}); | ||
expect.assertions(1); | ||
}); | ||
}); | ||
|
||
describe("null values on non-null field", () => { | ||
it("no alias", done => { | ||
const link = ApolloLink.from([ | ||
withScalars({ schema, validateEnums: true }), | ||
new ApolloLink(() => { | ||
return Observable.of(badNullsResponse); | ||
}) | ||
]); | ||
|
||
const observable = execute(link, request); | ||
observable.subscribe(value => { | ||
expect(value).toEqual({ | ||
errors: [ | ||
{ | ||
message: `non-null field "second" with null value` | ||
} | ||
] | ||
}); | ||
done(); | ||
}); | ||
expect.assertions(1); | ||
}); | ||
|
||
it("with alias", done => { | ||
const link = ApolloLink.from([ | ||
withScalars({ schema, validateEnums: true }), | ||
new ApolloLink(() => { | ||
return Observable.of(badNullsWithAliasResponse); | ||
}) | ||
]); | ||
|
||
const observable = execute(link, request); | ||
observable.subscribe(value => { | ||
expect(value).toEqual({ | ||
errors: [ | ||
{ | ||
message: `non-null field "second" (alias "otherSecond") with null value` | ||
} | ||
] | ||
}); | ||
done(); | ||
}); | ||
expect.assertions(1); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.