Skip to content

Commit

Permalink
feat(subscriptions): add support for subscriptions.
Browse files Browse the repository at this point in the history
closes #79
  • Loading branch information
Mayank1791989 committed Dec 9, 2017
1 parent e12f262 commit 2da1800
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 2 deletions.
14 changes: 14 additions & 0 deletions src/__test-data__/schema/subscription.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type Subscription {
# Like story subscription
LikeStory(input: LikeStorySubscriptionInput): LikeStorySubscriptionPayload
}

input LikeStorySubscriptionInput {
clientSubscriptionId: String
id: ID!
}

type LikeStorySubscriptionPayload {
clientSubscriptionId: String
doesViewerLike: Boolean
}
64 changes: 64 additions & 0 deletions src/__test-data__/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,27 @@ export function getDefLocations() {
path: path.resolve('src/__test-data__/schema/mutation.gql'),
},

Subscription: {
start: { line: 1, column: 1 },
end: { line: 4, column: 2 },
path: path.resolve('src/__test-data__/schema/subscription.gql'),
},
Subscription_LikeStory: { // eslint-disable-line camelcase
start: { line: 3, column: 3 },
end: { line: 3, column: 77 },
path: path.resolve('src/__test-data__/schema/subscription.gql'),
},
Subscription_LikeStorySubscriptionInput: { // eslint-disable-line camelcase
start: { line: 6, column: 1 },
end: { line: 9, column: 2 },
path: path.resolve('src/__test-data__/schema/subscription.gql'),
},
Subscription_LikeStorySubscriptionInput_id: { // eslint-disable-line camelcase
start: { line: 8, column: 3 },
end: { line: 8, column: 10 },
path: path.resolve('src/__test-data__/schema/subscription.gql'),
},

Query: {
start: { line: 2, column: 1 },
end: { line: 6, column: 2 },
Expand Down Expand Up @@ -213,6 +234,16 @@ export function getHints() {
text: 'NewPlayer',
type: 'Object',
},
{
description: '',
text: 'Subscription',
type: 'Object',
},
{
description: '',
text: 'LikeStorySubscriptionPayload',
type: 'Object',
},
],

OutputTypes: [
Expand Down Expand Up @@ -276,6 +307,16 @@ export function getHints() {
text: 'CustomScalar',
type: 'Scalar',
},
{
description: '',
text: 'Subscription',
type: 'Object',
},
{
description: '',
text: 'LikeStorySubscriptionPayload',
type: 'Object',
},
{
description: '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.',
text: 'String',
Expand Down Expand Up @@ -354,6 +395,16 @@ export function getHints() {
text: 'Entity',
type: 'Union',
},
{
description: '',
text: 'Subscription',
type: 'Object',
},
{
description: '',
text: 'LikeStorySubscriptionPayload',
type: 'Object',
},
],

InputTypes: [
Expand All @@ -372,6 +423,11 @@ export function getHints() {
text: 'CustomScalar',
type: 'Scalar',
},
{
description: '',
text: 'LikeStorySubscriptionInput',
type: 'Input',
},
{
description: '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.',
text: 'String',
Expand Down Expand Up @@ -464,6 +520,14 @@ export function getHints() {
},
],

PossibleSubscriptions: [
{
description: 'Like story subscription',
text: 'LikeStory',
type: 'LikeStorySubscriptionPayload',
},
],

QueryFields: [
{
description: '',
Expand Down
2 changes: 2 additions & 0 deletions src/query/_shared/Parsers/QueryParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ const parserOptions = {
return 'Query';
case 'mutation':
return 'Mutation';
case 'subscription':
return 'Subscription';
case 'fragment':
return 'FragmentDefinition';
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,13 @@ Array [
},
]
`;

exports[`subscription field args 1`] = `
Array [
Object {
"description": "",
"text": "input",
"type": "LikeStorySubscriptionInput",
},
]
`;
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,40 @@ type Query {
],
}
`;

exports[`subscriptions field: Include both input and output type 1`] = `
Object {
"contents": Array [
"# Like story subscription
(field) LikeStory(input: LikeStorySubscriptionInput): LikeStorySubscriptionPayload",
"input LikeStorySubscriptionInput {
clientSubscriptionId: String
id: ID!
}",
"type LikeStorySubscriptionPayload {
clientSubscriptionId: String
doesViewerLike: Boolean
}",
],
}
`;

exports[`subscriptions input object fields 1`] = `
Object {
"contents": Array [
"(field) id: ID!",
"# The \`ID\` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as \`\\"4\\"\`) or integer (such as \`4\`) input value will be accepted as an ID.",
],
}
`;

exports[`subscriptions type: include description 1`] = `
Object {
"contents": Array [
"type Subscription {
# Like story subscription
LikeStory(input: LikeStorySubscriptionInput): LikeStorySubscriptionPayload
}",
],
}
`;
45 changes: 44 additions & 1 deletion src/query/commands/__tests__/getDefinitionAtPosition.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,5 +283,48 @@ describe('getDef', () => {
).toEqual(null);
});
});
});

