Skip to content

Commit

Permalink
Enable schemaDescription & inputTypeDeprecation (#2077)
Browse files Browse the repository at this point in the history
- Include schema description in DocExplorer for schema introspection requests. Enables the `schemaDescription` option for `getIntrospectionQuery()`.
- Also includes `deprecationReason` support in DocExplorer for arguments! 
- Enables `inputValueDeprecation` in `getIntrospectionQuery()` and displays deprecation section on field doc view.
  • Loading branch information
acao committed Dec 4, 2021
1 parent fe5bb0d commit 701ca13
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 22 deletions.
7 changes: 7 additions & 0 deletions .changeset/smooth-elephants-eat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'graphiql': patch
---

Include schema description in DocExplorer for schema introspection requests. Enables the `schemaDescription` option for `getIntrospectionQuery()`.
Also includes `deprecationReason` support in DocExplorer for arguments!
Enables `inputValueDeprecation` in `getIntrospectionQuery()` and displays deprecation section on field doc view.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"release:canary": "(node scripts/canary-release.js && yarn build && yarn build-bundles && yarn changeset publish --tag canary) || echo Skipping Canary...",
"repo:lint": "manypkg check",
"repo:fix": "manypkg fix",
"start-graphiql": "yarn build:clean && npm-run-all -l -p build dev-graphiql",
"start-graphiql": "yarn workspace graphiql dev",
"start-monaco": "yarn workspace example-monaco-graphql-webpack start",
"t": "yarn run testonly",
"test": "yarn jest",
Expand Down
8 changes: 8 additions & 0 deletions packages/graphiql/cypress/integration/docs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,12 @@ describe('GraphQL DocExplorer - deprecated fields', () => {
'<p>No longer in use, try <code>test</code> instead.</p>',
);
});
it('should show deprecated arguments category title', () => {
cy.get('#doc-fields .doc-category-item a.field-name').last().click();
cy.get('#doc-deprecated-args>.doc-category-title')
.last()
.should('have.text', 'deprecated arguments');
cy.get('.show-btn').click();
cy.get('.doc-deprecation').should('have.text', 'deprecated argument\n');
});
});
70 changes: 58 additions & 12 deletions packages/graphiql/src/components/DocExplorer/FieldDoc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,69 @@ type FieldDocProps = {
};

