Skip to content

Commit

Permalink
Undo automatic stripping of __typename from HttpLink and GraphQLWsLin…
Browse files Browse the repository at this point in the history
…k introduced in #10724
  • Loading branch information
jerelmiller committed May 10, 2023
1 parent d0f85b9 commit 04896a2
Show file tree
Hide file tree
Showing 4 changed files with 3 additions and 285 deletions.
256 changes: 0 additions & 256 deletions src/link/http/__tests__/HttpLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1111,262 +1111,6 @@ describe('HttpLink', () => {
new Error('HttpLink: Trying to send a client-only query to the server. To send to the server, ensure a non-client field is added to the query or set the `transformOptions.removeClientFields` option to `true`.')
);
});

it('strips __typename from object argument when sending a mutation', async () => {
fetchMock.mock('https://example.com/graphql', {
status: 200,
body: JSON.stringify({
data: {
__typename: 'Mutation',
updateTodo: {
__typename: 'Todo',
id: 1,
name: 'Take out trash',
completed: true
}
}
}),
headers: { 'content-type': 'application/json' }
});

const query = gql`
mutation UpdateTodo($todo: TodoInput!) {
updateTodo(todo: $todo) {
id
name
completed
}
}
`;

const link = createHttpLink({ uri: 'https://example.com/graphql' });

const todo = {
__typename: 'Todo',
id: 1,
name: 'Take out trash',
completed: true,
}

await new Promise((resolve, reject) => {
execute(link, { query, variables: { todo } }).subscribe({
next: resolve,
error: reject
});
});

const [, options] = fetchMock.lastCall()!;
const { body } = options!

expect(JSON.parse(body!.toString())).toEqual({
operationName: 'UpdateTodo',
query: print(query),
variables: {
todo: {
id: 1,
name: 'Take out trash',
completed: true,
}
}
});
});

it('strips __typename from array argument when sending a mutation', async () => {
fetchMock.mock('https://example.com/graphql', {
status: 200,
body: JSON.stringify({
data: {
__typename: 'Mutation',
updateTodos: [
{
__typename: 'Todo',
id: 1,
name: 'Take out trash',
completed: true
},
{
__typename: 'Todo',
id: 2,
name: 'Clean room',
completed: true
},
]
}
}),
headers: { 'content-type': 'application/json' }
});

const query = gql`
mutation UpdateTodos($todos: [TodoInput!]!) {
updateTodos(todos: $todos) {
id
name
completed
}
}
`;

const link = createHttpLink({ uri: 'https://example.com/graphql' });

const todos = [
{
__typename: 'Todo',
id: 1,
name: 'Take out trash',
completed: true,
},
{
__typename: 'Todo',
id: 2,
name: 'Clean room',
completed: true,
},
];

await new Promise((resolve, reject) => {
execute(link, { query, variables: { todos } }).subscribe({
next: resolve,
error: reject
});
});

const [, options] = fetchMock.lastCall()!;
const { body } = options!

expect(JSON.parse(body!.toString())).toEqual({
operationName: 'UpdateTodos',
query: print(query),
variables: {
todos: [
{
id: 1,
name: 'Take out trash',
completed: true,
},
{
id: 2,
name: 'Clean room',
completed: true,
},
]
}
});
});

