apollo-utilities
Version:
Utilities for working with GraphQL ASTs
317 lines (283 loc) • 8.01 kB
text/typescript
import { print } from 'graphql/language/printer';
import gql from 'graphql-tag';
import { FragmentDefinitionNode, OperationDefinitionNode } from 'graphql';
import {
checkDocument,
getFragmentDefinitions,
getQueryDefinition,
getMutationDefinition,
createFragmentMap,
FragmentMap,
getDefaultValues,
getOperationName,
} from '../getFromAST';
describe('AST utility functions', () => {
it('should correctly check a document for correctness', () => {
const multipleQueries = gql`
query {
author {
firstName
lastName
}
}
query {
author {
address
}
}
`;
expect(() => {
checkDocument(multipleQueries);
}).toThrow();
const namedFragment = gql`
query {
author {
...authorDetails
}
}
fragment authorDetails on Author {
firstName
lastName
}
`;
expect(() => {
checkDocument(namedFragment);
}).not.toThrow();
});
it('should get fragment definitions from a document containing a single fragment', () => {
const singleFragmentDefinition = gql`
query {
author {
...authorDetails
}
}
fragment authorDetails on Author {
firstName
lastName
}
`;
const expectedDoc = gql`
fragment authorDetails on Author {
firstName
lastName
}
`;
const expectedResult: FragmentDefinitionNode[] = [
expectedDoc.definitions[0] as FragmentDefinitionNode,
];
const actualResult = getFragmentDefinitions(singleFragmentDefinition);
expect(actualResult.length).toEqual(expectedResult.length);
expect(print(actualResult[0])).toBe(print(expectedResult[0]));
});
it('should get fragment definitions from a document containing a multiple fragments', () => {
const multipleFragmentDefinitions = gql`
query {
author {
...authorDetails
...moreAuthorDetails
}
}
fragment authorDetails on Author {
firstName
lastName
}
fragment moreAuthorDetails on Author {
address
}
`;
const expectedDoc = gql`
fragment authorDetails on Author {
firstName
lastName
}
fragment moreAuthorDetails on Author {
address
}
`;
const expectedResult: FragmentDefinitionNode[] = [
expectedDoc.definitions[0] as FragmentDefinitionNode,
expectedDoc.definitions[1] as FragmentDefinitionNode,
];
const actualResult = getFragmentDefinitions(multipleFragmentDefinitions);
expect(actualResult.map(print)).toEqual(expectedResult.map(print));
});
it('should get the correct query definition out of a query containing multiple fragments', () => {
const queryWithFragments = gql`
fragment authorDetails on Author {
firstName
lastName
}
fragment moreAuthorDetails on Author {
address
}
query {
author {
...authorDetails
...moreAuthorDetails
}
}
`;
const expectedDoc = gql`
query {
author {
...authorDetails
...moreAuthorDetails
}
}
`;
const expectedResult: OperationDefinitionNode = expectedDoc
.definitions[0] as OperationDefinitionNode;
const actualResult = getQueryDefinition(queryWithFragments);
expect(print(actualResult)).toEqual(print(expectedResult));
});
it('should throw if we try to get the query definition of a document with no query', () => {
const mutationWithFragments = gql`
fragment authorDetails on Author {
firstName
lastName
}
mutation {
createAuthor(firstName: "John", lastName: "Smith") {
...authorDetails
}
}
`;
expect(() => {
getQueryDefinition(mutationWithFragments);
}).toThrow();
});
it('should get the correct mutation definition out of a mutation with multiple fragments', () => {
const mutationWithFragments = gql`
mutation {
createAuthor(firstName: "John", lastName: "Smith") {
...authorDetails
}
}
fragment authorDetails on Author {
firstName
lastName
}
`;
const expectedDoc = gql`
mutation {
createAuthor(firstName: "John", lastName: "Smith") {
...authorDetails
}
}
`;
const expectedResult: OperationDefinitionNode = expectedDoc
.definitions[0] as OperationDefinitionNode;
const actualResult = getMutationDefinition(mutationWithFragments);
expect(print(actualResult)).toEqual(print(expectedResult));
});
it('should create the fragment map correctly', () => {
const fragments = getFragmentDefinitions(gql`
fragment authorDetails on Author {
firstName
lastName
}
fragment moreAuthorDetails on Author {
address
}
`);
const fragmentMap = createFragmentMap(fragments);
const expectedTable: FragmentMap = {
authorDetails: fragments[0],
moreAuthorDetails: fragments[1],
};
expect(fragmentMap).toEqual(expectedTable);
});
it('should return an empty fragment map if passed undefined argument', () => {
expect(createFragmentMap(undefined)).toEqual({});
});
it('should get the operation name out of a query', () => {
const query = gql`
query nameOfQuery {
fortuneCookie
}
`;
const operationName = getOperationName(query);
expect(operationName).toEqual('nameOfQuery');
});
it('should get the operation name out of a mutation', () => {
const query = gql`
mutation nameOfMutation {
fortuneCookie
}
`;
const operationName = getOperationName(query);
expect(operationName).toEqual('nameOfMutation');
});
it('should return null if the query does not have an operation name', () => {
const query = gql`
{
fortuneCookie
}
`;
const operationName = getOperationName(query);
expect(operationName).toEqual(null);
});
it('should throw if type definitions found in document', () => {
const queryWithTypeDefination = gql`
fragment authorDetails on Author {
firstName
lastName
}
query($search: AuthorSearchInputType) {
author(search: $search) {
...authorDetails
}
}
input AuthorSearchInputType {
firstName: String
}
`;
expect(() => {
getQueryDefinition(queryWithTypeDefination);
}).toThrowError(
'Schema type definitions not allowed in queries. Found: "InputObjectTypeDefinition"',
);
});
describe('getDefaultValues', () => {
it('will create an empty variable object if no default values are provided', () => {
const basicQuery = gql`
query people($first: Int, $second: String) {
allPeople(first: $first) {
people {
name
}
}
}
`;
expect(getDefaultValues(getQueryDefinition(basicQuery))).toEqual({});
});
it('will create a variable object based on the definition node with default values', () => {
const basicQuery = gql`
query people($first: Int = 1, $second: String!) {
allPeople(first: $first) {
people {
name
}
}
}
`;
const complexMutation = gql`
mutation complexStuff(
$test: Input = { key1: ["value", "value2"], key2: { key3: 4 } }
) {
complexStuff(test: $test) {
people {
name
}
}
}
`;
expect(getDefaultValues(getQueryDefinition(basicQuery))).toEqual({
first: 1,
});
expect(getDefaultValues(getMutationDefinition(complexMutation))).toEqual({
test: { key1: ['value', 'value2'], key2: { key3: 4 } },
});
});
});
});