Skip to content

Commit

Permalink
Add MutationOptions config option implementation. Add and update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
eddeee888 committed Jul 15, 2019
1 parent 9fc204f commit 0f84fcb
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 3 deletions.
19 changes: 19 additions & 0 deletions packages/plugins/typescript/react-apollo/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,25 @@ export interface ReactApolloRawPluginConfig extends RawClientSideBasePluginConfi
* ```
*/
withResultType?: boolean;
/**
* @name withMutationOptionsType
* @type boolean
* @description Customized the output by enabling/disabling the generated mutation option type.
* @default true
*
* @example
* ```yml
* generates:
* path/to/file.ts:
* plugins:
* - typescript
* - typescript-operations
* - typescript-react-apollo
* config:
* withMutationOptionsType: true
*
*/
withMutationOptionsType?: boolean;
}

export const plugin: PluginFunction<ReactApolloRawPluginConfig> = (schema: GraphQLSchema, documents: Types.DocumentFile[], config: ReactApolloRawPluginConfig) => {
Expand Down
17 changes: 16 additions & 1 deletion packages/plugins/typescript/react-apollo/src/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface ReactApolloPluginConfig extends ClientSideBasePluginConfig {
componentSuffix: string;
reactApolloVersion: 2 | 3;
withResultType: boolean;
withMutationOptionsType: boolean;
}

export class ReactApolloVisitor extends ClientSideBaseVisitor<ReactApolloRawPluginConfig, ReactApolloPluginConfig> {
Expand All @@ -29,6 +30,7 @@ export class ReactApolloVisitor extends ClientSideBaseVisitor<ReactApolloRawPlug
reactApolloImportFrom: getConfigValue(rawConfig.reactApolloImportFrom, 'react-apollo'),
reactApolloVersion: getConfigValue(rawConfig.reactApolloVersion, 2),
withResultType: getConfigValue(rawConfig.withResultType, true),
withMutationOptionsType: getConfigValue(rawConfig.withMutationOptionsType, true),
} as any);

autoBind(this);
Expand Down Expand Up @@ -160,14 +162,27 @@ export class ReactApolloVisitor extends ClientSideBaseVisitor<ReactApolloRawPlug
}
}

private _buildWithMutationOptionsType(node: OperationDefinitionNode, operationResultType: string, operationVariablesTypes: string): string {
if (node.operation !== 'mutation') {
return '';
}

this.imports.add(this.getReactApolloImport());

const mutationOptionsType = this.convertName(node.name.value, { suffix: 'MutationOptions', useTypesPrefix: false });

return `export type ${mutationOptionsType} = ReactApollo.MutationOptions<${operationResultType}, ${operationVariablesTypes}>;`;
}

protected buildOperation(node: OperationDefinitionNode, documentVariableName: string, operationType: string, operationResultType: string, operationVariablesTypes: string): string {
const mutationFn = this.config.withMutationFn || this.config.withComponent ? this._buildMutationFn(node, operationResultType, operationVariablesTypes) : null;
const component = this.config.withComponent ? this._buildComponent(node, documentVariableName, operationType, operationResultType, operationVariablesTypes) : null;
const hoc = this.config.withHOC ? this._buildOperationHoc(node, documentVariableName, operationResultType, operationVariablesTypes) : null;
const hooks = this.config.withHooks ? this._buildHooks(node, operationType, documentVariableName, operationResultType, operationVariablesTypes) : null;
const resultType = this.config.withResultType ? this._buildResultType(node, operationType, operationResultType, operationVariablesTypes) : null;
const mutationOptionsType = this.config.withMutationOptionsType ? this._buildWithMutationOptionsType(node, operationResultType, operationVariablesTypes) : null;

return [mutationFn, component, hoc, hooks, resultType].filter(a => a).join('\n');
return [mutationFn, component, hoc, hooks, resultType, mutationOptionsType].filter(a => a).join('\n');
}
}

Expand Down
132 changes: 130 additions & 2 deletions packages/plugins/typescript/react-apollo/tests/react-apollo.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { validateTs } from '@graphql-codegen/testing';
import { plugin } from '../src/index';
import { plugin, ReactApolloRawPluginConfig } from '../src/index';
import { parse, GraphQLSchema, buildClientSchema, buildASTSchema } from 'graphql';
import gql from 'graphql-tag';
import { Types, mergeOutputs } from '@graphql-codegen/plugin-helpers';
Expand Down Expand Up @@ -831,12 +831,13 @@ export function useListenToCommentsSubscription(baseOptions?: ReactApolloHooks.S
});

