From de535a6480627dd828343b808d7609788ff44158 Mon Sep 17 00:00:00 2001 From: Vincent Boulaye Date: Fri, 11 Aug 2023 12:54:41 +0200 Subject: [PATCH 1/4] Add test case for paginated fragment in SinglePage mode --- e2e/kit/src/lib/utils/routes.ts | 1 + .../forward-cursor-single-page/+page.svelte | 37 ++++++++++++++ .../forward-cursor-single-page/spec.ts | 49 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/+page.svelte create mode 100644 e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/spec.ts diff --git a/e2e/kit/src/lib/utils/routes.ts b/e2e/kit/src/lib/utils/routes.ts index 5638744b8e..d5637acbe3 100644 --- a/e2e/kit/src/lib/utils/routes.ts +++ b/e2e/kit/src/lib/utils/routes.ts @@ -94,6 +94,7 @@ export const routes = { Pagination_query_offset_variable: '/pagination/query/offset-variable', Pagination_fragment_forward_cursor: '/pagination/fragment/forward-cursor', + Pagination_fragment_forward_cursor_single_page: '/pagination/fragment/forward-cursor-single-page', Pagination_fragment_backwards_cursor: '/pagination/fragment/backwards-cursor', Pagination_fragment_bidirectional_cursor: '/pagination/fragment/bidirectional-cursor', Pagination_fragment_offset: '/pagination/fragment/offset', diff --git a/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/+page.svelte b/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/+page.svelte new file mode 100644 index 0000000000..17339680c7 --- /dev/null +++ b/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/+page.svelte @@ -0,0 +1,37 @@ + + +
+ {$fragmentResult.data?.friendsConnection.edges.map(({ node }) => node?.name).join(', ')} +
+ +
+ {JSON.stringify($fragmentResult.pageInfo)} +
+ + diff --git a/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/spec.ts b/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/spec.ts new file mode 100644 index 0000000000..791cb6b52e --- /dev/null +++ b/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/spec.ts @@ -0,0 +1,49 @@ +import { test } from '@playwright/test'; +import { routes } from '../../../../lib/utils/routes.js'; +import { + expect_1_gql, + expect_0_gql, + expect_to_be, + expectToContain, + goto +} from '../../../../lib/utils/testsHelper.js'; + +test.describe('forwards cursor paginatedFragment in SinglePage mode', () => { + test('loadNextPage', async ({ page }) => { + await goto(page, routes.Pagination_fragment_forward_cursor_single_page); + + await expect_to_be(page, 'Bruce Willis, Samuel Jackson'); + + // wait for the api response + await expect_1_gql(page, 'button[id=next]'); + + // make sure we got the new content + await expect_to_be(page, 'Bruce Willis, Samuel Jackson, Morgan Freeman, Tom Hanks'); + }); + + test('page info tracks connection state', async ({ page }) => { + await goto(page, routes.Pagination_fragment_forward_cursor_single_page); + + const data = [ + 'Morgan Freeman, Tom Hanks', + 'Will Smith, Harrison Ford', + 'Eddie Murphy, Clint Eastwood' + ]; + + // load the next 3 pages + for (let i = 0; i < 3; i++) { + // wait for the request to resolve + await expect_1_gql(page, 'button[id=next]'); + + // check the page info + await expect_to_be(page, data[i]); + } + + // make sure we have all of the data loaded + await expect_to_be(page, data[2]); + + await expectToContain(page, `"hasNextPage":false`); + + await expect_0_gql(page, 'button[id=next]'); + }); +}); From 071139ed4ce88e941d73f63203177d9873e89d41 Mon Sep 17 00:00:00 2001 From: jycouet Date: Fri, 18 Aug 2023 14:16:16 +0200 Subject: [PATCH 2/4] :sparkles: IMPROVE: typings --- packages/houdini-react/package.json | 2 +- .../src/runtime/hooks/useDocumentHandle.ts | 2 +- packages/houdini/src/runtime/cache/cache.ts | 7 +++-- .../src/runtime/client/documentStore.ts | 3 +- .../houdini/src/runtime/lib/pagination.ts | 28 +++++++++++++------ 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/packages/houdini-react/package.json b/packages/houdini-react/package.json index 0bb7ec2126..2e5c306c08 100644 --- a/packages/houdini-react/package.json +++ b/packages/houdini-react/package.json @@ -71,4 +71,4 @@ }, "main": "./build/plugin-cjs/index.js", "types": "./build/plugin/index.d.ts" -} +} \ No newline at end of file diff --git a/packages/houdini-react/src/runtime/hooks/useDocumentHandle.ts b/packages/houdini-react/src/runtime/hooks/useDocumentHandle.ts index 886ebec269..a93fdce9b1 100644 --- a/packages/houdini-react/src/runtime/hooks/useDocumentHandle.ts +++ b/packages/houdini-react/src/runtime/hooks/useDocumentHandle.ts @@ -106,7 +106,7 @@ export function useDocumentHandle< getVariables: () => storeValue.variables!, storeName: artifact.name, fetch: fetchQuery, - fetchUpdate: async (args, updates = ['append']) => { + fetchUpdate: (args, updates) => { return observer.send({ ...args, cacheParams: { diff --git a/packages/houdini/src/runtime/cache/cache.ts b/packages/houdini/src/runtime/cache/cache.ts index fff8f5e5ac..fe576b6eed 100644 --- a/packages/houdini/src/runtime/cache/cache.ts +++ b/packages/houdini/src/runtime/cache/cache.ts @@ -8,6 +8,7 @@ import type { GraphQLObject, GraphQLValue, NestedList, + RefetchUpdateModes, SubscriptionSelection, SubscriptionSpec, ValueMap, @@ -57,7 +58,7 @@ export class Cache { variables?: {} parent?: string layer?: LayerID | null - applyUpdates?: string[] + applyUpdates?: RefetchUpdateModes[] notifySubscribers?: SubscriptionSpec[] forceNotify?: boolean forceStale?: boolean @@ -397,7 +398,7 @@ class CacheInternal { root?: string layer: Layer toNotify?: FieldSelection[] - applyUpdates?: string[] + applyUpdates?: RefetchUpdateModes[] forceNotify?: boolean forceStale?: boolean }): FieldSelection[] { @@ -1334,7 +1335,7 @@ class CacheInternal { abstract: boolean variables: {} specs: FieldSelection[] - applyUpdates?: string[] + applyUpdates?: RefetchUpdateModes[] fields: SubscriptionSelection layer: Layer forceNotify?: boolean diff --git a/packages/houdini/src/runtime/client/documentStore.ts b/packages/houdini/src/runtime/client/documentStore.ts index 0559503e18..0686cb2de0 100644 --- a/packages/houdini/src/runtime/client/documentStore.ts +++ b/packages/houdini/src/runtime/client/documentStore.ts @@ -14,6 +14,7 @@ import type { SubscriptionSpec, CachePolicies, GraphQLVariables, + RefetchUpdateModes, } from '../lib/types' import { ArtifactKind } from '../lib/types' import { cachePolicy } from './plugins' @@ -583,7 +584,7 @@ export type ClientPluginContext = { disableWrite?: boolean disableRead?: boolean disableSubscriptions?: boolean - applyUpdates?: string[] + applyUpdates?: RefetchUpdateModes[] serverSideFallback?: boolean } stuff: App.Stuff diff --git a/packages/houdini/src/runtime/lib/pagination.ts b/packages/houdini/src/runtime/lib/pagination.ts index 1c27648978..1e6224b106 100644 --- a/packages/houdini/src/runtime/lib/pagination.ts +++ b/packages/houdini/src/runtime/lib/pagination.ts @@ -11,6 +11,7 @@ import type { QueryArtifact, QueryResult, FetchParams, + RefetchUpdateModes, } from './types' export function cursorHandlers<_Data extends GraphQLObject, _Input extends GraphQLVariables>({ @@ -26,7 +27,10 @@ export function cursorHandlers<_Data extends GraphQLObject, _Input extends Graph getVariables: () => NonNullable<_Input> getSession: () => Promise fetch: FetchFn<_Data, _Input> - fetchUpdate: (arg: SendParams, updates: string[]) => ReturnType> + fetchUpdate: ( + arg: SendParams, + updates: RefetchUpdateModes[] + ) => ReturnType> }): CursorHandlers<_Data, _Input> { // dry up the page-loading logic const loadPage = async ({ @@ -236,7 +240,10 @@ export function offsetHandlers<_Data extends GraphQLObject, _Input extends Graph }: { artifact: QueryArtifact fetch: FetchFn<_Data, _Input> - fetchUpdate: (arg: SendParams) => ReturnType> + fetchUpdate: ( + arg: SendParams, + updates: RefetchUpdateModes[] + ) => ReturnType> storeName: string getState: () => _Data | null getVariables: () => _Input @@ -282,13 +289,16 @@ export function offsetHandlers<_Data extends GraphQLObject, _Input extends Graph // send the query const targetFetch = isSinglePage ? parentFetch : parentFetchUpdate - await targetFetch({ - variables: queryVariables as _Input, - fetch, - metadata, - policy: isSinglePage ? artifact.policy : CachePolicy.NetworkOnly, - session: await getSession(), - }) + await targetFetch( + { + variables: queryVariables as _Input, + fetch, + metadata, + policy: isSinglePage ? artifact.policy : CachePolicy.NetworkOnly, + session: await getSession(), + }, + ['append'] + ) // add the page size to the offset so we load the next page next time const pageSize = queryVariables.limit || artifact.refetch!.pageSize From 7cf34da23980e22921e06bb33df8ca5668633401 Mon Sep 17 00:00:00 2001 From: jycouet Date: Mon, 21 Aug 2023 12:21:18 +0200 Subject: [PATCH 3/4] :children_crossing: UPDATE: space --- .../pagination/fragment/forward-cursor-single-page/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/+page.svelte b/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/+page.svelte index 17339680c7..40c71c4bc4 100644 --- a/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/+page.svelte +++ b/e2e/kit/src/routes/pagination/fragment/forward-cursor-single-page/+page.svelte @@ -14,7 +14,7 @@ $queryResult.data?.user ?? null, graphql(` fragment ForwardsCursorSinglePageFragment on User { - friendsConnection(first: 2) @paginate(mode:SinglePage) { + friendsConnection(first: 2) @paginate(mode: SinglePage) { edges { node { name From ad661dc2640da8055e0acd535700ac288fb9daaa Mon Sep 17 00:00:00 2001 From: jycouet Date: Mon, 21 Aug 2023 12:30:49 +0200 Subject: [PATCH 4/4] :children_crossing: UPDATE: tentatives exp --- .../houdini/src/runtime/lib/pagination.ts | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/packages/houdini/src/runtime/lib/pagination.ts b/packages/houdini/src/runtime/lib/pagination.ts index 1e6224b106..a2862e1a99 100644 --- a/packages/houdini/src/runtime/lib/pagination.ts +++ b/packages/houdini/src/runtime/lib/pagination.ts @@ -65,16 +65,24 @@ export function cursorHandlers<_Data extends GraphQLObject, _Input extends Graph let isSinglePage = artifact.refetch?.mode === 'SinglePage' // send the query - await (isSinglePage ? parentFetch : parentFetchUpdate)( - { + if (isSinglePage) { + await parentFetch({ variables: loadVariables, - fetch, metadata, - policy: isSinglePage ? artifact.policy : CachePolicy.NetworkOnly, - session: await getSession(), - }, - isSinglePage ? [] : [where === 'start' ? 'prepend' : 'append'] - ) + policy: artifact.policy, + }) + } else { + await parentFetchUpdate( + { + variables: loadVariables, + fetch, + metadata, + policy: CachePolicy.NetworkOnly, + session: await getSession(), + }, + [where === 'start' ? 'prepend' : 'append'] + ) + } } const getPageInfo = () => { @@ -288,17 +296,24 @@ export function offsetHandlers<_Data extends GraphQLObject, _Input extends Graph let isSinglePage = artifact.refetch?.mode === 'SinglePage' // send the query - const targetFetch = isSinglePage ? parentFetch : parentFetchUpdate - await targetFetch( - { + if (isSinglePage) { + await parentFetch({ variables: queryVariables as _Input, - fetch, metadata, - policy: isSinglePage ? artifact.policy : CachePolicy.NetworkOnly, - session: await getSession(), - }, - ['append'] - ) + policy: artifact.policy, + }) + } else { + await parentFetchUpdate( + { + variables: queryVariables as _Input, + fetch, + metadata, + policy: CachePolicy.NetworkOnly, + session: await getSession(), + }, + ['append'] + ) + } // add the page size to the offset so we load the next page next time const pageSize = queryVariables.limit || artifact.refetch!.pageSize