/* @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 }) =>
,
}));
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',
);
});