describe('subscriptions', () => {
it('subscription keyword', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
subscription { LikeStory }
#--^
\`
`);
expect(
getDefinitionAtPosition(schema, sourceText, position, relayQLParser),
).toEqual(defLocations.Subscription);
});

it('field', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
subscription { LikeStory }
#----------^
\`
`);
expect(
getDefinitionAtPosition(schema, sourceText, position, relayQLParser),
).toEqual(defLocations.Subscription_LikeStory);
});

it('input object fields', () => {
const { sourceText, position } = code(`
subscription {
LikeStory(
input: {
id: "some_id",
#----^
}
) {
clientSubscriptionId
}
}
`);
expect(
getDefinitionAtPosition(schema, sourceText, position, 'QueryParser'),
).toEqual(defLocations.Subscription_LikeStorySubscriptionInput_id);
});
});
});
27 changes: 27 additions & 0 deletions src/query/commands/__tests__/getHintsAtPosition.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,30 @@ describe('show meta field __typename in abstract types', () => {
).toMatchSnapshot();
});
});

describe('subscription', () => {
it('fields', () => {
const { sourceText, position } = code(`
Relay.QL\`
subscription { }
--------------^
\`;
`);
expect(
getHintsAtPosition(schema, sourceText, position, relayConfig),
).toEqual(hints.PossibleSubscriptions);
});

it('field args', () => {
const { sourceText, position } = code(`
subscription {
LikeStory()
----------^
}
`);
expect(
getHintsAtPosition(schema, sourceText, position, queryConfig),
).toMatchSnapshot();
});
});

48 changes: 48 additions & 0 deletions src/query/commands/__tests__/getInfoOfTokenAtPosition.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,54 @@ describe('mutations', () => {
});
});

describe('subscriptions', () => {
it('type: include description', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
subscription {
#-----^
}
\`
`);
expect(
getInfoOfTokenAtPosition(schema, sourceText, position, relayQLParser),
).toMatchSnapshot();
});

it('field: Include both input and output type', () => {
const { sourceText, position } = code(`
const a = Relay.QL\`
subscription {
LikeStory
#-----^
}
\`
`);
expect(
getInfoOfTokenAtPosition(schema, sourceText, position, relayQLParser),
).toMatchSnapshot();
});

it('input object fields', () => {
const { sourceText, position } = code(`
subscription {
LikeStory(
input: {
id: ,
#----^
}
) {
clientSubscriptionId
}
}
`);
expect(
getInfoOfTokenAtPosition(schema, sourceText, position, { parser: 'QueryParser' }),
).toMatchSnapshot();
});
});


describe('query', () => {
it('query keyword', () => {
const { sourceText, position } = code(`
Expand Down
1 change: 1 addition & 0 deletions src/query/commands/getDefinitionAtPosition.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function getDefinitionAtPosition(
(state.kind === 'NamedType' && state.step === 0) ||
(state.kind === 'TypeCondition' && state.step === 1) || // fragment on TypeName <----
(state.kind === 'Mutation' && state.step === 0) || // ----> mutation { }
(state.kind === 'Subscription' && state.step === 0) || // ----> subscription { }
(state.kind === 'Query' && state.step === 0) // ----> query xyz { xyz }
) {
if (typeInfo.type) {
Expand Down
3 changes: 2 additions & 1 deletion src/query/commands/getInfoOfTokenAtPosition.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ function getInfoOfTokenAtPosition( // eslint-disable-line complexity
(kind === 'NamedType' && step === 0) ||
(kind === 'TypeCondition' && step === 1) || // fragment on TypeName <----
(kind === 'Mutation' && step === 0) || // ----> mutation { }
(kind === 'Subscription' && step === 0) || // ----> subscription { }
(kind === 'Query' && step === 0) // ----> query xyz { xyz }
) {
if (typeInfo.type) {
Expand All @@ -57,7 +58,7 @@ function getInfoOfTokenAtPosition( // eslint-disable-line complexity

contents.push(fieldDef.print());

if (typeInfo.parentType && typeInfo.parentType.name === 'Mutation') {
if (typeInfo.parentType && (typeInfo.parentType.name === 'Mutation' || typeInfo.parentType.name === 'Subscription')) {
// include input args type
fieldDef.args.forEach((arg) => {
const argType = getNamedType(arg.type);
Expand Down

0 comments on commit 2da1800

Please # to comment.