Skip to content

Commit

Permalink
Add data masking tests for useMutation
Browse files Browse the repository at this point in the history
  • Loading branch information
jerelmiller committed Aug 28, 2024
1 parent 270f76e commit 94d1d14
Showing 1 changed file with 211 additions and 0 deletions.
211 changes: 211 additions & 0 deletions src/react/hooks/__tests__/useMutation.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
mockSingleLink,
subscribeAndCount,
MockedResponse,
MockLink,
} from "../../../testing";
import { ApolloProvider } from "../../context";
import { useQuery } from "../useQuery";
Expand Down Expand Up @@ -2826,6 +2827,216 @@ describe("useMutation Hook", () => {
});
});

describe("data masking", () => {
test("masks data returned from useMutation when dataMasking is `true`", async () => {
interface Mutation {
updateUser: {
__typename: "User";
id: number;
name: string;
};
}

const mutation: TypedDocumentNode<Mutation, never> = gql`
mutation MaskedMutation {
updateUser {
id
name
...UserFields
}
}
fragment UserFields on User {
age
}
`;

const mocks = [
{
request: { query: mutation },
result: {
data: {
updateUser: {
__typename: "User",
id: 1,
name: "Test User",
age: 30,
},
},
},
delay: 10,
},
];

const client = new ApolloClient({
dataMasking: true,
cache: new InMemoryCache(),
link: new MockLink(mocks),
});

const ProfiledHook = profileHook(() => useMutation(mutation));

render(<ProfiledHook />, {
wrapper: ({ children }) => (
<ApolloProvider client={client}>{children}</ApolloProvider>
),
});

const [mutate, result] = await ProfiledHook.takeSnapshot();

expect(result.loading).toBe(false);
expect(result.data).toBeUndefined();
expect(result.error).toBeUndefined();

let promise!: Promise<FetchResult<Mutation>>;
act(() => {
promise = mutate();
});

{
const [, result] = await ProfiledHook.takeSnapshot();

expect(result.loading).toBe(true);
expect(result.data).toBeUndefined();
expect(result.error).toBeUndefined();
}

{
const [, result] = await ProfiledHook.takeSnapshot();

expect(result.loading).toBe(false);
expect(result.data).toEqual({
updateUser: {
__typename: "User",
id: 1,
name: "Test User",
},
});
expect(result.error).toBeUndefined();
}

{
const { data, errors } = await promise;

expect(data).toEqual({
updateUser: {
__typename: "User",
id: 1,
name: "Test User",
},
});
expect(errors).toBeUndefined();
}

await expect(ProfiledHook).not.toRerender();
});

test("does not mask data returned from useMutation when dataMasking is `false`", async () => {
interface Mutation {
updateUser: {
__typename: "User";
id: number;
name: string;
};
}

const mutation: TypedDocumentNode<Mutation, never> = gql`
mutation MaskedMutation {
updateUser {
id
name
...UserFields
}
}
fragment UserFields on User {
age
}
`;

const mocks = [
{
request: { query: mutation },
result: {
data: {
updateUser: {
__typename: "User",
id: 1,
name: "Test User",
age: 30,
},
},
},
delay: 10,
},
];

const client = new ApolloClient({
dataMasking: false,
cache: new InMemoryCache(),
link: new MockLink(mocks),
});

const ProfiledHook = profileHook(() => useMutation(mutation));

render(<ProfiledHook />, {
wrapper: ({ children }) => (
<ApolloProvider client={client}>{children}</ApolloProvider>
),
});

const [mutate, result] = await ProfiledHook.takeSnapshot();

expect(result.loading).toBe(false);
expect(result.data).toBeUndefined();
expect(result.error).toBeUndefined();

let promise!: Promise<FetchResult<Mutation>>;
act(() => {
promise = mutate();
});

{
const [, result] = await ProfiledHook.takeSnapshot();

expect(result.loading).toBe(true);
expect(result.data).toBeUndefined();
expect(result.error).toBeUndefined();
}

{
const [, result] = await ProfiledHook.takeSnapshot();

expect(result.loading).toBe(false);
expect(result.data).toEqual({
updateUser: {
__typename: "User",
id: 1,
name: "Test User",
age: 30,
},
});
expect(result.error).toBeUndefined();
}

{
const { data, errors } = await promise;

expect(data).toEqual({
updateUser: {
__typename: "User",
id: 1,
name: "Test User",
age: 30,
},
});
expect(errors).toBeUndefined();
}

await expect(ProfiledHook).not.toRerender();
});
});

describe.skip("Type Tests", () => {
test("NoInfer prevents adding arbitrary additional variables", () => {
const typedNode = {} as TypedDocumentNode<{ foo: string }, { bar: number }>;
Expand Down

0 comments on commit 94d1d14

Please sign in to comment.