fix: search bug
This commit is contained in:
239
tests/app/searchWorksResults.test.tsx
Normal file
239
tests/app/searchWorksResults.test.tsx
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* TDD Phase 1: RED - Write failing tests first
|
||||
*
|
||||
* 测试搜索结果页面的分页功能
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { render, waitFor, fireEvent } from '@testing-library/react-native'
|
||||
import { useRouter, useLocalSearchParams } from 'expo-router'
|
||||
import SearchWorksResultsScreen from '@/app/searchWorksResults'
|
||||
import { useWorksSearch } from '@/hooks/use-works-search'
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock('expo-router', () => ({
|
||||
useRouter: jest.fn(),
|
||||
useLocalSearchParams: jest.fn(),
|
||||
}))
|
||||
|
||||
jest.mock('@/hooks/use-works-search', () => ({
|
||||
useWorksSearch: jest.fn(),
|
||||
}))
|
||||
|
||||
jest.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string) => key,
|
||||
i18n: { language: 'zh-CN' },
|
||||
}),
|
||||
}))
|
||||
|
||||
jest.mock('@/components/SearchBar', () => 'SearchBar')
|
||||
jest.mock('@/components/WorksGallery', () => 'WorksGallery')
|
||||
|
||||
describe('SearchWorksResultsScreen - Pagination', () => {
|
||||
const mockRouter = {
|
||||
push: jest.fn(),
|
||||
back: jest.fn(),
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
;(useRouter as jest.Mock).mockReturnValue(mockRouter)
|
||||
;(useLocalSearchParams as jest.Mock).mockReturnValue({ q: '测试' })
|
||||
})
|
||||
|
||||
describe('Load More Functionality', () => {
|
||||
it('should load first page on initial render', () => {
|
||||
const mockUseWorksSearch = useWorksSearch as jest.Mock
|
||||
mockUseWorksSearch.mockReturnValue({
|
||||
data: {
|
||||
data: [
|
||||
{
|
||||
id: '1',
|
||||
createdAt: new Date('2025-01-15'),
|
||||
template: { id: 't1', name: 'Template 1' },
|
||||
status: 'completed',
|
||||
duration: 5,
|
||||
},
|
||||
],
|
||||
total: 50,
|
||||
page: 1,
|
||||
limit: 20,
|
||||
totalPages: 3,
|
||||
},
|
||||
works: [
|
||||
{
|
||||
id: '1',
|
||||
createdAt: new Date('2025-01-15'),
|
||||
template: { id: 't1', name: 'Template 1' },
|
||||
status: 'completed',
|
||||
duration: 5,
|
||||
},
|
||||
],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
})
|
||||
|
||||
render(<SearchWorksResultsScreen />)
|
||||
|
||||
// 验证初始调用使用 page: 1
|
||||
expect(mockUseWorksSearch).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
page: 1,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should accumulate results when loading more pages', async () => {
|
||||
const mockUseWorksSearch = useWorksSearch as jest.Mock
|
||||
|
||||
// 第一页数据
|
||||
const page1Data = [
|
||||
{
|
||||
id: '1',
|
||||
createdAt: new Date('2025-01-15'),
|
||||
template: { id: 't1', name: 'Template 1' },
|
||||
status: 'completed',
|
||||
duration: 5,
|
||||
},
|
||||
]
|
||||
|
||||
// 第二页数据
|
||||
const page2Data = [
|
||||
{
|
||||
id: '2',
|
||||
createdAt: new Date('2025-01-14'),
|
||||
template: { id: 't2', name: 'Template 2' },
|
||||
status: 'completed',
|
||||
duration: 10,
|
||||
},
|
||||
]
|
||||
|
||||
mockUseWorksSearch.mockReturnValue({
|
||||
data: {
|
||||
data: page1Data,
|
||||
total: 50,
|
||||
page: 1,
|
||||
limit: 20,
|
||||
totalPages: 3,
|
||||
},
|
||||
works: page1Data,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
loadMore: jest.fn(),
|
||||
})
|
||||
|
||||
const { rerender } = render(<SearchWorksResultsScreen />)
|
||||
|
||||
// 模拟加载第二页
|
||||
mockUseWorksSearch.mockReturnValue({
|
||||
data: {
|
||||
data: [...page1Data, ...page2Data],
|
||||
total: 50,
|
||||
page: 2,
|
||||
limit: 20,
|
||||
totalPages: 3,
|
||||
},
|
||||
works: [...page1Data, ...page2Data],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
loadMore: jest.fn(),
|
||||
})
|
||||
|
||||
rerender(<SearchWorksResultsScreen />)
|
||||
|
||||
// 验证结果累积
|
||||
expect(mockUseWorksSearch).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not load more when already loading', () => {
|
||||
const mockLoadMore = jest.fn()
|
||||
const mockUseWorksSearch = useWorksSearch as jest.Mock
|
||||
|
||||
mockUseWorksSearch.mockReturnValue({
|
||||
data: {
|
||||
data: [],
|
||||
total: 50,
|
||||
page: 1,
|
||||
limit: 20,
|
||||
totalPages: 3,
|
||||
},
|
||||
works: [],
|
||||
isLoading: true,
|
||||
error: null,
|
||||
loadMore: mockLoadMore,
|
||||
})
|
||||
|
||||
render(<SearchWorksResultsScreen />)
|
||||
|
||||
// 验证加载中时不应触发新的加载
|
||||
expect(mockLoadMore).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not load more when all pages loaded', () => {
|
||||
const mockLoadMore = jest.fn()
|
||||
const mockUseWorksSearch = useWorksSearch as jest.Mock
|
||||
|
||||
mockUseWorksSearch.mockReturnValue({
|
||||
data: {
|
||||
data: [
|
||||
{
|
||||
id: '1',
|
||||
createdAt: new Date('2025-01-15'),
|
||||
template: { id: 't1', name: 'Template 1' },
|
||||
status: 'completed',
|
||||
duration: 5,
|
||||
},
|
||||
],
|
||||
total: 1,
|
||||
page: 1,
|
||||
limit: 20,
|
||||
totalPages: 1,
|
||||
},
|
||||
works: [
|
||||
{
|
||||
id: '1',
|
||||
createdAt: new Date('2025-01-15'),
|
||||
template: { id: 't1', name: 'Template 1' },
|
||||
status: 'completed',
|
||||
duration: 5,
|
||||
},
|
||||
],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
loadMore: mockLoadMore,
|
||||
hasMore: false,
|
||||
})
|
||||
|
||||
render(<SearchWorksResultsScreen />)
|
||||
|
||||
// 验证没有更多数据时不应触发加载
|
||||
expect(mockLoadMore).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('Loading State', () => {
|
||||
it('should show loading indicator when loading more', () => {
|
||||
const mockUseWorksSearch = useWorksSearch as jest.Mock
|
||||
|
||||
mockUseWorksSearch.mockReturnValue({
|
||||
data: {
|
||||
data: [],
|
||||
total: 50,
|
||||
page: 2,
|
||||
limit: 20,
|
||||
totalPages: 3,
|
||||
},
|
||||
works: [],
|
||||
isLoading: true,
|
||||
error: null,
|
||||
isLoadingMore: true,
|
||||
})
|
||||
|
||||
const { getByTestId } = render(<SearchWorksResultsScreen />)
|
||||
|
||||
// 验证显示加载指示器
|
||||
expect(() => getByTestId('loading-more-indicator')).not.toThrow()
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user