Skip to content

Commit

Permalink
Use "No longer supported" as the default deprecationReason for deprec…
Browse files Browse the repository at this point in the history
…ations without a reason specified (#2692)

* fix: use "No longer supported" as the default deprecationReason for deprecated fields with no reason specified

* test: add integration tests to ensure deprecated fields with no reason set get the default reason defined in the spec `No longer supported`
  • Loading branch information
arseniocosta1 committed Jun 23, 2023
1 parent 640f383 commit 1a9dbad
Show file tree
Hide file tree
Showing 16 changed files with 121 additions and 17 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/check-integration
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ curl -s --connect-timeout 5 \
--retry-max-time 40 \
--retry-connrefused \
localhost:8080 > /dev/null
echo "### running integration spec"
npm run test


echo "### validating introspected schema"
Expand All @@ -26,3 +24,6 @@ if ! diff <(tail -n +3 src/generated/schema-expected.graphql) <(tail -n +3 src/g
echo "The expected schema has changed, you need to update schema-expected.graphql with any expected changes"
exit 1
fi

echo "### running integration spec"
npm run test
5 changes: 3 additions & 2 deletions _examples/chat/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import (

"github.com/99designs/gqlgen/graphql/playground"

"github.com/99designs/gqlgen/_examples/chat"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/gorilla/websocket"
"github.com/opentracing/opentracing-go"
"github.com/rs/cors"
"sourcegraph.com/sourcegraph/appdash"
appdashtracer "sourcegraph.com/sourcegraph/appdash/opentracing"
"sourcegraph.com/sourcegraph/appdash/traceapp"

"github.com/99designs/gqlgen/_examples/chat"
"github.com/99designs/gqlgen/graphql/handler"
)

func main() {
Expand Down
6 changes: 4 additions & 2 deletions graphql/introspection/introspection.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,15 @@ func (f *Field) IsDeprecated() bool {
}

func (f *Field) DeprecationReason() *string {
if f.deprecation == nil {
if f.deprecation == nil || !f.IsDeprecated() {
return nil
}

reason := f.deprecation.Arguments.ForName("reason")

if reason == nil {
return nil
defaultReason := "No longer supported"
return &defaultReason
}

return &reason.Value.Raw
Expand Down
3 changes: 3 additions & 0 deletions integration/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const config: CodegenConfig = {
'src/generated/schema-fetched.graphql': {
plugins: ['schema-ast'],
},
'src/generated/schema-introspection.json': {
plugins: ['introspection'],
}
},
};

Expand Down
15 changes: 15 additions & 0 deletions integration/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion integration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@
},
"devDependencies": {
"@apollo/client": "^3.7.14",
"urql": "^4.0.3",
"@graphql-codegen/cli": "^4.0.0",
"@graphql-codegen/client-preset": "^4.0.0",
"@graphql-codegen/introspection": "^4.0.0",
"@graphql-codegen/schema-ast": "^4.0.0",
"graphql": "^16.6.0",
"graphql-codegen": "^0.4.0",
"graphql-sse": "^2.1.4",
"graphql-ws": "^5.13.1",
"typescript": "^5.0.2",
"urql": "^4.0.3",
"vite": "^4.3.9",
"vitest": "^0.32.0"
}
Expand Down
57 changes: 55 additions & 2 deletions integration/server/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions integration/server/remote_api/user.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package remote_api

type User struct {
Name string
Likes []string
Name string
Likes []string
PhoneNumber string
}
2 changes: 1 addition & 1 deletion integration/server/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (r *queryResolver) Date(ctx context.Context, filter models.DateFilter) (boo

func (r *queryResolver) Viewer(ctx context.Context) (*models.Viewer, error) {
return &models.Viewer{
User: &remote_api.User{Name: "Bob", Likes: []string{"Alice"}},
User: &remote_api.User{Name: "Bob", Likes: []string{"Alice"}, PhoneNumber: "1234567890"},
}, nil
}

Expand Down
1 change: 1 addition & 0 deletions integration/server/schema/user.graphql
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
type User {
name: String!
likes: [String!]!
phoneNumber: String @deprecated
}
21 changes: 21 additions & 0 deletions integration/src/__test__/integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {Client as ClientSSE, ClientOptions as ClientOptionsSSE, createClient as
import {CoercionDocument, ComplexityDocument, DateDocument, ErrorDocument, ErrorType, JsonEncodingDocument, PathDocument, UserFragmentFragmentDoc, ViewerDocument} from '../generated/graphql.ts';
import {cacheExchange, Client, dedupExchange, subscriptionExchange} from 'urql';
import {isFragmentReady, useFragment} from "../generated";
import { readFileSync } from 'fs';
import { join } from 'path';

const uri = process.env.VITE_SERVER_URL || 'http://localhost:8080/query';

Expand Down Expand Up @@ -225,6 +227,25 @@ describe('HTTP client', () => {
});
});

describe('Schema Introspection', () => {

const schemaJson = readFileSync(join(__dirname, '../generated/schema-introspection.json'), 'utf-8');
const schema = JSON.parse(schemaJson);

it('User.phoneNumber is deprecated and deprecationReason has the default value: `No longer supported`', async () => {

const userType = schema.__schema.types.find((type: any) => type.name === 'User');

expect(userType).toBeDefined();

const phoneNumberField = userType.fields.find((field: any) => field.name === 'phoneNumber');
expect(phoneNumberField).toBeDefined();

expect(phoneNumberField.isDeprecated).toBe(true);
expect(phoneNumberField.deprecationReason).toBe('No longer supported');
})
});

describe('Websocket client', () => {
const client = new ApolloClient({
link: new GraphQLWsLink(
Expand Down
1 change: 1 addition & 0 deletions integration/src/generated/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
schema-fetched.graphql
schema-introspection.json
4 changes: 2 additions & 2 deletions integration/src/generated/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const documents = {
"query error($type: ErrorType) {\n error(type: $type)\n}": types.ErrorDocument,
"query jsonEncoding {\n jsonEncoding\n}": types.JsonEncodingDocument,
"query path {\n path {\n cc: child {\n error\n }\n }\n}": types.PathDocument,
"query viewer {\n viewer {\n user {\n name\n ...userFragment @defer\n }\n }\n}\n\nfragment userFragment on User {\n likes\n}": types.ViewerDocument,
"query viewer {\n viewer {\n user {\n name\n phoneNumber\n ...userFragment @defer\n }\n }\n}\n\nfragment userFragment on User {\n likes\n}": types.ViewerDocument,
};

/**
Expand Down Expand Up @@ -63,7 +63,7 @@ export function graphql(source: "query path {\n path {\n cc: child {\n
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "query viewer {\n viewer {\n user {\n name\n ...userFragment @defer\n }\n }\n}\n\nfragment userFragment on User {\n likes\n}"): (typeof documents)["query viewer {\n viewer {\n user {\n name\n ...userFragment @defer\n }\n }\n}\n\nfragment userFragment on User {\n likes\n}"];
export function graphql(source: "query viewer {\n viewer {\n user {\n name\n phoneNumber\n ...userFragment @defer\n }\n }\n}\n\nfragment userFragment on User {\n likes\n}"): (typeof documents)["query viewer {\n viewer {\n user {\n name\n phoneNumber\n ...userFragment @defer\n }\n }\n}\n\nfragment userFragment on User {\n likes\n}"];

export function graphql(source: string) {
return (documents as any)[source] ?? {};
Expand Down
6 changes: 4 additions & 2 deletions integration/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ export type User = {
__typename?: 'User';
likes: Array<Scalars['String']['output']>;
name: Scalars['String']['output'];
/** @deprecated No longer supported */
phoneNumber?: Maybe<Scalars['String']['output']>;
};

export type Viewer = {
Expand Down Expand Up @@ -139,7 +141,7 @@ export type PathQuery = { __typename?: 'Query', path?: Array<{ __typename?: 'Ele
export type ViewerQueryVariables = Exact<{ [key: string]: never; }>;


export type ViewerQuery = { __typename?: 'Query', viewer?: { __typename?: 'Viewer', user?: ( { __typename?: 'User', name: string } & (
export type ViewerQuery = { __typename?: 'Query', viewer?: { __typename?: 'Viewer', user?: ( { __typename?: 'User', name: string, phoneNumber?: string | null } & (
{ __typename?: 'User' }
& { ' $fragmentRefs'?: { 'UserFragmentFragment': Incremental<UserFragmentFragment> } }
) ) | null } | null };
Expand All @@ -153,4 +155,4 @@ export const DateDocument = {"kind":"Document","definitions":[{"kind":"Operation
export const ErrorDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"error"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"type"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ErrorType"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"error"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"type"},"value":{"kind":"Variable","name":{"kind":"Name","value":"type"}}}]}]}}]} as unknown as DocumentNode<ErrorQuery, ErrorQueryVariables>;
export const JsonEncodingDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"jsonEncoding"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"jsonEncoding"}}]}}]} as unknown as DocumentNode<JsonEncodingQuery, JsonEncodingQueryVariables>;
export const PathDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"path"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"path"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"cc"},"name":{"kind":"Name","value":"child"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]}}]} as unknown as DocumentNode<PathQuery, PathQueryVariables>;
export const ViewerDocument = {"__meta__":{"deferredFields":{"userFragment":["likes"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"viewer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"viewer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"userFragment"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"userFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"User"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"likes"}}]}}]} as unknown as DocumentNode<ViewerQuery, ViewerQueryVariables>;
export const ViewerDocument = {"__meta__":{"deferredFields":{"userFragment":["likes"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"viewer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"viewer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phoneNumber"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"userFragment"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"userFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"User"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"likes"}}]}}]} as unknown as DocumentNode<ViewerQuery, ViewerQueryVariables>;
1 change: 1 addition & 0 deletions integration/src/generated/schema-expected.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type RemoteModelWithOmitempty {
type User {
likes: [String!]!
name: String!
phoneNumber: String @deprecated
}

type Viewer {
Expand Down
3 changes: 2 additions & 1 deletion integration/src/queries/viewer.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ query viewer {
viewer {
user {
name
phoneNumber
... userFragment @defer
}
}
}

fragment userFragment on User {
likes
}
}

0 comments on commit 1a9dbad

Please sign in to comment.