Files
Genarrative/src/components/common/PlatformSubpanel.test.tsx
T
kdletters 1ad25e30f8 收口前端平台组件库能力
新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件
迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome
补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
2026-06-10 10:24:18 +08:00

232 lines
6.9 KiB
TypeScript

/* @vitest-environment jsdom */
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { expect, test, vi } from 'vitest';
import { PlatformSubpanel } from './PlatformSubpanel';
test('renders platform subpanel shell with section title', () => {
render(
<PlatformSubpanel title="作品信息">
<p>作品名称</p>
</PlatformSubpanel>,
);
const panel = screen.getByText('作品信息').closest('section');
expect(panel?.className).toContain('platform-subpanel');
expect(panel?.className).toContain('rounded-[1.25rem]');
expect(panel?.className).toContain('p-4');
expect(screen.getByText('作品信息').className).toContain('tracking-[0.18em]');
});
test('supports actions, strong title and body class', () => {
render(
<PlatformSubpanel
as="div"
title="音频"
titleVariant="strong"
actions={<button type="button">重置</button>}
radius="lg"
padding="lg"
bodyClassName="mt-3 grid gap-2"
className="custom-panel"
>
<span>上传</span>
</PlatformSubpanel>,
);
const panel = screen.getByText('音频').closest('div.custom-panel');
const body = screen.getByText('上传').parentElement;
expect(panel?.className).toContain('rounded-[1.35rem]');
expect(panel?.className).toContain('sm:p-5');
expect(screen.getByText('音频').className).toContain('font-black');
expect(screen.getByRole('button', { name: '重置' })).toBeTruthy();
expect(body?.className).toContain('mt-3 grid gap-2');
});
test('supports extra large platform subpanel radius', () => {
render(
<PlatformSubpanel radius="xl" padding="lg">
方洞面板
</PlatformSubpanel>,
);
const panel = screen.getByText('方洞面板').closest('section');
expect(panel?.className).toContain('rounded-[1.5rem]');
expect(panel?.className).toContain('sm:p-5');
});
test('passes static element attributes through to the panel shell', () => {
render(
<PlatformSubpanel as="aside" aria-label="预览面板" data-testid="preview">
预览内容
</PlatformSubpanel>,
);
const panel = screen.getByTestId('preview');
expect(panel.tagName).toBe('ASIDE');
expect(panel.getAttribute('aria-label')).toBe('预览面板');
expect(panel.className).toContain('platform-subpanel');
});
test('supports flat compact subpanel cards', () => {
render(
<PlatformSubpanel
as="div"
surface="flat"
radius="sm"
padding="sm"
title="封面"
actions={<button type="button">选择</button>}
>
<span>已绑定</span>
</PlatformSubpanel>,
);
const panel = screen.getByText('已绑定').closest('div');
expect(panel?.className.split(/\s+/u)).not.toContain('platform-subpanel');
expect(panel?.className).toContain('bg-white/72');
expect(panel?.className).toContain('rounded-[1rem]');
expect(panel?.className).toContain('p-3');
expect(screen.getByRole('button', { name: '选择' })).toBeTruthy();
});
test('supports dark compact subpanel cards', () => {
render(
<PlatformSubpanel as="div" surface="dark" radius="xs" padding="xs">
任务目标
</PlatformSubpanel>,
);
const panel = screen.getByText('任务目标').closest('div');
expect(panel?.className).toContain('border-white/10');
expect(panel?.className).toContain('bg-black/25');
expect(panel?.className).toContain('rounded-xl');
expect(panel?.className).toContain('px-3');
expect(panel?.className).toContain('py-2.5');
});
test('supports tinted dark information panels', () => {
const { rerender } = render(
<PlatformSubpanel as="div" surface="darkSky" radius="lg" padding="md">
私聊
</PlatformSubpanel>,
);
let panel = screen.getByText('私聊').closest('div');
expect(panel?.className).toContain('border-sky-400/18');
expect(panel?.className).toContain('bg-sky-500/8');
expect(panel?.className).toContain('text-sky-50');
expect(panel?.className).toContain('rounded-[1.35rem]');
rerender(
<PlatformSubpanel as="div" surface="darkEmerald" radius="xs" padding="row">
队友收束
</PlatformSubpanel>,
);
panel = screen.getByText('队友收束').closest('div');
expect(panel?.className).toContain('border-emerald-400/18');
expect(panel?.className).toContain('bg-emerald-500/8');
expect(panel?.className).toContain('text-emerald-100/85');
rerender(
<PlatformSubpanel as="div" surface="darkAmber" radius="xs" padding="sm">
等级
</PlatformSubpanel>,
);
panel = screen.getByText('等级').closest('div');
expect(panel?.className).toContain('border-amber-300/18');
expect(panel?.className).toContain('bg-amber-500/8');
expect(panel?.className).toContain('text-amber-50');
rerender(
<PlatformSubpanel as="div" surface="darkRose" radius="xs" padding="xs">
好感度
</PlatformSubpanel>,
);
panel = screen.getByText('好感度').closest('div');
expect(panel?.className).toContain('border-rose-300/18');
expect(panel?.className).toContain('bg-rose-500/8');
expect(panel?.className).toContain('text-rose-50');
});
test('supports soft tight subpanel rows', () => {
const { rerender } = render(
<PlatformSubpanel as="div" surface="soft" radius="sm" padding="tight">
新增标签
</PlatformSubpanel>,
);
let panel = screen.getByText('新增标签').closest('div');
expect(panel?.className).toContain('bg-white/68');
expect(panel?.className).toContain('rounded-[1rem]');
expect(panel?.className).toContain('p-2');
rerender(
<PlatformSubpanel as="div" surface="soft" radius="sm" padding="row">
已选素材
</PlatformSubpanel>,
);
panel = screen.getByText('已选素材').closest('div');
expect(panel?.className).toContain('px-3');
expect(panel?.className).toContain('py-2');
});
test('supports danger subpanel surface', () => {
render(
<PlatformSubpanel surface="danger" padding="none">
已选卡片
</PlatformSubpanel>,
);
const panel = screen.getByText('已选卡片').closest('section');
expect(panel?.className.split(/\s+/u)).not.toContain('platform-subpanel');
expect(panel?.className).toContain(
'border-[var(--platform-button-danger-border)]',
);
expect(panel?.className).toContain('bg-[var(--platform-button-danger-fill)]');
expect(panel?.className).toContain('p-0');
});
test('supports interactive button subpanel cards', async () => {
const user = userEvent.setup();
const onClick = vi.fn();
render(
<PlatformSubpanel
as="button"
surface="flat"
radius="sm"
padding="sm"
interactive
onClick={onClick}
>
继续
</PlatformSubpanel>,
);
const button = screen.getByRole('button', { name: '继续' });
expect(button.getAttribute('type')).toBe('button');
expect(button.className).toContain('hover:bg-white');
expect(button.className).toContain('disabled:cursor-not-allowed');
await user.click(button);
expect(onClick).toHaveBeenCalledTimes(1);
});