Skip to content

Commit

Permalink
fix(query): fix getInfo crashing for meta fields
Browse files Browse the repository at this point in the history
  • Loading branch information
Mayank1791989 committed May 15, 2017
1 parent c7bb3f3 commit a625b51
Show file tree
Hide file tree
Showing 7 changed files with 282 additions and 11 deletions.
8 changes: 4 additions & 4 deletions src/query/_shared/getTypeInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ import {
getNullableType,
GraphQLList,
isCompositeType,

SchemaMetaFieldDef,
TypeMetaFieldDef,
TypeNameMetaFieldDef,
} from 'graphql/type';

import {
Expand All @@ -22,6 +18,10 @@ import {
type GQLType,
type GQLNamedType,
type GQLSchema,

SchemaMetaFieldDef,
TypeMetaFieldDef,
TypeNameMetaFieldDef,
} from '../../shared/GQLTypes';

type Info = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,28 @@ Array [
},
]
`;

exports[`show meta field __typename in abstract types interface type 1`] = `
Array [
Object {
"description": "",
"text": "id",
"type": "ID!",
},
Object {
"description": "The name of the current Object type at runtime.",
"text": "__typename",
"type": "String!",
},
]
`;

exports[`show meta field __typename in abstract types union type 1`] = `
Array [
Object {
"description": "The name of the current Object type at runtime.",
"text": "__typename",
"type": "String!",
},
]
`;
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,101 @@ Object {
}
`;

exports[`meta field __schema 1`] = `
Object {
"contents": Array [
"# Access the current type schema of this server.
(meta-field) __schema: __Schema!",
"# A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all
# available types and directives on the server, as well as the entry points for
# query, mutation, and subscription operations.
type __Schema {
# A list of all types supported by this server.
types: [__Type!]!
# The type that query operations will be rooted at.
queryType: __Type!
# If this server supports mutation, the type that mutation operations will be rooted at.
mutationType: __Type
# If this server support subscription, the type that subscription operations will be rooted at.
subscriptionType: __Type
# A list of all directives supported by this server.
directives: [__Directive!]!
}",
],
}
`;

exports[`meta field __type 1`] = `
Object {
"contents": Array [
"# Request the type information of a single type.
(meta-field) __type(name: String!): __Type",
"# The fundamental unit of any GraphQL Schema is the type. There are many kinds of
# types in GraphQL as represented by the \`__TypeKind\` enum.
#
# Depending on the kind of a type, certain fields describe information about that
# type. Scalar types provide no information beyond a name and description, while
# Enum types provide their values. Object and Interface types provide the fields
# they describe. Abstract types, Union and Interface, provide the Object types
# possible at runtime. List and NonNull types compose other types.
type __Type {
kind: __TypeKind!
name: String
description: String
fields(includeDeprecated: Boolean = false): [__Field!]
interfaces: [__Type!]
possibleTypes: [__Type!]
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
inputFields: [__InputValue!]
ofType: __Type
}",
],
}
`;

exports[`meta field __typename when inside Interface Type 1`] = `
Object {
"contents": Array [
"# The name of the current Object type at runtime.
(meta-field) __typename: String!",
"# The \`String\` scalar type represents textual data, represented as UTF-8 character
# sequences. The String type is most often used by GraphQL to represent free-form
# human-readable text.
scalar String",
],
}
`;

exports[`meta field __typename when inside Object Type 1`] = `
Object {
"contents": Array [
"# The name of the current Object type at runtime.
(meta-field) __typename: String!",
"# The \`String\` scalar type represents textual data, represented as UTF-8 character
# sequences. The String type is most often used by GraphQL to represent free-form
# human-readable text.
scalar String",
],
}
`;

exports[`meta field __typename when inside Union Type 1`] = `
Object {
"contents": Array [
"# The name of the current Object type at runtime.
(meta-field) __typename: String!",
"# The \`String\` scalar type represents textual data, represented as UTF-8 character
# sequences. The String type is most often used by GraphQL to represent free-form
# human-readable text.
scalar String",
],
}
`;

exports[`mutations field: Include both input and output type 1`] = `
Object {
"contents": Array [
Expand Down
32 changes: 32 additions & 0 deletions src/query/commands/__tests__/getHintsAtPosition.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,35 @@ describe('directives', () => {
).toMatchSnapshot();
});
});


describe('show meta field __typename in abstract types', () => {
it('interface type', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
fragment on Node {
id
__type
#-------^
}
\`
`);
expect(
getHintsAtPosition(schema, sourceText, position, relayConfig),
).toMatchSnapshot();
});

it('union type', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
fragment on Entity {
__type
#-------^
}
\`
`);
expect(
getHintsAtPosition(schema, sourceText, position, relayConfig),
).toMatchSnapshot();
});
});
71 changes: 71 additions & 0 deletions src/query/commands/__tests__/getInfoOfTokenAtPosition.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,74 @@ describe('query', () => {
).toMatchSnapshot();
});
});