describe('ResultType', () => {
const config = {
const config: ReactApolloRawPluginConfig = {
withHOC: false,
withComponent: false,
withHooks: false,
withMutationFn: false,
withResultType: true,
withMutationOptionsType: false,
};

it('should generate ResultType for Query', async () => {
Expand Down Expand Up @@ -904,4 +905,131 @@ export function useListenToCommentsSubscription(baseOptions?: ReactApolloHooks.S
await validateTypeScript(content, schema, docs, {});
});
});

describe('MutationOptions', () => {
const config: ReactApolloRawPluginConfig = {
withHOC: false,
withComponent: false,
withHooks: false,
withMutationFn: false,
withResultType: false,
withMutationOptionsType: true,
};

const mutationDoc = parse(/* GraphQL */ `
mutation test($name: String) {
submitRepository(repoFullName: $name) {
id
}
}
`);

const subscriptionDoc = parse(/* GraphQL */ `
subscription test($name: String) {
commentAdded(repoFullName: $name) {
id
}
}
`);

it('should generate MutationOptions for Mutation if withMutationOptionsType is true', async () => {
const docs = [{ filePath: '', content: mutationDoc }];

const content = (await plugin(
schema,
docs,
{ ...config },
{
outputFile: 'graphql.tsx',
}
)) as Types.ComplexPluginOutput;

expect(content.prepend).toContain(`import * as ReactApollo from 'react-apollo';`);
expect(content.content).toContain(`export type TestMutationOptions = ReactApollo.MutationOptions<TestMutation, TestMutationVariables>;`);
await validateTypeScript(content, schema, docs, {});
});

it('should NOT generate MutationOptions for Mutation if withMutationOptionsType is false', async () => {
const docs = [{ filePath: '', content: mutationDoc }];

const content = (await plugin(
schema,
docs,
{ ...config, withMutationOptionsType: false },
{
outputFile: 'graphql.tsx',
}
)) as Types.ComplexPluginOutput;

expect(content.prepend).not.toContain(`import * as ReactApollo from 'react-apollo';`);
expect(content.content).not.toContain(`export type TestMutationOptions = ReactApollo.MutationOptions<TestMutation, TestMutationVariables>;`);
await validateTypeScript(content, schema, docs, {});
});

it('should NOT generate MutationOptions for Query if withMutationOptionsType is true', async () => {
const docs = [{ filePath: '', content: basicDoc }];
const content = (await plugin(
schema,
docs,
{ ...config },
{
outputFile: 'graphql.tsx',
}
)) as Types.ComplexPluginOutput;

expect(content.prepend).not.toContain(`import * as ReactApollo from 'react-apollo';`);
expect(content.content).not.toContain(`ReactApollo.MutationOptions`);
await validateTypeScript(content, schema, docs, {});
});

it('should NOT generate MutationOptions for Query if withMutationOptionsType is false', async () => {
const docs = [{ filePath: '', content: basicDoc }];
const content = (await plugin(
schema,
docs,
{ ...config, withMutationOptionsType: false },
{
outputFile: 'graphql.tsx',
}
)) as Types.ComplexPluginOutput;

expect(content.prepend).not.toContain(`import * as ReactApollo from 'react-apollo';`);
expect(content.content).not.toContain(`ReactApollo.MutationOptions`);
await validateTypeScript(content, schema, docs, {});
});

it('should NOT generate MutationOptions for Subscription if withMutationOptionsType is true', async () => {
const docs = [{ filePath: '', content: subscriptionDoc }];

const content = (await plugin(
schema,
docs,
{ ...config },
{
outputFile: 'graphql.tsx',
}
)) as Types.ComplexPluginOutput;

expect(content.prepend).not.toContain(`import * as ReactApollo from 'react-apollo';`);
expect(content.content).not.toContain(`ReactApollo.MutationOptions`);
await validateTypeScript(content, schema, docs, {});
});

it('should NOT generate MutationOptions for Subscription if withMutationOptionsType is false', async () => {
const docs = [{ filePath: '', content: subscriptionDoc }];

const content = (await plugin(
schema,
docs,
{ ...config, withMutationOptionsType: false },
{
outputFile: 'graphql.tsx',
}
)) as Types.ComplexPluginOutput;

expect(content.prepend).not.toContain(`import * as ReactApollo from 'react-apollo';`);
expect(content.content).not.toContain(`ReactApollo.MutationOptions`);
await validateTypeScript(content, schema, docs, {});
});
});
});

0 comments on commit 0f84fcb

Please sign in to comment.