Skip to content

Commit 6cde977

Browse files
committed
test(test-codegen-app): align type tests with selection api
1 parent 1ca2b49 commit 6cde977

4 files changed

Lines changed: 203 additions & 162 deletions

File tree

graphql/test-app/src/App.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,11 @@ function Dashboard({ token, userId, onSignOut }: { token: string; userId: string
813813
const [activeDbId, setActiveDbId] = useState<string | null>(null);
814814

815815
const { mutate: signOut, isPending: signingOut } = useSignOutMutation({
816+
selection: {
817+
fields: {
818+
clientMutationId: true,
819+
},
820+
},
816821
onSuccess: () => {
817822
queryClient.clear();
818823
onSignOut();

graphql/test-app/src/type-tests/react-query-helpers-options.type-test.ts

Lines changed: 82 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,25 @@
22
* Compile-time regression checks for helper overloads and React Query options.
33
*
44
* Focus:
5-
* - fetch/prefetch overload behavior
6-
* - optional variables + required selection.fields custom query overloads
7-
* - default vs explicit selection result narrowing in helpers
8-
* - allowed/disallowed React Query options on generated hooks
5+
* - fetch/prefetch signatures for selection-enabled queries
6+
* - optional variables flow for non-selection custom queries
7+
* - pass-through and blocked React Query options
98
*/
109

1110
import { QueryClient } from '@tanstack/react-query';
1211

1312
import {
1413
fetchDatabasesQuery,
15-
fetchGetObjectAtPathQuery,
14+
fetchStepsRequiredQuery,
15+
fetchUserByUsernameQuery,
1616
prefetchDatabasesQuery,
17-
prefetchGetObjectAtPathQuery,
17+
prefetchStepsRequiredQuery,
18+
prefetchUserByUsernameQuery,
1819
useCurrentUserQuery,
1920
useDatabasesQuery,
20-
useGetObjectAtPathQuery,
2121
useSignInMutation,
22+
useStepsRequiredQuery,
23+
useUserByUsernameQuery,
2224
} from '../generated/hooks';
2325

2426
type Assert<T extends true> = T;
@@ -28,9 +30,20 @@ type NotHasKey<T, K extends PropertyKey> = K extends keyof T ? false : true;
2830
function helperOverloadChecks() {
2931
const queryClient = new QueryClient();
3032

31-
const defaultDatabasesFetch = fetchDatabasesQuery({ selection: { first: 2 } });
32-
type DefaultDatabaseNode = Awaited<typeof defaultDatabasesFetch>['databases']['nodes'][number];
33-
type _defaultDatabaseFetchOmitsName = Assert<NotHasKey<DefaultDatabaseNode, 'name'>>;
33+
const idOnlyDatabasesFetch = fetchDatabasesQuery({
34+
selection: {
35+
first: 2,
36+
fields: {
37+
id: true,
38+
},
39+
},
40+
});
41+
type IdOnlyDatabaseNode = Awaited<
42+
typeof idOnlyDatabasesFetch
43+
>['databases']['nodes'][number];
44+
type _idOnlyDatabaseFetchOmitsName = Assert<
45+
NotHasKey<IdOnlyDatabaseNode, 'name'>
46+
>;
3447

3548
const selectedDatabasesFetch = fetchDatabasesQuery({
3649
selection: {
@@ -48,60 +61,67 @@ function helperOverloadChecks() {
4861
},
4962
},
5063
});
51-
type SelectedDatabaseNode = Awaited<typeof selectedDatabasesFetch>['databases']['nodes'][number];
52-
type _selectedDatabaseFetchHasName = Assert<HasKey<SelectedDatabaseNode, 'name'>>;
64+
type SelectedDatabaseNode = Awaited<
65+
typeof selectedDatabasesFetch
66+
>['databases']['nodes'][number];
67+
type _selectedDatabaseFetchHasName = Assert<
68+
HasKey<SelectedDatabaseNode, 'name'>
69+
>;
5370

54-
prefetchDatabasesQuery(queryClient, { selection: { first: 2 } });
5571
prefetchDatabasesQuery(queryClient, {
5672
selection: {
5773
first: 2,
5874
fields: {
5975
id: true,
60-
name: true,
6176
},
6277
},
6378
});
6479

65-
// @ts-expect-error invalid helper nested select key should be rejected
66-
fetchDatabasesQuery({ selection: { fields: { schemas: { select: { invalidField: true } } } } });
67-
68-
const defaultGetObjectFetch = fetchGetObjectAtPathQuery({ variables: undefined });
69-
type DefaultGetObject = Awaited<typeof defaultGetObjectFetch>['getObjectAtPath'];
70-
type _defaultGetObjectOmitsData = Assert<NotHasKey<DefaultGetObject, 'data'>>;
80+
// @ts-expect-error selection.fields is required
81+
fetchDatabasesQuery({ selection: { first: 2 } });
7182

72-
const selectedGetObjectFetch = fetchGetObjectAtPathQuery({
73-
variables: undefined,
83+
const selectedUserByUsernameFetch = fetchUserByUsernameQuery({
84+
variables: { username: 'dev' },
7485
selection: {
7586
fields: {
7687
id: true,
77-
data: true,
88+
username: true,
7889
},
7990
},
8091
});
81-
type SelectedGetObject = Awaited<typeof selectedGetObjectFetch>['getObjectAtPath'];
82-
type _selectedGetObjectHasData = Assert<HasKey<SelectedGetObject, 'data'>>;
92+
type SelectedUserByUsername = Awaited<
93+
typeof selectedUserByUsernameFetch
94+
>['userByUsername'];
95+
type _selectedUserByUsernameHasUsername = Assert<
96+
HasKey<SelectedUserByUsername, 'username'>
97+
>;
8398

84-
prefetchGetObjectAtPathQuery(queryClient, { variables: undefined });
85-
prefetchGetObjectAtPathQuery(queryClient, {
86-
variables: undefined,
99+
prefetchUserByUsernameQuery(queryClient, {
100+
variables: { username: 'dev' },
87101
selection: {
88102
fields: {
89103
id: true,
90104
},
91105
},
92106
});
93107

94-
// @ts-expect-error invalid custom helper select key should be rejected
95-
prefetchGetObjectAtPathQuery(queryClient, {
96-
variables: undefined,
97-
selection: { fields: { invalidField: true } },
98-
});
99-
100-
// @ts-expect-error custom helper select overload requires explicit variables
101-
fetchGetObjectAtPathQuery({ selection: { fields: { id: true } } });
108+
// @ts-expect-error selection is required for selection-enabled custom query helpers
109+
fetchUserByUsernameQuery({ variables: { username: 'dev' } });
110+
// @ts-expect-error variables are required for this custom query helper
111+
fetchUserByUsernameQuery({ selection: { fields: { id: true } } });
102112

103-
// @ts-expect-error custom helper prefetch overload requires explicit variables
104-
prefetchGetObjectAtPathQuery(queryClient, { selection: { fields: { id: true } } });
113+
// Optional variables flow for custom queries without selection support.
114+
fetchStepsRequiredQuery();
115+
fetchStepsRequiredQuery({ variables: { vlevel: '1', first: 10 } });
116+
prefetchStepsRequiredQuery(queryClient);
117+
prefetchStepsRequiredQuery(queryClient, { variables: { vlevel: '1' } });
118+
useStepsRequiredQuery();
119+
useStepsRequiredQuery({
120+
variables: { vlevel: '1' },
121+
enabled: false,
122+
});
123+
// @ts-expect-error selection is not available on this custom query
124+
useStepsRequiredQuery({ selection: { fields: { id: true } } });
105125
}
106126

107127
function reactQueryOptionsChecks() {
@@ -158,12 +178,18 @@ function reactQueryOptionsChecks() {
158178
// @ts-expect-error transformed query data should not expose connection shape
159179
transformedDatabases.data.databases;
160180

161-
const transformedCurrentUser = useCurrentUserQuery({
162-
select: (data) => data.currentUser.id,
181+
const currentUserResult = useCurrentUserQuery({
182+
selection: {
183+
fields: {
184+
id: true,
185+
username: true,
186+
},
187+
},
163188
placeholderData: (previousData) =>
164189
previousData ?? {
165190
currentUser: {
166191
id: 'fallback-user-id',
192+
username: 'fallback-user',
167193
},
168194
},
169195
enabled: false,
@@ -175,27 +201,18 @@ function reactQueryOptionsChecks() {
175201
return failureCount < 2;
176202
},
177203
});
178-
const transformedCurrentUserId: string | undefined = transformedCurrentUser.data;
179-
void transformedCurrentUserId;
180-
// @ts-expect-error transformed query data should not expose object shape
181-
transformedCurrentUser.data.currentUser;
204+
const currentUserId: string | undefined = currentUserResult.data?.currentUser.id;
205+
void currentUserId;
182206

183-
useGetObjectAtPathQuery({
184-
variables: undefined,
207+
useUserByUsernameQuery({
208+
variables: { username: 'dev' },
185209
selection: {
186210
fields: {
187211
id: true,
188212
},
189213
},
190214
enabled: false,
191215
staleTime: 5_000,
192-
gcTime: 60_000,
193-
placeholderData: {
194-
getObjectAtPath: {
195-
id: 'placeholder',
196-
},
197-
},
198-
select: (data) => data.getObjectAtPath.id,
199216
});
200217

201218
// @ts-expect-error unknown React Query option should be rejected
@@ -204,9 +221,9 @@ function reactQueryOptionsChecks() {
204221
// @ts-expect-error queryKey is owned by generated hooks
205222
useDatabasesQuery({ selection: { fields: { id: true } }, queryKey: ['override'] as const });
206223

207-
// @ts-expect-error queryFn is owned by generated hooks
208224
useDatabasesQuery({
209225
selection: { fields: { id: true } },
226+
// @ts-expect-error queryFn is owned by generated hooks
210227
queryFn: async () =>
211228
({
212229
databases: {
@@ -224,6 +241,14 @@ function reactQueryOptionsChecks() {
224241
selection: {
225242
fields: {
226243
clientMutationId: true,
244+
result: {
245+
select: {
246+
accessToken: true,
247+
isVerified: true,
248+
totpEnabled: true,
249+
userId: true,
250+
},
251+
},
227252
},
228253
},
229254
retry: 1,
@@ -243,16 +268,16 @@ function reactQueryOptionsChecks() {
243268
void context;
244269
},
245270
onSuccess: (data, variables) => {
246-
const clientMutationId = data.signIn.clientMutationId;
271+
const accessToken = data.signIn.result.accessToken;
247272
const email = variables.input.email;
248-
void clientMutationId;
273+
void accessToken;
249274
void email;
250275
},
251276
});
252277

253-
// @ts-expect-error mutationFn is owned by generated hooks
254278
useSignInMutation({
255279
selection: { fields: { clientMutationId: true } },
280+
// @ts-expect-error mutationFn is owned by generated hooks
256281
mutationFn: async () =>
257282
({
258283
signIn: {

0 commit comments

Comments
 (0)