Skip to content

Commit f366a0d

Browse files
committed
Add test to guard against partial abandoned query
1 parent d1c5573 commit f366a0d

1 file changed

Lines changed: 163 additions & 0 deletions

File tree

src/core/__tests__/client.watchQuery/deferGraphQL17Alpha9.test.ts

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,6 +1825,169 @@ test('reports partial cached data inside a defer boundary as "partial" when the
18251825
await expect(stream).not.toEmitAnything();
18261826
});
18271827

1828+
test("reports partial data correctly when a mid-stream request is abandoned and the query is subscribed to again", async () => {
1829+
// Suppress expected missing field warning when writing partial value after
1830+
// first chunk
1831+
using _ = spyOnConsole("error");
1832+
const query = gql`
1833+
query {
1834+
greeting {
1835+
message
1836+
... on Greeting @defer {
1837+
recipient {
1838+
name
1839+
email
1840+
}
1841+
}
1842+
}
1843+
}
1844+
`;
1845+
1846+
const defer1 = mockDeferStreamGraphQL17Alpha9();
1847+
const defer2 = mockDeferStreamGraphQL17Alpha9();
1848+
let requests = 0;
1849+
const link = ApolloLink.from([
1850+
new ApolloLink((operation, forward) => {
1851+
requests++;
1852+
return forward(operation);
1853+
}),
1854+
ApolloLink.split(() => requests === 1, defer1.httpLink, defer2.httpLink),
1855+
]);
1856+
1857+
const cache = new InMemoryCache();
1858+
cache.writeQuery({
1859+
query,
1860+
data: {
1861+
greeting: {
1862+
__typename: "Greeting",
1863+
recipient: { __typename: "Person", name: "Cached Alice" },
1864+
},
1865+
},
1866+
});
1867+
1868+
const client = new ApolloClient({
1869+
cache,
1870+
link,
1871+
incrementalHandler: new GraphQL17Alpha9Handler(),
1872+
});
1873+
1874+
const observable = client.watchQuery({
1875+
query,
1876+
fetchPolicy: "cache-first",
1877+
returnPartialData: true,
1878+
});
1879+
1880+
const initialChunk = {
1881+
data: { greeting: { __typename: "Greeting", message: "Hello world" } },
1882+
pending: [{ id: "0", path: ["greeting"] }],
1883+
hasNext: true,
1884+
};
1885+
1886+
const streamA = new ObservableStream(observable);
1887+
1888+
await expect(streamA).toEmitTypedValue({
1889+
data: {
1890+
greeting: {
1891+
__typename: "Greeting",
1892+
recipient: { __typename: "Person", name: "Cached Alice" },
1893+
},
1894+
},
1895+
dataState: "partial",
1896+
loading: true,
1897+
networkStatus: NetworkStatus.loading,
1898+
partial: true,
1899+
});
1900+
1901+
defer1.enqueueInitialChunk({ ...initialChunk });
1902+
1903+
await expect(streamA).toEmitTypedValue({
1904+
data: {
1905+
greeting: {
1906+
__typename: "Greeting",
1907+
message: "Hello world",
1908+
recipient: { __typename: "Person", name: "Cached Alice" },
1909+
},
1910+
},
1911+
dataState: "partial",
1912+
loading: true,
1913+
networkStatus: NetworkStatus.streaming,
1914+
partial: true,
1915+
});
1916+
1917+
// Abandon the request before the boundary is delivered.
1918+
streamA.unsubscribe();
1919+
1920+
const streamB = new ObservableStream(observable);
1921+
1922+
await expect(streamB).toEmitTypedValue({
1923+
data: {
1924+
greeting: {
1925+
__typename: "Greeting",
1926+
message: "Hello world",
1927+
recipient: { __typename: "Person", name: "Cached Alice" },
1928+
},
1929+
},
1930+
dataState: "partial",
1931+
loading: true,
1932+
networkStatus: NetworkStatus.loading,
1933+
partial: true,
1934+
});
1935+
1936+
defer2.enqueueInitialChunk({ ...initialChunk });
1937+
1938+
await expect(streamB).toEmitTypedValue({
1939+
data: {
1940+
greeting: {
1941+
__typename: "Greeting",
1942+
message: "Hello world",
1943+
recipient: { __typename: "Person", name: "Cached Alice" },
1944+
},
1945+
},
1946+
dataState: "partial",
1947+
loading: true,
1948+
networkStatus: NetworkStatus.streaming,
1949+
partial: true,
1950+
});
1951+
1952+
defer2.enqueueSubsequentChunk({
1953+
incremental: [
1954+
{
1955+
data: {
1956+
__typename: "Greeting",
1957+
recipient: {
1958+
name: "Alice",
1959+
email: "alice@example.com",
1960+
__typename: "Person",
1961+
},
1962+
},
1963+
id: "0",
1964+
},
1965+
],
1966+
completed: [{ id: "0" }],
1967+
hasNext: false,
1968+
});
1969+
1970+
await expect(streamB).toEmitTypedValue({
1971+
data: {
1972+
greeting: {
1973+
__typename: "Greeting",
1974+
message: "Hello world",
1975+
recipient: {
1976+
__typename: "Person",
1977+
name: "Alice",
1978+
email: "alice@example.com",
1979+
},
1980+
},
1981+
},
1982+
dataState: "complete",
1983+
loading: false,
1984+
networkStatus: NetworkStatus.ready,
1985+
partial: false,
1986+
});
1987+
1988+
await expect(streamB).not.toEmitAnything();
1989+
});
1990+
18281991
test("emits empty then streaming results for deferred queries with no data in the cache and returnPartialData", async () => {
18291992
const query = gql`
18301993
query {

0 commit comments

Comments
 (0)