This commit is contained in:
imeepos
2026-01-29 16:00:21 +08:00
parent 7e6de68891
commit 7c3b3c066c
5 changed files with 183 additions and 24 deletions

View File

@@ -23,6 +23,10 @@ jest.mock('react-i18next', () => ({
// Mock expo-router
const mockPush = jest.fn()
const mockUseFocusEffect = jest.fn((callback: () => void) => {
// 立即执行 callback 来模拟页面获得焦点
callback()
})
jest.mock('expo-router', () => ({
useRouter: () => ({
push: mockPush,
@@ -30,6 +34,7 @@ jest.mock('expo-router', () => ({
back: jest.fn(),
}),
useLocalSearchParams: () => ({}),
useFocusEffect: (callback: () => void) => mockUseFocusEffect(callback),
}))
// Mock hooks
@@ -87,6 +92,7 @@ jest.mock('@/hooks/use-messages', () => ({
messages: mockMessages,
loading: false,
loadingMore: false,
refreshing: false,
error: null,
execute: mockExecute,
refetch: mockRefetch,
@@ -524,9 +530,10 @@ describe('MessageScreen', () => {
})
describe('Initial Data Fetch', () => {
it('should call execute on mount', () => {
it('should call refetch on mount via useFocusEffect', () => {
render(<MessageScreen />)
expect(mockExecute).toHaveBeenCalled()
// 现在使用 useFocusEffect + refetch 替代 useEffect + execute
expect(mockRefetch).toHaveBeenCalled()
})
it('should call announcement execute on mount', () => {
@@ -534,4 +541,144 @@ describe('MessageScreen', () => {
expect(mockAnnouncementExecute).toHaveBeenCalled()
})
})
describe('Pull-to-Refresh', () => {
beforeEach(() => {
jest.clearAllMocks()
const { useMessages } = require('@/hooks/use-messages')
useMessages.mockReturnValue({
messages: mockMessages,
loading: false,
loadingMore: false,
refreshing: false,
error: null,
execute: mockExecute,
refetch: mockRefetch,
loadMore: mockLoadMore,
hasMore: true,
})
const { useAnnouncements } = require('@/hooks/use-announcements')
useAnnouncements.mockReturnValue({
announcements: mockAnnouncements,
loading: false,
error: null,
execute: mockAnnouncementExecute,
refetch: jest.fn(),
loadMore: jest.fn(),
hasMore: false,
})
})
it('should render FlatList with RefreshControl', () => {
const { getByTestId } = render(<MessageScreen />)
const flatList = getByTestId('message-list')
expect(flatList.props.refreshControl).toBeTruthy()
})
it('should call refetch when pull-to-refresh is triggered', async () => {
const { getByTestId } = render(<MessageScreen />)
const flatList = getByTestId('message-list')
// 触发 onRefresh
const refreshControl = flatList.props.refreshControl
refreshControl.props.onRefresh()
await waitFor(() => {
expect(mockRefetch).toHaveBeenCalled()
})
})
it('should call executeAnnouncements when pull-to-refresh is triggered', async () => {
const { getByTestId } = render(<MessageScreen />)
const flatList = getByTestId('message-list')
// 触发 onRefresh
const refreshControl = flatList.props.refreshControl
refreshControl.props.onRefresh()
await waitFor(() => {
expect(mockAnnouncementExecute).toHaveBeenCalled()
})
})
it('should show refreshing indicator when refreshing is true', () => {
const { useMessages } = require('@/hooks/use-messages')
useMessages.mockReturnValue({
messages: mockMessages,
loading: false,
loadingMore: false,
refreshing: true,
error: null,
execute: mockExecute,
refetch: mockRefetch,
loadMore: mockLoadMore,
hasMore: true,
})
const { getByTestId } = render(<MessageScreen />)
const flatList = getByTestId('message-list')
const refreshControl = flatList.props.refreshControl
expect(refreshControl.props.refreshing).toBe(true)
})
it('should not show refreshing indicator when refreshing is false', () => {
const { getByTestId } = render(<MessageScreen />)
const flatList = getByTestId('message-list')
const refreshControl = flatList.props.refreshControl
expect(refreshControl.props.refreshing).toBe(false)
})
})
describe('Tab Focus Reload', () => {
beforeEach(() => {
jest.clearAllMocks()
const { useMessages } = require('@/hooks/use-messages')
useMessages.mockReturnValue({
messages: mockMessages,
loading: false,
loadingMore: false,
refreshing: false,
error: null,
execute: mockExecute,
refetch: mockRefetch,
loadMore: mockLoadMore,
hasMore: true,
})
const { useAnnouncements } = require('@/hooks/use-announcements')
useAnnouncements.mockReturnValue({
announcements: mockAnnouncements,
loading: false,
error: null,
execute: mockAnnouncementExecute,
refetch: jest.fn(),
loadMore: jest.fn(),
hasMore: false,
})
})
it('should call refetch when tab gains focus', () => {
render(<MessageScreen />)
// useFocusEffect 在 mock 中会立即执行 callback
// 所以 refetch 应该被调用
expect(mockRefetch).toHaveBeenCalled()
})
it('should call executeAnnouncements when tab gains focus', () => {
render(<MessageScreen />)
expect(mockAnnouncementExecute).toHaveBeenCalled()
})
it('should use useFocusEffect hook', () => {
render(<MessageScreen />)
// 验证 useFocusEffect 被调用
expect(mockUseFocusEffect).toHaveBeenCalled()
})
})
})