Skip to content

Commit 761adba

Browse files
committed
fix: add NaN-safe header parsing and remove non-null assertions
- Add parseHeaderInt helper with parseInt and NaN validation - Replace non-null assertions with optional chaining in tests - Add tests for invalid header values (NaN handling)
1 parent 4d984cd commit 761adba

File tree

2 files changed

+38
-18
lines changed

2 files changed

+38
-18
lines changed

src/hooks/usePagination/usePagination.test.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ describe('extractPaginationMeta', () => {
3333
const result = extractPaginationMeta(httpMeta)
3434
expect(result.totalItems).toBe(0)
3535
})
36+
37+
test('defaults totalPages to 1 when header is invalid', () => {
38+
const httpMeta = createMockHttpMeta({ 'x-total-pages': 'invalid' })
39+
const result = extractPaginationMeta(httpMeta)
40+
expect(result.totalPages).toBe(1)
41+
})
42+
43+
test('defaults totalItems to 0 when header is invalid', () => {
44+
const httpMeta = createMockHttpMeta({ 'x-total-count': 'abc' })
45+
const result = extractPaginationMeta(httpMeta)
46+
expect(result.totalItems).toBe(0)
47+
})
48+
49+
test('defaults totalPages to 1 when header is empty string', () => {
50+
const httpMeta = createMockHttpMeta({ 'x-total-pages': '' })
51+
const result = extractPaginationMeta(httpMeta)
52+
expect(result.totalPages).toBe(1)
53+
})
3654
})
3755

3856
describe('usePagination', () => {
@@ -96,10 +114,9 @@ describe('usePagination', () => {
96114
})
97115

98116
expect(setCurrentPage).toHaveBeenCalled()
99-
const call = setCurrentPage.mock.calls[0]
100-
expect(call).toBeDefined()
101-
const updateFn = call![0] as (prev: number) => number
102-
expect(updateFn(3)).toBe(2)
117+
const updateFn = setCurrentPage.mock.calls[0]?.[0] as ((prev: number) => number) | undefined
118+
expect(updateFn).toBeDefined()
119+
expect(updateFn?.(3)).toBe(2)
103120
})
104121

105122
test('handleNextPage increments page', () => {
@@ -114,10 +131,9 @@ describe('usePagination', () => {
114131
})
115132

116133
expect(setCurrentPage).toHaveBeenCalled()
117-
const call = setCurrentPage.mock.calls[0]
118-
expect(call).toBeDefined()
119-
const updateFn = call![0] as (prev: number) => number
120-
expect(updateFn(3)).toBe(4)
134+
const updateFn = setCurrentPage.mock.calls[0]?.[0] as ((prev: number) => number) | undefined
135+
expect(updateFn).toBeDefined()
136+
expect(updateFn?.(3)).toBe(4)
121137
})
122138

123139
test('handleLastPage sets page to totalPages', () => {
@@ -163,10 +179,9 @@ describe('usePagination', () => {
163179
result.current.handlePreviousPage()
164180
})
165181

166-
const call = setCurrentPage.mock.calls[0]
167-
expect(call).toBeDefined()
168-
const updateFn = call![0] as (prev: number) => number
169-
expect(updateFn(1)).toBe(1)
182+
const updateFn = setCurrentPage.mock.calls[0]?.[0] as ((prev: number) => number) | undefined
183+
expect(updateFn).toBeDefined()
184+
expect(updateFn?.(1)).toBe(1)
170185
})
171186

172187
test('handleNextPage on last page stays on last page', () => {
@@ -180,10 +195,9 @@ describe('usePagination', () => {
180195
result.current.handleNextPage()
181196
})
182197

183-
const call = setCurrentPage.mock.calls[0]
184-
expect(call).toBeDefined()
185-
const updateFn = call![0] as (prev: number) => number
186-
expect(updateFn(5)).toBe(5)
198+
const updateFn = setCurrentPage.mock.calls[0]?.[0] as ((prev: number) => number) | undefined
199+
expect(updateFn).toBeDefined()
200+
expect(updateFn?.(5)).toBe(5)
187201
})
188202
})
189203

src/hooks/usePagination/usePagination.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@ type PaginationState = {
1212
setItemsPerPage: React.Dispatch<React.SetStateAction<PaginationItemsPerPage>>
1313
}
1414

15+
function parseHeaderInt(value: string | null, defaultValue: number): number {
16+
if (value === null) return defaultValue
17+
const parsed = parseInt(value, 10)
18+
return Number.isNaN(parsed) ? defaultValue : parsed
19+
}
20+
1521
export function extractPaginationMeta(httpMeta?: HttpMeta | null) {
1622
return {
17-
totalPages: Number(httpMeta?.response.headers.get('x-total-pages') ?? 1),
18-
totalItems: Number(httpMeta?.response.headers.get('x-total-count') ?? 0),
23+
totalPages: parseHeaderInt(httpMeta?.response.headers.get('x-total-pages') ?? null, 1),
24+
totalItems: parseHeaderInt(httpMeta?.response.headers.get('x-total-count') ?? null, 0),
1925
}
2026
}
2127

0 commit comments

Comments
 (0)