Skip to content

Commit

Permalink
deprecate useFragement returnPartialData option
Browse files Browse the repository at this point in the history
  • Loading branch information
Lenz Weber-Tronic committed Apr 14, 2023
1 parent a0ef413 commit 885a02e
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-buttons-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/client": patch
---

deprecate `useFragement` `returnPartialData` option
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
"acorn": "8.8.2",
"blob-polyfill": "7.0.20220408",
"bytes": "3.1.2",
"console-testing-library": "^0.6.1",
"cross-fetch": "3.1.5",
"eslint": "8.38.0",
"eslint-plugin-testing-library": "5.10.2",
Expand Down
91 changes: 91 additions & 0 deletions src/react/hooks/__tests__/useFragment.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from "react";
import { render, waitFor, screen, renderHook } from "@testing-library/react";
import userEvent from '@testing-library/user-event';
import { act } from "react-dom/test-utils";
import { mockConsole, createConsole } from "console-testing-library/pure";

import { useFragment_experimental as useFragment } from "../useFragment";
import { MockedProvider } from "../../../testing";
Expand Down Expand Up @@ -911,4 +912,94 @@ describe("useFragment", () => {
]);
});
});

describe("tests with incomplete data", () => {
let cache: InMemoryCache, wrapper: React.FunctionComponent;
const ItemFragment = gql`
fragment ItemFragment on Item {
id
text
}
`;

beforeEach(() => {
cache = new InMemoryCache();

wrapper = ({ children }: any) => <MockedProvider cache={cache}>{children}</MockedProvider>;

// silence the console for the incomplete fragment write
const restoreConsole = mockConsole(createConsole());
cache.writeFragment({
fragment: ItemFragment,
data: {
__typename: "Item",
id: 5,
},
});
restoreConsole();
});

it("assumes `returnPartialData: true` per default", () => {
const { result } = renderHook(
() =>
useFragment({
fragment: ItemFragment,
from: { __typename: "Item", id: 5 },
}),
{ wrapper }
);

expect(result.current.data).toEqual({ __typename: "Item", id: 5 });
expect(result.current.complete).toBe(false);
});

it("throws an exception with `returnPartialData: false` if only partial data is available", () => {
// this is actually not intended behavuor, but it is the current behaviour
// let's document it in a test until we remove `returnPartialData` in 3.8

let error: Error;

renderHook(
() => {
// we can't just `expect(() => renderHook(...)).toThrow(...)` because it will render a second time, resulting in an uncaught exception
try {
useFragment({
fragment: ItemFragment,
from: { __typename: "Item", id: 5 },
returnPartialData: false,
});
} catch (e) {
error = e;
}
},
{ wrapper }
);

expect(error!.toString()).toMatch(`Error: Can't find field 'text' on Item:5 object`);
});

it("throws an exception with `returnPartialData: false` if no data is available", () => {
// this is actually not intended behavuor, but it is the current behaviour
// let's document it in a test until we remove `returnPartialData` in 3.8
let error: Error;

renderHook(
() => {
// we can't just `expect(() => renderHook(...)).toThrow(...)` because it will render a second time, resulting in an uncaught exception
try {
useFragment({
fragment: ItemFragment,
from: { __typename: "Item", id: 6 },
returnPartialData: false,
});
} catch (e) {
error = e;
}
},
{ wrapper }
);

expect(error!.toString()).toMatch(`Error: Dangling reference to missing Item:6 object`);
});
});
});
15 changes: 12 additions & 3 deletions src/react/hooks/useFragment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,27 @@ import { OperationVariables } from "../../core";

export interface UseFragmentOptions<TData, TVars>
extends Omit<
Cache.DiffOptions<TData, TVars>,
Cache.DiffOptions<TData, TVars>,
| "id"
| "query"
| "optimistic"
| "previousResult"
>, Omit<
Cache.ReadFragmentOptions<TData, TVars>,
| "returnPartialData"
>, Omit<Cache.ReadFragmentOptions<TData, TVars>,
| "id"
| "returnPartialData"
> {
from: StoreObject | Reference | string;
// Override this field to make it optional (default: true).
optimistic?: boolean;

/**
* Whether to return incomplete data rather than null.
* Defaults to `true`.
* @deprecated This option will be removed in Apollo Client 3.8.
* Please check `result.missing` instead.
*/
returnPartialData?: boolean;
}

// Since the above definition of UseFragmentOptions can be hard to parse without
Expand Down

0 comments on commit 885a02e

Please sign in to comment.