Skip to content

Commit bdaea99

Browse files
author
devgioele
committed
make default query optional
1 parent 5aca733 commit bdaea99

11 files changed

Lines changed: 156 additions & 117 deletions

File tree

src/engine/pagination.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,14 @@ const parsePagination = (query: Query): Partial<PaginationQuery> => {
4646
}
4747
}
4848

49-
export const useAbstractQueryAndPagination = <T extends AbstractQuery>(
50-
defaultQuery: T,
51-
parseQuery: ParseQuery<T>,
49+
export const useAbstractQueryAndPagination = <
50+
TQuery extends AbstractQuery,
51+
TDefaultQuery extends Partial<TQuery>,
52+
>(
5253
router: Router,
53-
defaultPagination?: PaginationQuery,
54+
parseQuery: ParseQuery<TQuery>,
55+
defaultQuery: TDefaultQuery,
56+
defaultPagination?: Partial<PaginationQuery>,
5457
options?: Partial<AbstractQueryOptions>,
5558
) => {
5659
const mergedDefaultPagination = {
@@ -63,9 +66,9 @@ export const useAbstractQueryAndPagination = <T extends AbstractQuery>(
6366
}
6467

6568
const { query, setQuery } = useAbstractQuery(
66-
mergedDefaultQueryAndPagination,
67-
parseQuery,
6869
router,
70+
parseQuery,
71+
mergedDefaultQueryAndPagination,
6972
options,
7073
)
7174

@@ -74,15 +77,18 @@ export const useAbstractQueryAndPagination = <T extends AbstractQuery>(
7477
setQuery: setPagination,
7578
resetQuery: resetPagination,
7679
} = useAbstractQuery(
77-
mergedDefaultPagination,
78-
parsePagination,
7980
router,
81+
parsePagination,
82+
mergedDefaultPagination,
8083
options,
8184
)
8285

8386
return {
8487
query,
85-
setQuery: (query: Partial<T>, options?: Partial<ChangeQueryOptions>) => {
88+
setQuery: (
89+
query: Partial<TQuery>,
90+
options?: Partial<ChangeQueryOptions>,
91+
) => {
8692
const mergedOptions = { ...DEFAULT_CHANGE_QUERY_OPTIONS, ...options }
8793
setQuery({
8894
...query,

src/engine/query.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,17 @@ export type ParseQuery<T> = (query: Query) => Partial<T>
2424

2525
export type Router = {
2626
/**
27-
* @returns The current query.
27+
* @returns The current query. If a property is undefined by the current query, the corresponding property of the default query is taken, which might be undefined too.
2828
*/
2929
getQuery: (defaultQuery: Query) => Query
3030

3131
/**
32-
* Updates the query by merging the given query with the current query.
32+
* Updates the query by merging the given query with the current query. If a property is undefined by the given query and the current query, the corresponding default query is taken, which might be undefined too.
3333
*/
3434
setQuery: (query: Partial<Query>, defaultQuery: Query) => void
3535
}
3636

37-
export const useQuery = <T extends Query>(defaultQuery: T, router: Router) => {
37+
export const useQuery = <T extends Query>(router: Router, defaultQuery: T) => {
3838
const resetQuery = useCallback(() => {
3939
router.setQuery(defaultQuery, defaultQuery)
4040
}, [router, defaultQuery])
@@ -71,10 +71,13 @@ const DEFAULT_ABSTRACT_QUERY_OPTIONS: AbstractQueryOptions = {
7171
},
7272
}
7373

74-
export const useAbstractQuery = <T extends AbstractQuery>(
75-
defaultQuery: T,
76-
parseQuery: ParseQuery<T>,
74+
export const useAbstractQuery = <
75+
TQuery extends AbstractQuery,
76+
TDefaultQuery extends Partial<TQuery>,
77+
>(
7778
router: Router,
79+
parseQuery: ParseQuery<TQuery>,
80+
defaultQuery: TDefaultQuery,
7881
options?: Partial<AbstractQueryOptions>,
7982
) => {
8083
const mergedOptions = useMemo(
@@ -88,12 +91,12 @@ export const useAbstractQuery = <T extends AbstractQuery>(
8891
)
8992

9093
const { query, setQuery, resetQuery } = useQuery(
91-
convertedDefaultQuery,
9294
router,
95+
convertedDefaultQuery,
9396
)
9497

95-
const parsedQuery: T = useMemo(() => {
96-
let parsed: Partial<T>
98+
const parsedQuery = useMemo(() => {
99+
let parsed: Partial<TQuery>
97100
try {
98101
parsed = parseQuery(query)
99102
} catch (e) {
@@ -106,7 +109,7 @@ export const useAbstractQuery = <T extends AbstractQuery>(
106109
}, [defaultQuery, parseQuery, query])
107110

108111
const setAbstractQuery = useCallback(
109-
(query: Partial<T>) => {
112+
(query: Partial<TQuery>) => {
110113
setQuery(mergedOptions.convertToQuery(query))
111114
},
112115
[setQuery, mergedOptions],

src/routers/__test__/inMemory.test.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { act, renderHook } from '@testing-library/react'
22
import { z } from 'zod'
3-
import { NonNullableRecord } from '../../utils'
43
import { useQuery, useQueryAndPagination } from '../../zod/routers/inMemory'
54
import { usePagination } from '../inMemory'
65

@@ -10,8 +9,8 @@ describe('InMemory', () => {
109
})
1110

1211
const useInMemoryQueryWithSearch = (
13-
defaultQuery: NonNullableRecord<z.infer<typeof searchSchema>>,
14-
) => useQuery(defaultQuery, searchSchema)
12+
defaultQuery: Partial<z.output<typeof searchSchema>> = {},
13+
) => useQuery(searchSchema, defaultQuery)
1514

1615
test('should set default page and size', () => {
1716
const page = 0
@@ -53,7 +52,7 @@ describe('InMemory', () => {
5352
const page = 2
5453

5554
const { result } = renderHook(() =>
56-
useQueryAndPagination({ search: '' }, searchSchema),
55+
useQueryAndPagination(searchSchema, { search: '' }),
5756
)
5857

5958
act(() => {
@@ -90,7 +89,7 @@ describe('InMemory', () => {
9089
const page = 2
9190

9291
const { result } = renderHook(() =>
93-
useQueryAndPagination({ search: defaultSearch }, searchSchema),
92+
useQueryAndPagination(searchSchema, { search: defaultSearch }),
9493
)
9594

9695
act(() => {
@@ -125,7 +124,7 @@ describe('InMemory', () => {
125124
const page = 2
126125

127126
const { result } = renderHook(() =>
128-
useQueryAndPagination({ search: defaultSearch }, searchSchema),
127+
useQueryAndPagination(searchSchema, { search: defaultSearch }),
129128
)
130129

131130
act(() => {
@@ -159,7 +158,7 @@ describe('InMemory', () => {
159158
})
160159

161160
const { result } = renderHook(() =>
162-
useQuery({ search: '', department: '' }, schema),
161+
useQuery(schema, { search: '', department: '' }),
163162
)
164163

165164
act(() => {
@@ -178,7 +177,7 @@ describe('InMemory', () => {
178177
const search = ''
179178

180179
const { result } = renderHook(() =>
181-
useQuery({ search: 'Default search' }, searchSchema),
180+
useQuery(searchSchema, { search: 'Default search' }),
182181
)
183182

184183
act(() => {

src/routers/__test__/nextRouter.test.ts

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { act, renderHook } from '@testing-library/react'
22
import router from 'next/router'
33
import { z } from 'zod'
44
import { vi } from 'vitest'
5-
import { NonNullableRecord } from '../../utils'
65
import { useQuery, useQueryAndPagination } from '../../zod/routers/nextRouter'
76
import { usePagination } from '../nextRouter'
87

@@ -19,8 +18,8 @@ describe('NextRouter', () => {
1918
})
2019

2120
const useNextRouterQueryWithSearch = (
22-
defaultQuery: NonNullableRecord<z.infer<typeof searchSchema>>,
23-
) => useQuery(defaultQuery, searchSchema)
21+
defaultQuery: Partial<z.infer<typeof searchSchema>> = {},
22+
) => useQuery(searchSchema, defaultQuery)
2423

2524
test('should set default page and size', () => {
2625
const page = 0
@@ -64,7 +63,7 @@ describe('NextRouter', () => {
6463
const page = 2
6564

6665
const { result } = renderHook(() =>
67-
useQueryAndPagination({ search: '' }, searchSchema),
66+
useQueryAndPagination(searchSchema, { search: '' }),
6867
)
6968

7069
act(() => {
@@ -104,7 +103,7 @@ describe('NextRouter', () => {
104103
const page = 2
105104

106105
const { result } = renderHook(() =>
107-
useQueryAndPagination({ search: defaultSearch }, searchSchema),
106+
useQueryAndPagination(searchSchema, { search: defaultSearch }),
108107
)
109108

110109
act(() => {
@@ -146,7 +145,7 @@ describe('NextRouter', () => {
146145
const page = 2
147146

148147
const { result } = renderHook(() =>
149-
useQueryAndPagination({ search: defaultSearch }, searchSchema),
148+
useQueryAndPagination(searchSchema, { search: defaultSearch }),
150149
)
151150

152151
act(() => {
@@ -194,17 +193,14 @@ describe('NextRouter', () => {
194193
})
195194

196195
const { result } = renderHook(() =>
197-
useQuery(
198-
{
199-
search: '',
200-
department: '',
201-
age: defaultAge,
202-
birthDate: defaultBirthDate,
203-
netWorth: defaultNetWorth,
204-
darkMode: defaultDarkMode,
205-
},
206-
schema,
207-
),
196+
useQuery(schema, {
197+
search: '',
198+
department: '',
199+
age: defaultAge,
200+
birthDate: defaultBirthDate,
201+
netWorth: defaultNetWorth,
202+
darkMode: defaultDarkMode,
203+
}),
208204
)
209205

210206
act(() => {
@@ -226,7 +222,7 @@ describe('NextRouter', () => {
226222
const greeting = 'hello'
227223
router.query = { greeting }
228224

229-
const { result } = renderHook(() => useQuery({ search: '' }, searchSchema))
225+
const { result } = renderHook(() => useQuery(searchSchema, { search: '' }))
230226

231227
act(() => {
232228
result.current.setQuery({ search: 'Max' })
@@ -242,7 +238,7 @@ describe('NextRouter', () => {
242238
router.query = { search: 'Max' }
243239

244240
const { result } = renderHook(() =>
245-
useQuery({ search: defaultSearch }, searchSchema),
241+
useQuery(searchSchema, { search: defaultSearch }),
246242
)
247243

248244
act(() => {
@@ -257,7 +253,7 @@ describe('NextRouter', () => {
257253
const search = ''
258254

259255
const { result } = renderHook(() =>
260-
useQuery({ search: 'Default search' }, searchSchema),
256+
useQuery(searchSchema, { search: 'Default search' }),
261257
)
262258

263259
act(() => {
@@ -267,4 +263,25 @@ describe('NextRouter', () => {
267263
expect(result.current.query.search).toBe(search)
268264
expect(router.query.search).toBe(search)
269265
})
266+
267+
test('passing no default query should return undefined for a property that is not in the query', () => {
268+
const { result } = renderHook(() =>
269+
useQuery(z.object({ department: z.string() })),
270+
)
271+
272+
expect(result.current.query.department).toBeUndefined()
273+
})
274+
275+
test('the query should be a merge of the default query and the current query', () => {
276+
const defaultRole = 'ADMIN'
277+
278+
const { result } = renderHook(() =>
279+
useQuery(z.object({ department: z.string(), role: z.string() }), {
280+
role: defaultRole,
281+
}),
282+
)
283+
284+
expect(result.current.query.department).toBeUndefined()
285+
expect(result.current.query.role).toBe(defaultRole)
286+
})
270287
})

src/routers/__test__/reactRouter.test.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { act, renderHook } from '@testing-library/react'
22
import { z } from 'zod'
33
import { BrowserRouter } from 'react-router-dom'
4-
import { NonNullableRecord } from '../../utils'
54
import { useQuery, useQueryAndPagination } from '../../zod/routers/reactRouter'
65
import { usePagination } from '../reactRouter'
76

@@ -24,8 +23,8 @@ describe('ReactRouter', () => {
2423
})
2524

2625
const useReactRouterQueryWithSearch = (
27-
defaultQuery: NonNullableRecord<z.infer<typeof searchSchema>>,
28-
) => useQuery(defaultQuery, searchSchema)
26+
defaultQuery: Partial<z.infer<typeof searchSchema>> = {},
27+
) => useQuery(searchSchema, defaultQuery)
2928

3029
test('should set default page and size', () => {
3130
const page = 0
@@ -71,7 +70,7 @@ describe('ReactRouter', () => {
7170
const page = 2
7271

7372
const { result } = renderHookWithContext(() =>
74-
useQueryAndPagination({ search: '' }, searchSchema),
73+
useQueryAndPagination(searchSchema, { search: '' }),
7574
)
7675

7776
act(() => {
@@ -111,7 +110,7 @@ describe('ReactRouter', () => {
111110
const page = 2
112111

113112
const { result } = renderHookWithContext(() =>
114-
useQueryAndPagination({ search: defaultSearch }, searchSchema),
113+
useQueryAndPagination(searchSchema, { search: defaultSearch }),
115114
)
116115

117116
act(() => {
@@ -149,7 +148,7 @@ describe('ReactRouter', () => {
149148
const page = 2
150149

151150
const { result } = renderHookWithContext(() =>
152-
useQueryAndPagination({ search: defaultSearch }, searchSchema),
151+
useQueryAndPagination(searchSchema, { search: defaultSearch }),
153152
)
154153

155154
act(() => {
@@ -186,7 +185,7 @@ describe('ReactRouter', () => {
186185
})
187186

188187
const { result } = renderHookWithContext(() =>
189-
useQuery({ search: '', department: '' }, schema),
188+
useQuery(schema, { search: '', department: '' }),
190189
)
191190

192191
act(() => {
@@ -207,7 +206,7 @@ describe('ReactRouter', () => {
207206
window.history.pushState({}, '', `/?greeting=${greeting}`)
208207

209208
const { result } = renderHookWithContext(() =>
210-
useQuery({ search: '' }, searchSchema),
209+
useQuery(searchSchema, { search: '' }),
211210
)
212211

213212
act(() => {
@@ -226,7 +225,7 @@ describe('ReactRouter', () => {
226225
window.history.pushState({}, '', `/?search=Max`)
227226

228227
const { result } = renderHookWithContext(() =>
229-
useQuery({ search: defaultSearch }, searchSchema),
228+
useQuery(searchSchema, { search: defaultSearch }),
230229
)
231230

232231
act(() => {
@@ -241,7 +240,7 @@ describe('ReactRouter', () => {
241240
const search = ''
242241

243242
const { result } = renderHookWithContext(() =>
244-
useQuery({ search: 'Default search' }, searchSchema),
243+
useQuery(searchSchema, { search: 'Default search' }),
245244
)
246245

247246
act(() => {

0 commit comments

Comments
 (0)