/* @vitest-environment jsdom */ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { expect, test, vi } from 'vitest'; import { AnimationState, type Character, type CompanionRenderState, type EquipmentLoadout, WorldType, } from '../types'; import { CharacterPanel } from './CharacterPanel'; vi.mock('./CharacterAnimator', () => ({ CharacterAnimator: () =>
角色动画
, })); vi.mock('./MedievalNpcAnimator', () => ({ MedievalNpcAnimator: () =>
NPC 动画
, })); vi.mock('./PixelCloseButton', () => ({ PixelCloseButton: ({ label, onClick, }: { label: string; onClick: () => void; }) => ( ), })); vi.mock('./PixelIcon', () => ({ PixelIcon: ({ className }: { className?: string }) => ( 像素图标 ), })); vi.mock('./ResolvedAssetImage', () => ({ ResolvedAssetImage: ({ alt }: { alt: string }) => {alt}, })); function createCharacter(id: string, name: string): Character { return { id, name, title: `${name}称号`, gender: 'female', description: `${name}描述`, backstory: `${name}背景故事`, avatar: `/${id}.png`, portrait: `/${id}.png`, assetFolder: 'roles', assetVariant: 'generated', attributes: { strength: 10, agility: 10, intelligence: 10, spirit: 10, }, personality: `${name}性格`, skills: [], adventureOpenings: {}, }; } function findSharedDarkPanelForText(text: string) { let current: HTMLElement | null = screen.getByText(text); while (current) { if ( current.className.includes('border-white/10') && current.className.includes('bg-black/25') ) { return current; } current = current.parentElement; } return null; } test('角色面板详情静态信息复用暗色平台子面板和胶囊标签', async () => { const user = userEvent.setup(); const playerCharacter = createCharacter('hero', '沈行'); const companionCharacter = createCharacter('sword-princess', '闻雪'); const companionRenderState: CompanionRenderState = { npcId: 'npc-companion-1', character: companionCharacter, hp: 42, maxHp: 60, mana: 18, maxMana: 30, skillCooldowns: {}, animationState: AnimationState.IDLE, slot: 'upper', }; render( , ); const multiplierBadge = screen.getAllByText(/适配 x/u)[0]; expect(multiplierBadge?.className).toContain('rounded-full'); expect(multiplierBadge?.className).toContain('bg-emerald-500/10'); await user.click(screen.getByRole('button', { name: /沈行/u })); const levelProgressPanel = screen.getByTestId( 'character-panel-level-progress', ); expect(levelProgressPanel.className).toContain('border-amber-300/18'); expect(levelProgressPanel.className).toContain('bg-amber-500/8'); expect(levelProgressPanel.className).toContain('rounded-xl'); expect(findSharedDarkPanelForText('沈行背景故事')?.className).toContain( 'bg-black/25', ); expect(findSharedDarkPanelForText('沈行性格')?.className).toContain( 'bg-black/25', ); await user.click(screen.getByRole('button', { name: '关闭角色详情' })); await user.click(screen.getByRole('button', { name: /闻雪/u })); expect(findSharedDarkPanelForText('个人线阶段')?.className).toContain( 'bg-black/25', ); expect(findSharedDarkPanelForText('潮声里的信任')?.className).toContain( 'bg-black/25', ); const resolutionPanel = screen.getByTestId('character-panel-resolution'); expect(resolutionPanel.className).toContain('border-emerald-400/18'); expect(resolutionPanel.className).toContain('bg-emerald-500/8'); expect(resolutionPanel.className).toContain('rounded-xl'); expect(findSharedDarkPanelForText('王庭剑')?.className).toContain( 'bg-black/25', ); });