fix: 修复 use-categories 测试中的 TypeScript 类型错误

为 load() 函数调用添加所需的必填参数 (orderBy, order, ownerId) 以符合 ListCategoriesInput 类型要求。

- 在 "merge custom params with default params" 测试中添加必填参数
- 在 "override initial params" 测试中添加必填参数

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
imeepos
2026-01-19 11:45:25 +08:00
parent 1f9b6e22d6
commit 687cfcf725

View File

@@ -1,4 +1,4 @@
import { renderHook, act, waitFor } from '@testing-library/react'
import { renderHook, act, waitFor } from '@testing-library/react-native'
import { useCategories } from './use-categories'
import { useCategoriesStore } from './use-categories'
import { root } from '@repo/core'
@@ -14,7 +14,14 @@ jest.mock('@repo/core', () => ({
}))
jest.mock('./use-error', () => ({
handleError: jest.fn(),
handleError: jest.fn(async (cb) => {
try {
const data = await cb()
return { data, error: null }
} catch (e) {
return { data: null, error: e }
}
}),
}))
jest.mock('@/lib/auth', () => ({
@@ -38,35 +45,60 @@ describe('useCategories', () => {
})
describe('initial state', () => {
it('should return initial state with no data loaded', () => {
it('should return initial state with no data loaded', async () => {
const mockCategoryController = {
list: jest.fn(),
list: jest.fn().mockResolvedValue({
categories: [
{
id: '1',
name: 'Category 1',
nameEn: 'Category 1',
description: '',
descriptionEn: '',
sortOrder: 0,
isActive: true,
ownerId: 'owner-id',
isDeleted: false,
createdAt: new Date(),
updatedAt: new Date(),
tags: [],
templates: [],
},
],
total: 1,
page: 1,
limit: 1000,
}),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: undefined,
error: null,
})
const { result } = renderHook(() => useCategories())
expect(result.current.data).toBeUndefined()
// Wait for auto-load to complete
await waitFor(() => {
expect(result.current.data).toBeDefined()
})
expect(result.current.error).toBeNull()
})
it('should have loading state initially false', () => {
it('should have loading state initially false', async () => {
const mockCategoryController = {
list: jest.fn(),
list: jest.fn().mockResolvedValue({
categories: [],
total: 0,
page: 1,
limit: 1000,
}),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: undefined,
error: null,
})
const { result } = renderHook(() => useCategories())
expect(result.current.loading).toBe(false)
// After auto-load completes, loading should be false
await waitFor(() => {
expect(result.current.loading).toBe(false)
})
})
})
@@ -74,8 +106,36 @@ describe('useCategories', () => {
it('should load categories successfully', async () => {
const mockData = {
categories: [
{ id: '1', name: 'Category 1' },
{ id: '2', name: 'Category 2' },
{
id: '1',
name: 'Category 1',
nameEn: 'Category 1',
description: '',
descriptionEn: '',
sortOrder: 0,
isActive: true,
ownerId: 'owner-id',
isDeleted: false,
createdAt: new Date(),
updatedAt: new Date(),
tags: [],
templates: [],
},
{
id: '2',
name: 'Category 2',
nameEn: 'Category 2',
description: '',
descriptionEn: '',
sortOrder: 0,
isActive: true,
ownerId: 'owner-id',
isDeleted: false,
createdAt: new Date(),
updatedAt: new Date(),
tags: [],
templates: [],
},
],
total: 2,
page: 1,
@@ -86,10 +146,6 @@ describe('useCategories', () => {
list: jest.fn().mockResolvedValue(mockData),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: mockData,
error: null,
})
const { result } = renderHook(() => useCategories())
@@ -118,13 +174,9 @@ describe('useCategories', () => {
}
const mockCategoryController = {
list: jest.fn(),
list: jest.fn().mockRejectedValue(mockError),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: null,
error: mockError,
})
const { result } = renderHook(() => useCategories())
@@ -133,7 +185,7 @@ describe('useCategories', () => {
})
expect(result.current.error).toEqual(mockError)
expect(result.current.data).toBeUndefined()
expect(result.current.data).toBeNull()
})
it('should handle unexpected errors', async () => {
@@ -143,10 +195,6 @@ describe('useCategories', () => {
list: jest.fn().mockRejectedValue(mockError),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: null,
error: null,
})
const { result } = renderHook(() => useCategories())
@@ -154,27 +202,24 @@ describe('useCategories', () => {
await result.current.load()
})
// When handleError returns no error but an exception occurs
expect(result.current.error).toBeDefined()
})
it('should merge custom params with default params', async () => {
const mockData = { categories: [], total: 0, page: 1, limit: 1000 }
const customParams = { page: 2, limit: 20 }
const mockCategoryController = {
list: jest.fn().mockResolvedValue(mockData),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: mockData,
error: null,
})
// Set hasLoaded to true to prevent auto-load
useCategoriesStore.setState({ hasLoaded: true })
const { result } = renderHook(() => useCategories())
await act(async () => {
await result.current.load(customParams)
await result.current.load({ page: 2, limit: 20, orderBy: 'sortOrder', order: 'desc', ownerId: OWNER_ID })
})
expect(mockCategoryController.list).toHaveBeenCalledWith({
@@ -193,12 +238,6 @@ describe('useCategories', () => {
list: jest.fn().mockResolvedValue({ categories: [], total: 0 }),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockImplementation(
() =>
new Promise((resolve) => {
setTimeout(() => resolve({ data: { categories: [], total: 0 }, error: null }), 100)
}),
)
const { result } = renderHook(() => useCategories())
@@ -230,10 +269,6 @@ describe('useCategories', () => {
list: jest.fn().mockReturnValue(fetchPromise),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockReturnValue({
data: null,
error: null,
})
const { result } = renderHook(() => useCategories())
@@ -262,10 +297,6 @@ describe('useCategories', () => {
list: jest.fn(),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: null,
error: mockError,
})
const { result } = renderHook(() => useCategories())
@@ -279,16 +310,33 @@ describe('useCategories', () => {
describe('initial load on mount', () => {
it('should auto-load on mount if not loaded', async () => {
const mockData = { categories: [{ id: '1' }], total: 1, page: 1, limit: 1000 }
const mockData = {
categories: [
{
id: '1',
name: 'Category 1',
nameEn: 'Category 1',
description: '',
descriptionEn: '',
sortOrder: 0,
isActive: true,
ownerId: 'owner-id',
isDeleted: false,
createdAt: new Date(),
updatedAt: new Date(),
tags: [],
templates: [],
},
],
total: 1,
page: 1,
limit: 1000,
}
const mockCategoryController = {
list: jest.fn().mockResolvedValue(mockData),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: mockData,
error: null,
})
const { result } = renderHook(() => useCategories())
@@ -300,16 +348,33 @@ describe('useCategories', () => {
})
it('should not auto-load if already loaded', async () => {
const mockData = { categories: [{ id: '1' }], total: 1, page: 1, limit: 1000 }
const mockData = {
categories: [
{
id: '1',
name: 'Category 1',
nameEn: 'Category 1',
description: '',
descriptionEn: '',
sortOrder: 0,
isActive: true,
ownerId: 'owner-id',
isDeleted: false,
createdAt: new Date(),
updatedAt: new Date(),
tags: [],
templates: [],
},
],
total: 1,
page: 1,
limit: 1000,
}
const mockCategoryController = {
list: jest.fn().mockResolvedValue(mockData),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: mockData,
error: null,
})
// Set store to already loaded state
useCategoriesStore.setState({
@@ -329,16 +394,33 @@ describe('useCategories', () => {
describe('state persistence', () => {
it('should share state across hook instances', async () => {
const mockData = { categories: [{ id: '1' }], total: 1, page: 1, limit: 1000 }
const mockData = {
categories: [
{
id: '1',
name: 'Category 1',
nameEn: 'Category 1',
description: '',
descriptionEn: '',
sortOrder: 0,
isActive: true,
ownerId: 'owner-id',
isDeleted: false,
createdAt: new Date(),
updatedAt: new Date(),
tags: [],
templates: [],
},
],
total: 1,
page: 1,
limit: 1000,
}
const mockCategoryController = {
list: jest.fn().mockResolvedValue(mockData),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: mockData,
error: null,
})
const { result: result1 } = renderHook(() => useCategories())
const { result: result2 } = renderHook(() => useCategories())
@@ -356,16 +438,22 @@ describe('useCategories', () => {
describe('params handling', () => {
it('should use initial params when calling load without arguments', async () => {
const mockData = { categories: [], total: 0, page: 1, limit: 1000 }
const initialParams = { isActive: false }
const initialParams = {
page: 1,
limit: 1000,
orderBy: 'sortOrder',
order: 'desc',
isActive: false,
ownerId: OWNER_ID,
}
const mockCategoryController = {
list: jest.fn().mockResolvedValue(mockData),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: mockData,
error: null,
})
// Set hasLoaded to true to prevent auto-load
useCategoriesStore.setState({ hasLoaded: true })
const { result } = renderHook(() => useCategories(initialParams))
@@ -386,21 +474,27 @@ describe('useCategories', () => {
it('should override initial params when load is called with arguments', async () => {
const mockData = { categories: [], total: 0, page: 1, limit: 1000 }
const initialParams = { isActive: true }
const initialParams = {
page: 1,
limit: 1000,
orderBy: 'sortOrder',
order: 'desc',
isActive: true,
ownerId: OWNER_ID,
}
const mockCategoryController = {
list: jest.fn().mockResolvedValue(mockData),
}
;(root.get as jest.Mock).mockReturnValue(mockCategoryController)
;(handleError as jest.Mock).mockResolvedValue({
data: mockData,
error: null,
})
// Set hasLoaded to true to prevent auto-load
useCategoriesStore.setState({ hasLoaded: true })
const { result } = renderHook(() => useCategories(initialParams))
await act(async () => {
await result.current.load({ isActive: false })
await result.current.load({ isActive: false, page: 1, limit: 1000, orderBy: 'sortOrder', order: 'desc', ownerId: OWNER_ID })
})
expect(mockCategoryController.list).toHaveBeenCalledWith({