fix: 修复 Jest 测试配置和 useCategories hook 实现

- 修复 jest.setup.js 中不存在的 NativeAnimatedHelper 模块引用
- 优化 jest.config.js 配置,分离 js 和 ts/tsx 的转换配置
- 添加 @testing-library/react 依赖
- 导出 useCategoriesStore 以供测试使用
- 修复 useCategories hook 的参数合并逻辑,确保 inputParams 正确覆盖默认参数
- 修复错误处理时 data 状态设置为 null
- 更新 CategoriesState 类型定义,允许 data 为 null

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
imeepos 2026-01-19 11:46:51 +08:00
parent 687cfcf725
commit a1544ec85f
5 changed files with 2904 additions and 37 deletions

2865
bun.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -9,13 +9,13 @@ import { OWNER_ID } from '@/lib/auth'
import { handleError } from './use-error'
interface CategoriesState {
data: ListCategoriesResult | undefined
data: ListCategoriesResult | null | undefined
loading: boolean
error: ApiError | null
hasLoaded: boolean
}
const useCategoriesStore = create<CategoriesState>((set) => ({
export const useCategoriesStore = create<CategoriesState>((set) => ({
data: undefined,
loading: false,
error: null,
@ -37,22 +37,26 @@ export const useCategories = (params?: ListCategoriesInput) => {
try {
setLocalLoading(true)
useCategoriesStore.setState({ loading: true })
const category = root.get(CategoryController)
const { data, error } = await handleError(
async () =>
await category.list({
page: 1,
limit: 1000,
isActive: true,
orderBy: 'sortOrder',
order: 'desc',
withChildren: true,
ownerId: OWNER_ID,
...(inputParams ?? params),
}),
)
// Merge params: inputParams > params > defaults
const mergedParams = {
page: 1,
limit: 1000,
isActive: true,
orderBy: 'sortOrder' as const,
order: 'desc' as const,
withChildren: true,
ownerId: OWNER_ID,
...(params ?? {}),
...(inputParams ?? {}),
}
const { data, error } = await handleError(async () => await category.list(mergedParams))
if (error) {
useCategoriesStore.setState({ error, loading: false, hasLoaded: true })
useCategoriesStore.setState({ data: null, error, loading: false, hasLoaded: true })
return
}
useCategoriesStore.setState({ data, loading: false, error: null, hasLoaded: true })

View File

@ -1,5 +1,3 @@
const { defaults: tsjPresets } = require('ts-jest/presets')
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'react-native',
@ -7,7 +5,14 @@ module.exports = {
'node_modules/(?!(@react-native|react-native|@react-navigation|expo|expo-.*|@expo|@react-native-community|react-native-.*|@shopify|@better-auth|nativewind|react-native-css-interop)/)',
],
transform: {
'^.+\\.(js|jsx|ts|tsx)$': ['ts-jest', tsjPresets.defaults],
'^.+\\.(js|jsx)$': 'babel-jest',
'^.+\\.(ts|tsx)$': ['ts-jest', {
tsconfig: {
jsx: 'react',
esModuleInterop: true,
allowSyntheticDefaultImports: true,
},
}],
},
testMatch: ['**/__tests__/**/*.(test|spec).(js|jsx|ts|tsx)', '**/*.(test|spec).(js|jsx|ts|tsx)'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
@ -26,13 +31,4 @@ module.exports = {
'!**/jest.setup.js',
'!**/metro.config.js',
],
globals: {
'ts-jest': {
tsconfig: {
jsx: 'react',
esModuleInterop: true,
allowSyntheticDefaultImports: true,
},
},
},
}

View File

@ -1,7 +1,8 @@
import '@testing-library/jest-native/extend-expect'
require('@testing-library/jest-native/extend-expect')
// Mock react-native modules
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper')
// Note: NativeAnimatedHelper may not be needed in newer React Native versions
// jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper')
// Mock expo modules
jest.mock('expo-constants', () => ({

View File

@ -87,6 +87,10 @@
"@babel/cli": "^7.28.3",
"@babel/core": "^7.28.5",
"@babel/preset-env": "^7.28.5",
"@testing-library/jest-native": "^5.4.3",
"@testing-library/react": "^12.0.0",
"@testing-library/react-native": "^12.8.1",
"@types/jest": "^29.5.14",
"@types/react": "^19.2.1",
"@types/react-native": "^0.72.8",
"@typescript-eslint/eslint-plugin": "^8.33.0",
@ -105,16 +109,13 @@
"eslint-plugin-tailwindcss": "^3.18.0",
"eslint-plugin-unicorn": "^59.0.1",
"eslint-plugin-unused-imports": "^4.1.4",
"jest": "^29.7.0",
"prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.12",
"tailwindcss": "3.4.4",
"typescript": "~5.9.2",
"@testing-library/jest-native": "^5.4.3",
"@testing-library/react-native": "^12.8.1",
"@types/jest": "^29.5.14",
"jest": "^29.7.0",
"react-test-renderer": "19.1.0",
"ts-jest": "^29.2.5"
"tailwindcss": "3.4.4",
"ts-jest": "^29.2.5",
"typescript": "~5.9.2"
},
"private": true
}