export default function FieldDoc({ field, onClickType }: FieldDocProps) {
const [showDeprecated, handleShowDeprecated] = React.useState(false);
let argsDef;
let deprecatedArgsDef;
if (field && 'args' in field && field.args.length > 0) {
argsDef = (
<div className="doc-category">
<div id="doc-args" className="doc-category">
<div className="doc-category-title">{'arguments'}</div>
{field.args.map((arg: GraphQLArgument) => (
<div key={arg.name} className="doc-category-item">
<div>
<Argument arg={arg} onClickType={onClickType} />
{field.args
.filter(arg => !arg.deprecationReason)
.map((arg: GraphQLArgument) => (
<div key={arg.name} className="doc-category-item">
<div>
<Argument arg={arg} onClickType={onClickType} />
</div>
<MarkdownContent
className="doc-value-description"
markdown={arg.description}
/>
{arg && 'deprecationReason' in arg && (
<MarkdownContent
className="doc-deprecation"
markdown={arg?.deprecationReason}
/>
)}
</div>
<MarkdownContent
className="doc-value-description"
markdown={arg.description}
/>
</div>
))}
))}
</div>
);
const deprecatedArgs = field.args.filter(arg =>
Boolean(arg.deprecationReason),
);
if (deprecatedArgs.length > 0) {
deprecatedArgsDef = (
<div id="doc-deprecated-args" className="doc-category">
<div className="doc-category-title">{'deprecated arguments'}</div>
{!showDeprecated ? (
<button
className="show-btn"
onClick={() => handleShowDeprecated(!showDeprecated)}>
{'Show deprecated arguments...'}
</button>
) : (
deprecatedArgs.map((arg, i) => (
<div key={i}>
<div>
<Argument arg={arg} onClickType={onClickType} />
</div>
<MarkdownContent
className="doc-value-description"
markdown={arg.description}
/>
{arg && 'deprecationReason' in arg && (
<MarkdownContent
className="doc-deprecation"
markdown={arg?.deprecationReason}
/>
)}
</div>
))
)}
</div>
);
}
}

let directivesDef;
Expand All @@ -47,7 +92,7 @@ export default function FieldDoc({ field, onClickType }: FieldDocProps) {
field.astNode.directives.length > 0
) {
directivesDef = (
<div className="doc-category">
<div id="doc-directives" className="doc-category">
<div className="doc-category-title">{'directives'}</div>
{field.astNode.directives.map((directive: DirectiveNode) => (
<div key={directive.name.value} className="doc-category-item">
Expand Down Expand Up @@ -78,6 +123,7 @@ export default function FieldDoc({ field, onClickType }: FieldDocProps) {
</div>
{argsDef}
{directivesDef}
{deprecatedArgsDef}
</div>
);
}
14 changes: 8 additions & 6 deletions packages/graphiql/src/components/DocExplorer/TypeDoc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default class TypeDoc extends React.Component<
let typesDef;
if (types && types.length > 0) {
typesDef = (
<div className="doc-category">
<div id="doc-types" className="doc-category">
<div className="doc-category-title">{typesTitle}</div>
{types.map(subtype => (
<div key={subtype.name} className="doc-category-item">
Expand All @@ -90,7 +90,7 @@ export default class TypeDoc extends React.Component<
const fieldMap = type.getFields();
const fields = Object.keys(fieldMap).map(name => fieldMap[name]);
fieldsDef = (
<div className="doc-category">
<div id="doc-fields" className="doc-category">
<div className="doc-category-title">{'fields'}</div>
{fields
.filter(field => !field.deprecationReason)
Expand All @@ -111,7 +111,7 @@ export default class TypeDoc extends React.Component<
);
if (deprecatedFields.length > 0) {
deprecatedFieldsDef = (
<div className="doc-category">
<div id="doc-deprecated-fields" className="doc-category">
<div className="doc-category-title">{'deprecated fields'}</div>
{!this.state.showDeprecated ? (
<button className="show-btn" onClick={this.handleShowDeprecated}>
Expand Down Expand Up @@ -210,9 +210,11 @@ function Field({ type, field, onClickType, onClickField }: FieldProps) {
field.args.length > 0 && [
'(',
<span key="args">
{field.args.map(arg => (
<Argument key={arg.name} arg={arg} onClickType={onClickType} />
))}
{field.args
.filter(arg => !arg.deprecationReason)
.map(arg => (
<Argument key={arg.name} arg={arg} onClickType={onClickType} />
))}
</span>,
')',
]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import React from 'react';
import { render } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';

import FieldDoc from '../FieldDoc';

Expand All @@ -28,6 +28,11 @@ const exampleObject = new GraphQLObjectType({
name: 'stringArg',
type: GraphQLString,
},
deprecatedStringArg: {
name: 'deprecatedStringArg',
type: GraphQLString,
deprecationReason: 'no longer used',
},
},
},
stringWithDirective: {
Expand Down Expand Up @@ -115,6 +120,13 @@ describe('FieldDoc', () => {
expect(container.querySelector('.arg')).toHaveTextContent(
'stringArg: String',
);
// by default, the deprecation docs should be hidden
expect(container.querySelectorAll('.doc-deprecation')).toHaveLength(0);
// make sure deprecation is present
fireEvent.click(container.querySelector('.show-btn'));
const deprecationDocs = container.querySelectorAll('.doc-deprecation');
expect(deprecationDocs).toHaveLength(1);
expect(deprecationDocs[0]).toHaveTextContent('no longer used');
});

it('should render a string field with directives', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,8 @@ describe('DocExplorer', () => {
const { container } = render(<DocExplorer schema={ExampleSchema} />);
const error = container.querySelectorAll('.error-container');
expect(error).toHaveLength(0);
expect(container.querySelector('.doc-type-description')).toHaveTextContent(
'GraphQL Schema for testing',
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,5 @@ export const ExampleQuery = new GraphQLObjectType({

export const ExampleSchema = new GraphQLSchema({
query: ExampleQuery,
description: 'GraphQL Schema for testing',
});
6 changes: 5 additions & 1 deletion packages/graphiql/src/utility/introspectionQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@

import { getIntrospectionQuery } from 'graphql';

export const introspectionQuery = getIntrospectionQuery();
export const introspectionQuery = getIntrospectionQuery({
schemaDescription: true,
inputValueDeprecation: true,
specifiedByUrl: true,
});

export const staticName = 'IntrospectionQuery';

Expand Down
8 changes: 7 additions & 1 deletion packages/graphiql/test/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ const TestType = new GraphQLObjectType({
return JSON.stringify(args);
},
args: {
string: { type: GraphQLString },
string: { type: GraphQLString, description: 'A string' },
int: { type: GraphQLInt },
float: { type: GraphQLFloat },
boolean: { type: GraphQLBoolean },
Expand All @@ -301,6 +301,11 @@ const TestType = new GraphQLObjectType({
listID: { type: new GraphQLList(GraphQLID) },
listEnum: { type: new GraphQLList(TestEnum) },
listObject: { type: new GraphQLList(TestInputObject) },
deprecatedArg: {
type: GraphQLString,
deprecationReason: 'deprecated argument',
description: 'Hello!',
},
},
},
}),
Expand Down Expand Up @@ -347,6 +352,7 @@ const myTestSchema = new GraphQLSchema({
query: TestType,
mutation: TestMutationType,
subscription: TestSubscriptionType,
description: 'This is a test schema for GraphiQL',
});

module.exports = myTestSchema;

2 comments on commit 701ca13

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.