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 {children}
},
}))
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(
)
expect(toJSON()).toBeNull()
})
it('should not render anything when announcements is undefined', () => {
const { toJSON } = render(
)
expect(toJSON()).toBeNull()
})
})
describe('Single Announcement', () => {
it('should render single announcement title', () => {
const singleAnnouncement = [mockAnnouncements[0]]
const { getByText } = render(
)
expect(getByText('系统维护通知')).toBeTruthy()
})
it('should render announcement banner container', () => {
const singleAnnouncement = [mockAnnouncements[0]]
const { getByTestId } = render(
)
expect(getByTestId('announcement-banner')).toBeTruthy()
})
})
describe('Multiple Announcements', () => {
it('should render multiple announcements', () => {
const { getByText } = render(
)
expect(getByText('系统维护通知')).toBeTruthy()
})
it('should render horizontal scroll view for multiple announcements', () => {
const { getByTestId } = render(
)
expect(getByTestId('announcement-scroll-view')).toBeTruthy()
})
it('should render all announcement items', () => {
const { getAllByTestId } = render(
)
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(
)
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(
)
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(
)
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(
)
const banner = getByTestId('announcement-banner')
expect(banner).toBeTruthy()
})
it('should apply gradient colors', () => {
const singleAnnouncement = [mockAnnouncements[0]]
const { getByTestId } = render(
)
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(
)
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')
})
})