新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件 迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome 补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
168 lines
4.7 KiB
TypeScript
168 lines
4.7 KiB
TypeScript
/* @vitest-environment jsdom */
|
||
|
||
import { render, screen } from '@testing-library/react';
|
||
import { expect, test } from 'vitest';
|
||
|
||
import { PlatformIconButton } from './PlatformIconButton';
|
||
|
||
test('renders platform icon button with accessible label and icon chrome', () => {
|
||
render(
|
||
<PlatformIconButton
|
||
label="关闭"
|
||
icon={<span aria-hidden="true">×</span>}
|
||
/>,
|
||
);
|
||
|
||
const button = screen.getByRole('button', { name: '关闭' });
|
||
|
||
expect(button.className).toContain('platform-icon-button');
|
||
expect(button.getAttribute('type')).toBe('button');
|
||
expect(button.textContent).toBe('×');
|
||
});
|
||
|
||
test('keeps local class names and explicit title', () => {
|
||
render(
|
||
<PlatformIconButton
|
||
label="发送"
|
||
title="发送"
|
||
icon={<span aria-hidden="true">↑</span>}
|
||
className="h-11 w-11"
|
||
/>,
|
||
);
|
||
|
||
const button = screen.getByRole('button', { name: '发送' });
|
||
|
||
expect(button.className).toContain('h-11');
|
||
expect(button.getAttribute('title')).toBe('发送');
|
||
});
|
||
|
||
test('supports floating surface icon action chrome', () => {
|
||
render(
|
||
<PlatformIconButton
|
||
label="更换图片"
|
||
title="更换图片"
|
||
variant="surfaceFloating"
|
||
icon={<span aria-hidden="true">+</span>}
|
||
className="h-10 w-10"
|
||
/>,
|
||
);
|
||
|
||
const button = screen.getByRole('button', { name: '更换图片' });
|
||
|
||
expect(button.className).toContain('bg-white/94');
|
||
expect(button.className).toContain('backdrop-blur');
|
||
expect(button.className).toContain('h-10');
|
||
expect(button.className).not.toContain('platform-icon-button');
|
||
});
|
||
|
||
test('supports visible short label on floating surface actions', () => {
|
||
render(
|
||
<PlatformIconButton
|
||
label="选择历史图片"
|
||
title="选择历史图片"
|
||
variant="surfaceFloating"
|
||
icon={<span aria-hidden="true">↺</span>}
|
||
className="gap-1.5 px-3"
|
||
>
|
||
<span>历史</span>
|
||
</PlatformIconButton>,
|
||
);
|
||
|
||
const button = screen.getByRole('button', { name: '选择历史图片' });
|
||
|
||
expect(button.textContent).toContain('历史');
|
||
expect(button.className).toContain('bg-white/94');
|
||
expect(button.className).toContain('gap-1.5');
|
||
expect(button.className).toContain('px-3');
|
||
});
|
||
|
||
test('supports dark mini icon action chrome', () => {
|
||
render(
|
||
<PlatformIconButton
|
||
label="字段说明"
|
||
variant="darkMini"
|
||
icon={<span aria-hidden="true">?</span>}
|
||
className="h-4 w-4 text-[10px]"
|
||
/>,
|
||
);
|
||
|
||
const button = screen.getByRole('button', { name: '字段说明' });
|
||
|
||
expect(button.className).toContain('bg-black/55');
|
||
expect(button.className).toContain('border-white/16');
|
||
expect(button.className).toContain('hover:bg-black/70');
|
||
expect(button.className).toContain('h-4');
|
||
expect(button.textContent).toBe('?');
|
||
});
|
||
|
||
test('supports label child chrome for icon upload controls', () => {
|
||
const { container } = render(
|
||
<>
|
||
<PlatformIconButton
|
||
asChild="label"
|
||
htmlFor="reference-image"
|
||
label="上传参考图"
|
||
title="上传参考图"
|
||
icon={<span aria-hidden="true" />}
|
||
className="h-9 w-9 cursor-pointer"
|
||
/>
|
||
<input id="reference-image" type="file" />
|
||
</>,
|
||
);
|
||
|
||
const input = screen.getByLabelText('上传参考图');
|
||
const label = container.querySelector('label[for="reference-image"]');
|
||
|
||
expect(input.getAttribute('type')).toBe('file');
|
||
expect(label?.tagName).toBe('LABEL');
|
||
expect(label?.getAttribute('for')).toBe('reference-image');
|
||
expect(label?.className).toContain('platform-icon-button');
|
||
expect(label?.className).toContain('cursor-pointer');
|
||
expect(label?.getAttribute('title')).toBe('上传参考图');
|
||
});
|
||
|
||
test('supports floating surface label upload controls', () => {
|
||
const { container } = render(
|
||
<PlatformIconButton
|
||
asChild="label"
|
||
label="上传参考图"
|
||
variant="surfaceFloating"
|
||
title="上传参考图"
|
||
icon={
|
||
<>
|
||
<span aria-hidden="true">+</span>
|
||
<input type="file" />
|
||
</>
|
||
}
|
||
className="h-8 w-8 cursor-pointer"
|
||
/>,
|
||
);
|
||
|
||
const label = container.querySelector('label');
|
||
const input = label?.querySelector('input');
|
||
|
||
expect(label?.textContent).toContain('上传参考图');
|
||
expect(input?.getAttribute('type')).toBe('file');
|
||
expect(label?.className).toContain('bg-white/94');
|
||
expect(label?.className).toContain('cursor-pointer');
|
||
});
|
||
|
||
test('keeps nested file input associated with the label name', () => {
|
||
render(
|
||
<PlatformIconButton
|
||
asChild="label"
|
||
label="上传参考图"
|
||
icon={
|
||
<>
|
||
<span aria-hidden="true" />
|
||
<input type="file" />
|
||
</>
|
||
}
|
||
/>,
|
||
);
|
||
|
||
const input = screen.getByLabelText('上传参考图', { selector: 'input' });
|
||
|
||
expect(input.getAttribute('type')).toBe('file');
|
||
});
|