describe('meta field __typename', () => {
it('when inside Object Type', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
fragment on Viewer {
__typename
#----^
}
\`
`);
expect(
getInfoOfTokenAtPosition(schema, sourceText, position, relayQLParser),
).toMatchSnapshot();
});
it('when inside Interface Type', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
fragment on Node {
__typename
#----^
}
\`
`);
expect(
getInfoOfTokenAtPosition(schema, sourceText, position, relayQLParser),
).toMatchSnapshot();
});
it('when inside Union Type', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
fragment on Entity {
__typename
#----^
}
\`
`);
expect(
getInfoOfTokenAtPosition(schema, sourceText, position, relayQLParser),
).toMatchSnapshot();
});
});

test('meta field __schema', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
query Viewer {
__schema
#----^
}
\`
`);
expect(
getInfoOfTokenAtPosition(schema, sourceText, position, relayQLParser),
).toMatchSnapshot();
});

test('meta field __type', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
query Viewer {
__type
#--^
}
\`
`);
expect(
getInfoOfTokenAtPosition(schema, sourceText, position, relayQLParser),
).toMatchSnapshot();
});

8 changes: 4 additions & 4 deletions src/query/commands/getHintsAtPosition.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import {
GQLEnumType,
getNamedType,
type GQLSchema,

SchemaMetaFieldDef,
TypeMetaFieldDef,
TypeNameMetaFieldDef,
} from '../../shared/GQLTypes';
import { type QueryParser } from '../../config/GQLConfig';
import getTokenAtPosition from '../_shared/getTokenAtPosition';
Expand All @@ -19,10 +23,6 @@ import {

isInputType,
isCompositeType,

SchemaMetaFieldDef,
TypeMetaFieldDef,
TypeNameMetaFieldDef,
} from 'graphql/type';

import getTypeInfo from '../_shared/getTypeInfo';
Expand Down
54 changes: 51 additions & 3 deletions src/shared/GQLTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,17 @@ import {
GraphQLObjectType,
GraphQLSkipDirective,
GraphQLDirective,
GraphqlField,

SchemaMetaFieldDef as _SchemaMetaFieldDef,
TypeMetaFieldDef as _TypeMetaFieldDef,
TypeNameMetaFieldDef as _TypeNameMetaFieldDef,
} from 'graphql/type';

import { printType } from 'graphql/utilities/schemaPrinter';

import _keyBy from 'lodash/keyBy';

import {
type TypeDefinitionNode,
type FieldDefinitionNode,
Expand Down Expand Up @@ -48,7 +57,7 @@ export type GQLField = {
resolve?: any,
isDeprecated?: boolean,
deprecationReason?: ?string,
node: FieldDefinitionNode,
node: ?FieldDefinitionNode,
print: () => string,
};

Expand Down Expand Up @@ -132,15 +141,16 @@ function print(node: ?ASTNode, description: ?string, type: ?string): string {
].filter(Boolean).join('\n');
}

function patchFields(fields) {
Object.keys(fields).forEach((name) => {
function patchFields(fields: Array<GraphqlField>): Array<GQLField> {
return Object.keys(fields).map((name) => {
const field = fields[name];
field.print = memoize(() => print(field.node, field.description, 'field'));
field.args = field.args.map((arg, index) => ({
...arg,
node: field.node.arguments[index],
print: memoize(() => print(field.node.arguments[index], arg.description, 'argument')),
}));
return field;
});
}

Expand All @@ -166,6 +176,44 @@ GQLFloat.print = () => printDescription(GQLFloat.description);
export const GQLBoolean: GQLScalarType = GraphQLBoolean;
GQLBoolean.print = () => printDescription(GQLBoolean.description);

const [SchemaMetaFieldDef, TypeMetaFieldDef, TypeNameMetaFieldDef] = [
_SchemaMetaFieldDef,
_TypeMetaFieldDef,
_TypeNameMetaFieldDef,
].map(field => {
const type = getNamedType(field.type);
type.print = memoize(() => printType(type));

return {
...field,
print: memoize(() => {
// HACK: graphql doesnt expose printField method
// so creating fake type and printing it and extracting field string
const printedType = printType(
new GraphQLObjectType({
name: 'Demo',
fields: {
FIELD_NAME: {
...field,
args: Array.isArray(field.args)
? _keyBy(field.args, 'name')
: field.args,
},
},
}),
).replace('FIELD_NAME', `(meta-field) ${field.name}`);

const lines = printedType.split('\n');
return lines
.slice(1, lines.length - 1) // remove first and last line which is type we need field only
.map(line => line.trim())
.join('\n');
}),
};
});

export { SchemaMetaFieldDef, TypeMetaFieldDef, TypeNameMetaFieldDef };

function printArg(arg, indentation = '') {
return [
`${indentation}${printDescription(arg.description)}`,
Expand Down

0 comments on commit a625b51

Please sign in to comment.