1ad25e30f8
新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件 迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome 补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
111 lines
3.5 KiB
TypeScript
111 lines
3.5 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import { render, screen } from '@testing-library/react';
|
|
import { expect, test } from 'vitest';
|
|
|
|
import { PlatformProgressBar } from './PlatformProgressBar';
|
|
|
|
test('renders shared progressbar chrome and value', () => {
|
|
render(
|
|
<PlatformProgressBar
|
|
value={42}
|
|
minVisibleValue={8}
|
|
size="sm"
|
|
className="mt-3"
|
|
fillClassName="bg-emerald-300"
|
|
/>,
|
|
);
|
|
|
|
const progressbar = screen.getByRole('progressbar');
|
|
const fill = progressbar.firstElementChild as HTMLElement | null;
|
|
|
|
expect(progressbar.getAttribute('aria-valuenow')).toBe('42');
|
|
expect(progressbar.className).toContain('platform-progress-track');
|
|
expect(progressbar.className).toContain('h-2.5');
|
|
expect(progressbar.className).toContain('mt-3');
|
|
expect(fill?.className).toContain('bg-emerald-300');
|
|
expect(fill?.style.width).toBe('42%');
|
|
});
|
|
|
|
test('keeps zero progress visually empty and clamps invalid values', () => {
|
|
const { rerender } = render(<PlatformProgressBar value={0} />);
|
|
|
|
let progressbar = screen.getByRole('progressbar');
|
|
let fill = progressbar.firstElementChild as HTMLElement | null;
|
|
|
|
expect(progressbar.getAttribute('aria-valuenow')).toBe('0');
|
|
expect(fill?.style.width).toBe('0%');
|
|
|
|
rerender(<PlatformProgressBar value={Number.NaN} />);
|
|
progressbar = screen.getByRole('progressbar');
|
|
fill = progressbar.firstElementChild as HTMLElement | null;
|
|
|
|
expect(progressbar.getAttribute('aria-valuenow')).toBe('0');
|
|
expect(fill?.style.width).toBe('0%');
|
|
|
|
rerender(<PlatformProgressBar value={130} />);
|
|
progressbar = screen.getByRole('progressbar');
|
|
fill = progressbar.firstElementChild as HTMLElement | null;
|
|
|
|
expect(progressbar.getAttribute('aria-valuenow')).toBe('100');
|
|
expect(fill?.style.width).toBe('100%');
|
|
});
|
|
|
|
test('supports labelled progressbar and local fill style', () => {
|
|
render(
|
|
<>
|
|
<div id="progress-label">创作进度</div>
|
|
<PlatformProgressBar
|
|
value={3}
|
|
minVisibleValue={6}
|
|
labelledBy="progress-label"
|
|
size="md"
|
|
fillStyle={{ backgroundColor: 'red' }}
|
|
/>
|
|
</>,
|
|
);
|
|
|
|
const progressbar = screen.getByRole('progressbar');
|
|
const fill = progressbar.firstElementChild as HTMLElement | null;
|
|
|
|
expect(progressbar.getAttribute('aria-labelledby')).toBe('progress-label');
|
|
expect(progressbar.className).toContain('h-3');
|
|
expect(fill?.style.width).toBe('6%');
|
|
expect(fill?.style.backgroundColor).toBe('red');
|
|
});
|
|
|
|
test('supports aria label and overlay content', () => {
|
|
render(
|
|
<PlatformProgressBar value={64} ariaLabel="画面生成进度" size="lg">
|
|
<span>预计剩余 270 秒</span>
|
|
</PlatformProgressBar>,
|
|
);
|
|
|
|
const progressbar = screen.getByRole('progressbar', {
|
|
name: '画面生成进度',
|
|
});
|
|
|
|
expect(progressbar.getAttribute('aria-valuenow')).toBe('64');
|
|
expect(progressbar.className).toContain('relative');
|
|
expect(progressbar.className).toContain('h-12');
|
|
expect(screen.getByText('预计剩余 270 秒')).toBeTruthy();
|
|
});
|
|
|
|
test('omits current value for indeterminate progress', () => {
|
|
render(
|
|
<PlatformProgressBar
|
|
value={66}
|
|
ariaLabel="生成中"
|
|
indeterminate
|
|
fillClassName="animate-pulse"
|
|
/>,
|
|
);
|
|
|
|
const progressbar = screen.getByRole('progressbar', { name: '生成中' });
|
|
const fill = progressbar.firstElementChild as HTMLElement | null;
|
|
|
|
expect(progressbar.getAttribute('aria-valuenow')).toBeNull();
|
|
expect(fill?.className).toContain('animate-pulse');
|
|
expect(fill?.style.width).toBe('66%');
|
|
});
|