203 lines
6.5 KiB
TypeScript
203 lines
6.5 KiB
TypeScript
import React from 'react'
|
|
import { render, fireEvent } from '@testing-library/react-native'
|
|
|
|
import { AnnouncementBanner, type Announcement } from './AnnouncementBanner'
|
|
|
|
// Mock expo-linear-gradient
|
|
jest.mock('expo-linear-gradient', () => ({
|
|
LinearGradient: ({ children, ...props }: any) => {
|
|
const { View } = require('react-native')
|
|
return <View {...props}>{children}</View>
|
|
},
|
|
}))
|
|
|
|
describe('AnnouncementBanner', () => {
|
|
const mockAnnouncements: Announcement[] = [
|
|
{
|
|
id: 'ann-1',
|
|
title: '系统维护通知',
|
|
content: '系统将于今晚进行维护',
|
|
link: 'https://example.com/maintenance',
|
|
createdAt: new Date('2026-01-29T10:00:00Z'),
|
|
},
|
|
{
|
|
id: 'ann-2',
|
|
title: '新功能上线',
|
|
content: '我们推出了全新的AI生成功能',
|
|
createdAt: new Date('2026-01-28T10:00:00Z'),
|
|
},
|
|
{
|
|
id: 'ann-3',
|
|
title: '活动公告',
|
|
content: '春节活动即将开始',
|
|
link: 'https://example.com/event',
|
|
createdAt: new Date('2026-01-27T10:00:00Z'),
|
|
},
|
|
]
|
|
|
|
const mockOnPress = jest.fn()
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks()
|
|
})
|
|
|
|
describe('Empty State', () => {
|
|
it('should not render anything when announcements array is empty', () => {
|
|
const { toJSON } = render(
|
|
<AnnouncementBanner announcements={[]} onPress={mockOnPress} />
|
|
)
|
|
expect(toJSON()).toBeNull()
|
|
})
|
|
|
|
it('should not render anything when announcements is undefined', () => {
|
|
const { toJSON } = render(
|
|
<AnnouncementBanner announcements={undefined as any} onPress={mockOnPress} />
|
|
)
|
|
expect(toJSON()).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('Single Announcement', () => {
|
|
it('should render single announcement title', () => {
|
|
const singleAnnouncement = [mockAnnouncements[0]]
|
|
const { getByText } = render(
|
|
<AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
|
|
)
|
|
expect(getByText('系统维护通知')).toBeTruthy()
|
|
})
|
|
|
|
it('should render announcement banner container', () => {
|
|
const singleAnnouncement = [mockAnnouncements[0]]
|
|
const { getByTestId } = render(
|
|
<AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
|
|
)
|
|
expect(getByTestId('announcement-banner')).toBeTruthy()
|
|
})
|
|
})
|
|
|
|
describe('Multiple Announcements', () => {
|
|
it('should render multiple announcements', () => {
|
|
const { getByText } = render(
|
|
<AnnouncementBanner announcements={mockAnnouncements} onPress={mockOnPress} />
|
|
)
|
|
expect(getByText('系统维护通知')).toBeTruthy()
|
|
})
|
|
|
|
it('should render horizontal scroll view for multiple announcements', () => {
|
|
const { getByTestId } = render(
|
|
<AnnouncementBanner announcements={mockAnnouncements} onPress={mockOnPress} />
|
|
)
|
|
expect(getByTestId('announcement-scroll-view')).toBeTruthy()
|
|
})
|
|
|
|
it('should render all announcement items', () => {
|
|
const { getAllByTestId } = render(
|
|
<AnnouncementBanner announcements={mockAnnouncements} onPress={mockOnPress} />
|
|
)
|
|
const items = getAllByTestId(/^announcement-item-/)
|
|
expect(items.length).toBe(3)
|
|
})
|
|
})
|
|
|
|
describe('Press Interaction', () => {
|
|
it('should call onPress with correct announcement when pressed', () => {
|
|
const singleAnnouncement = [mockAnnouncements[0]]
|
|
const { getByTestId } = render(
|
|
<AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
|
|
)
|
|
fireEvent.press(getByTestId('announcement-item-ann-1'))
|
|
expect(mockOnPress).toHaveBeenCalledTimes(1)
|
|
expect(mockOnPress).toHaveBeenCalledWith(mockAnnouncements[0])
|
|
})
|
|
|
|
it('should call onPress with correct announcement for each item', () => {
|
|
const { getByTestId } = render(
|
|
<AnnouncementBanner announcements={mockAnnouncements} onPress={mockOnPress} />
|
|
)
|
|
|
|
fireEvent.press(getByTestId('announcement-item-ann-2'))
|
|
expect(mockOnPress).toHaveBeenCalledWith(mockAnnouncements[1])
|
|
})
|
|
|
|
it('should not crash when onPress is not provided', () => {
|
|
const singleAnnouncement = [mockAnnouncements[0]]
|
|
const { getByTestId } = render(
|
|
<AnnouncementBanner announcements={singleAnnouncement} />
|
|
)
|
|
expect(() => {
|
|
fireEvent.press(getByTestId('announcement-item-ann-1'))
|
|
}).not.toThrow()
|
|
})
|
|
})
|
|
|
|
describe('Gradient Background Style', () => {
|
|
it('should render with gradient background', () => {
|
|
const singleAnnouncement = [mockAnnouncements[0]]
|
|
const { getByTestId } = render(
|
|
<AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
|
|
)
|
|
const banner = getByTestId('announcement-banner')
|
|
expect(banner).toBeTruthy()
|
|
})
|
|
|
|
it('should apply gradient colors', () => {
|
|
const singleAnnouncement = [mockAnnouncements[0]]
|
|
const { getByTestId } = render(
|
|
<AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
|
|
)
|
|
const gradientContainer = getByTestId('gradient-container')
|
|
expect(gradientContainer.props.colors).toEqual(['#FF9966', '#FF6699', '#9966FF'])
|
|
})
|
|
})
|
|
|
|
describe('Announcement Icon', () => {
|
|
it('should render announcement icon', () => {
|
|
const singleAnnouncement = [mockAnnouncements[0]]
|
|
const { getByTestId } = render(
|
|
<AnnouncementBanner announcements={singleAnnouncement} onPress={mockOnPress} />
|
|
)
|
|
expect(getByTestId('announcement-icon')).toBeTruthy()
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('Announcement Type', () => {
|
|
it('should have required id field', () => {
|
|
const announcement: Announcement = {
|
|
id: 'test-id',
|
|
title: 'Test Title',
|
|
createdAt: new Date(),
|
|
}
|
|
expect(announcement.id).toBeDefined()
|
|
})
|
|
|
|
it('should have required title field', () => {
|
|
const announcement: Announcement = {
|
|
id: 'test-id',
|
|
title: 'Test Title',
|
|
createdAt: new Date(),
|
|
}
|
|
expect(announcement.title).toBeDefined()
|
|
})
|
|
|
|
it('should have optional content field', () => {
|
|
const announcement: Announcement = {
|
|
id: 'test-id',
|
|
title: 'Test Title',
|
|
content: 'Test Content',
|
|
createdAt: new Date(),
|
|
}
|
|
expect(announcement.content).toBe('Test Content')
|
|
})
|
|
|
|
it('should have optional link field', () => {
|
|
const announcement: Announcement = {
|
|
id: 'test-id',
|
|
title: 'Test Title',
|
|
link: 'https://example.com',
|
|
createdAt: new Date(),
|
|
}
|
|
expect(announcement.link).toBe('https://example.com')
|
|
})
|
|
})
|