flnxi-Wu/components/ui/__tests__/ProBadge.test.tsx
2026-05-25 14:52:24 +08:00

185 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* ProBadge 组件单元测试
*
* 测试 ProBadge 组件的尺寸变体和主题支持
*
* **Feature: free-version-ui-restrictions**
* **Property 3: ProBadge 尺寸变体**
* **Property 4: ProBadge 主题支持**
* **Validates: Requirements 4.2, 4.3**
*
* @jest-environment jsdom
*/
import React from 'react'
import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import ProBadge, { ProBadgeSize } from '../ProBadge'
// Mock useTheme hook
const mockUseTheme = jest.fn()
jest.mock('@/lib/ui-styles', () => ({
useTheme: () => mockUseTheme(),
cn: (...classes: (string | boolean | undefined)[]) =>
classes.filter(Boolean).join(' '),
}))
describe('ProBadge 组件', () => {
beforeEach(() => {
mockUseTheme.mockReturnValue('light')
})
describe('基础渲染', () => {
it('应该正确渲染 PRO 文字', () => {
render(<ProBadge />)
expect(screen.getByText('PRO')).toBeInTheDocument()
})
it('应该有正确的 data-testid', () => {
render(<ProBadge />)
expect(screen.getByTestId('pro-badge')).toBeInTheDocument()
})
it('应该使用默认的 small 尺寸', () => {
render(<ProBadge />)
const badge = screen.getByTestId('pro-badge')
expect(badge).toHaveAttribute('data-size', 'small')
})
it('应该应用自定义 className', () => {
render(<ProBadge className="custom-class" />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('custom-class')
})
})
/**
* Property 3: ProBadge 尺寸变体
* *For any* 有效的尺寸参数 (xs, small, medium, large),ProBadge 组件必须使用对应的尺寸样式渲染
* **Feature: free-version-ui-restrictions, Property 3: ProBadge Size Variants**
* **Validates: Requirements 4.2**
*/
describe('Property 3: ProBadge 尺寸变体', () => {
const sizes: ProBadgeSize[] = ['xs', 'small', 'medium', 'large']
const sizeExpectations: Record<ProBadgeSize, { textClass: string; paddingClass: string }> = {
xs: { textClass: 'text-[8px]', paddingClass: 'px-1' },
small: { textClass: 'text-[10px]', paddingClass: 'px-1.5' },
medium: { textClass: 'text-xs', paddingClass: 'px-2' },
large: { textClass: 'text-sm', paddingClass: 'px-2.5' },
}
sizes.forEach((size) => {
it(`应该正确渲染 ${size} 尺寸`, () => {
render(<ProBadge size={size} />)
const badge = screen.getByTestId('pro-badge')
expect(badge).toHaveAttribute('data-size', size)
})
it(`${size} 尺寸应该有正确的文字大小类`, () => {
render(<ProBadge size={size} />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain(sizeExpectations[size].textClass)
})
it(`${size} 尺寸应该有正确的内边距类`, () => {
render(<ProBadge size={size} />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain(sizeExpectations[size].paddingClass)
})
})
it('不同尺寸应该产生不同的样式', () => {
const { rerender } = render(<ProBadge size="small" />)
const smallBadge = screen.getByTestId('pro-badge')
const smallClassName = smallBadge.className
rerender(<ProBadge size="large" />)
const largeBadge = screen.getByTestId('pro-badge')
const largeClassName = largeBadge.className
expect(smallClassName).not.toBe(largeClassName)
})
})
/**
* Property 4: ProBadge 主题支持
* *For any* 主题 (light 或 dark),ProBadge 组件必须以适当的对比度和可见性渲染
* **Feature: free-version-ui-restrictions, Property 4: ProBadge Theme Support**
* **Validates: Requirements 4.3**
*/
describe('Property 4: ProBadge 主题支持', () => {
it('浅色主题应该有正确的阴影样式', () => {
mockUseTheme.mockReturnValue('light')
render(<ProBadge />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('bg-slate-100')
})
it('深色主题应该有正确的阴影样式', () => {
mockUseTheme.mockReturnValue('dark')
render(<ProBadge />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('bg-slate-800')
})
it('两种主题都应该有中性色背景', () => {
mockUseTheme.mockReturnValue('light')
const { rerender } = render(<ProBadge />)
let badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('bg-slate-100')
expect(badge.className).toContain('text-slate-700')
mockUseTheme.mockReturnValue('dark')
rerender(<ProBadge />)
badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('bg-slate-800')
expect(badge.className).toContain('text-slate-200')
})
it('两种主题都应该有清晰文字', () => {
mockUseTheme.mockReturnValue('light')
const { rerender } = render(<ProBadge />)
let badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('text-slate-700')
mockUseTheme.mockReturnValue('dark')
rerender(<ProBadge />)
badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('text-slate-200')
})
})
describe('视觉样式', () => {
it('应该有圆角样式', () => {
render(<ProBadge />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('rounded-full')
})
it('应该有中性色背景', () => {
render(<ProBadge />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('bg-slate-100')
})
it('应该有阴影效果', () => {
render(<ProBadge />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('shadow-sm')
})
it('应该是 inline-flex 以便内联使用', () => {
render(<ProBadge />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('inline-flex')
})
it('应该有加粗字体', () => {
render(<ProBadge />)
const badge = screen.getByTestId('pro-badge')
expect(badge.className).toContain('font-semibold')
})
})
})