/* @vitest-environment jsdom */
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { afterEach, expect, test, vi } from 'vitest';
import { AnimationState, type Character } from '../types';
import {
CharacterIdentityBadges,
CharacterSkillsList,
PlayerLevelProgress,
} from './CharacterInfoShared';
function createSkill(
name: string,
style: Character['skills'][number]['style'],
): Character['skills'][number] {
return {
id: '',
name,
animation: AnimationState.IDLE,
damage: 12,
manaCost: 4,
cooldownTurns: 2,
range: 1,
style,
};
}
afterEach(() => {
vi.restoreAllMocks();
});
test('CharacterSkillsList falls back to stable render ids when skill ids are empty', async () => {
const user = userEvent.setup();
const handleSelectSkill = vi.fn();
const consoleErrorSpy = vi
.spyOn(console, 'error')
.mockImplementation(() => undefined);
render(
,
);
const buttons = screen.getAllByRole('button');
await user.click(buttons[0]!);
await user.click(buttons[1]!);
expect(handleSelectSkill).toHaveBeenNthCalledWith(1, 'skill-潮刃突进-0');
expect(handleSelectSkill).toHaveBeenNthCalledWith(2, 'skill-雾行转位-1');
const duplicateKeyCalls = consoleErrorSpy.mock.calls.filter((call) =>
call.some(
(arg) =>
typeof arg === 'string' &&
arg.includes('Encountered two children with the same key'),
),
);
expect(duplicateKeyCalls).toHaveLength(0);
});
test('CharacterIdentityBadges renders role and level chips together', () => {
render(
,
);
expect(screen.getByText('队长')).toBeTruthy();
expect(screen.getByText('Lv.7')).toBeTruthy();
});
test('PlayerLevelProgress renders xp progress details', () => {
render(
,
);
expect(screen.getByText('Lv.6')).toBeTruthy();
expect(screen.getByText('72/120')).toBeTruthy();
});