it('strips __typename from mixed argument when sending a mutation', async () => {
fetchMock.mock('https://example.com/graphql', {
status: 200,
body: JSON.stringify({
data: {
__typename: 'Mutation',
updateProfile: {
__typename: 'Profile',
id: 1,
},
}
}),
headers: { 'content-type': 'application/json' }
});

const query = gql`
mutation UpdateProfile($profile: ProfileInput!) {
updateProfile(profile: $profile) {
id
}
}
`;

const link = createHttpLink({ uri: 'https://example.com/graphql' });

const profile = {
__typename: 'Profile',
id: 1,
interests: [
{ __typename: 'Interest', name: 'Hiking' },
{ __typename: 'Interest', name: 'Nature' }
],
avatar: {
__typename: 'Avatar',
url: 'https://example.com/avatar.jpg',
}
};

await new Promise((resolve, reject) => {
execute(link, { query, variables: { profile } }).subscribe({
next: resolve,
error: reject
});
});

const [, options] = fetchMock.lastCall()!;
const { body } = options!

expect(JSON.parse(body!.toString())).toEqual({
operationName: 'UpdateProfile',
query: print(query),
variables: {
profile: {
id: 1,
interests: [
{ name: 'Hiking' },
{ name: 'Nature' }
],
avatar: {
url: 'https://example.com/avatar.jpg',
},
},
}
});
});
});

it('strips __typename when sending a query', async () => {
fetchMock.mock('https://example.com/graphql', {
status: 200,
body: JSON.stringify({
data: {
__typename: 'Query',
searchTodos: []
}
}),
headers: { 'content-type': 'application/json' }
});

const query = gql`
query SearchTodos($filter: TodoFilter!) {
searchTodos(filter: $filter) {
id
name
}
}
`;

const link = createHttpLink({ uri: 'https://example.com/graphql' });

const filter = {
__typename: 'Filter',
completed: true,
};

await new Promise((resolve, reject) => {
execute(link, { query, variables: { filter } }).subscribe({
next: resolve,
error: reject
});
});

const [, options] = fetchMock.lastCall()!;
const { body } = options!

expect(JSON.parse(body!.toString())).toEqual({
operationName: 'SearchTodos',
query: print(query),
variables: {
filter: {
completed: true,
},
},
});
});

describe('Dev warnings', () => {
Expand Down
21 changes: 0 additions & 21 deletions src/link/http/__tests__/selectHttpOptionsAndBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,25 +104,4 @@ describe('selectHttpOptionsAndBody', () => {

expect(body.query).toBe('query SampleQuery{stub{id}}');
});

it('strips __typename from variables', () => {
const operation = createOperation(
{},
{
query,
variables: {
__typename: 'Test',
nested: { __typename: 'Nested', foo: 'bar' },
array: [{ __typename: 'Item', baz: 'foo' }]
},
}
);

const { body } = selectHttpOptionsAndBody(operation, {});

expect(body.variables).toEqual({
nested: { foo: 'bar' },
array: [{ baz: 'foo' }],
});
})
});
3 changes: 1 addition & 2 deletions src/link/http/selectHttpOptionsAndBody.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ASTNode, print } from 'graphql';
import { stripTypename } from '../../utilities';

import { Operation } from '../core';

Expand Down Expand Up @@ -180,7 +179,7 @@ export function selectHttpOptionsAndBodyInternal(

//The body depends on the http options
const { operationName, extensions, variables, query } = operation;
const body: Body = { operationName, variables: stripTypename(variables) };
const body: Body = { operationName, variables };

if (http.includeExtensions) (body as any).extensions = extensions;

Expand Down
8 changes: 2 additions & 6 deletions src/link/subscriptions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { print } from "graphql";
import type { Client } from "graphql-ws";

import { ApolloLink, Operation, FetchResult } from "../core";
import { isNonNullObject, stripTypename, Observable } from "../../utilities";
import { isNonNullObject, Observable } from "../../utilities";
import { ApolloError } from "../../errors";

// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close_event
Expand All @@ -53,11 +53,7 @@ export class GraphQLWsLink extends ApolloLink {
public request(operation: Operation): Observable<FetchResult> {
return new Observable((observer) => {
return this.client.subscribe<FetchResult>(
{
...operation,
query: print(operation.query),
variables: stripTypename(operation.variables)
},
{ ...operation, query: print(operation.query) },
{
next: observer.next.bind(observer),
complete: observer.complete.bind(observer),
Expand Down

0 comments on commit 04896a2

Please sign in to comment.