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

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%');
});