diff --git a/app/(tabs)/__tests__/index.test.tsx b/app/(tabs)/__tests__/index.test.tsx
new file mode 100644
index 0000000..8e752e1
--- /dev/null
+++ b/app/(tabs)/__tests__/index.test.tsx
@@ -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(
+
+ {component}
+
+ )
+}
+
+describe('HomeScreen', () => {
+ it('should render title bar with app name', async () => {
+ const { getByText } = renderWithProviders()
+
+ await waitFor(() => {
+ expect(getByText('Popcore')).toBeTruthy()
+ })
+ })
+
+ it('should render category tabs when data is loaded', async () => {
+ const { getByText } = renderWithProviders()
+
+ await waitFor(() => {
+ expect(getByText('Test Category')).toBeTruthy()
+ })
+ })
+
+ it('should render template cards when category has templates', async () => {
+ const { getByText } = renderWithProviders()
+
+ await waitFor(() => {
+ expect(getByText('Test Template')).toBeTruthy()
+ })
+ })
+
+ it('should not show loading state when data is loaded', async () => {
+ const { queryByText } = renderWithProviders()
+
+ await waitFor(() => {
+ expect(queryByText('加载中')).toBeNull()
+ })
+ })
+})