test: add unit tests for HomeScreen to ensure proper rendering

Following TDD principles (RED-GREEN-REFACTOR):
- RED: Created failing tests for HomeScreen rendering
- Verify RED: Confirmed tests failed due to missing mocks
- GREEN: Added necessary mocks for all dependencies
- Verify GREEN: All 4 tests passing (4/4)

Tests cover:
- Title bar rendering with app name
- Category tabs rendering when data is loaded
- Template cards rendering when category has templates
- Loading state not showing when data is loaded

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
imeepos 2026-01-21 15:28:18 +08:00
parent 57b92ac52f
commit 54867492a7
1 changed files with 134 additions and 0 deletions

View File

@ -0,0 +1,134 @@
import React from 'react'
import { render, waitFor } from '@testing-library/react-native'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import HomeScreen from '../index'
// Mock expo-linear-gradient
jest.mock('expo-linear-gradient', () => ({
LinearGradient: 'LinearGradient',
}))
// Mock expo-image
jest.mock('expo-image', () => ({
Image: 'Image',
}))
// Mock expo-status-bar
jest.mock('expo-status-bar', () => ({
StatusBar: 'StatusBar',
}))
// Mock icons
jest.mock('@/components/icon', () => ({
DownArrowIcon: () => 'DownArrowIcon',
PointsIcon: () => 'PointsIcon',
SearchIcon: () => 'SearchIcon',
}))
// Mock components
jest.mock('@/components/ErrorState', () => 'ErrorState')
jest.mock('@/components/LoadingState', () => 'LoadingState')
jest.mock('@/components/RefreshControl', () => 'RefreshControl')
// Mock dependencies
jest.mock('expo-router', () => ({
useLocalSearchParams: jest.fn(() => ({})),
useRouter: jest.fn(() => ({
push: jest.fn(),
})),
}))
jest.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string) => key,
}),
}))
jest.mock('@/hooks/use-activates', () => ({
useActivates: jest.fn(() => ({
load: jest.fn(),
data: {
activities: [
{
id: '1',
title: 'Test Activity',
desc: 'Test Description',
coverUrl: 'https://example.com/image.jpg',
link: '/test',
},
],
},
error: null,
})),
}))
jest.mock('@/hooks/use-categories', () => ({
useCategories: jest.fn(() => ({
load: jest.fn(),
data: {
categories: [
{
id: 'cat1',
name: 'Test Category',
templates: [
{
id: 'template1',
title: 'Test Template',
webpPreviewUrl: 'https://example.com/preview.webp',
previewUrl: 'https://example.com/preview.jpg',
coverImageUrl: 'https://example.com/cover.png',
aspectRatio: '1:1',
},
],
},
],
},
loading: false,
error: null,
})),
}))
const renderWithProviders = (component: React.ReactElement) => {
return render(
<SafeAreaProvider initialMetrics={{
frame: { x: 0, y: 0, width: 375, height: 812 },
insets: { top: 44, left: 0, right: 0, bottom: 34 },
}}>
{component}
</SafeAreaProvider>
)
}
describe('HomeScreen', () => {
it('should render title bar with app name', async () => {
const { getByText } = renderWithProviders(<HomeScreen />)
await waitFor(() => {
expect(getByText('Popcore')).toBeTruthy()
})
})
it('should render category tabs when data is loaded', async () => {
const { getByText } = renderWithProviders(<HomeScreen />)
await waitFor(() => {
expect(getByText('Test Category')).toBeTruthy()
})
})
it('should render template cards when category has templates', async () => {
const { getByText } = renderWithProviders(<HomeScreen />)
await waitFor(() => {
expect(getByText('Test Template')).toBeTruthy()
})
})
it('should not show loading state when data is loaded', async () => {
const { queryByText } = renderWithProviders(<HomeScreen />)
await waitFor(() => {
expect(queryByText('加载中')).toBeNull()
})
})
})