收口前端平台组件库能力

新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件
迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome
补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
This commit is contained in:
2026-06-10 10:24:18 +08:00
parent a4ee6ff698
commit 1ad25e30f8
226 changed files with 23364 additions and 7825 deletions

View File

@@ -22,6 +22,29 @@ afterEach(() => {
vi.restoreAllMocks();
});
test('creation agent workspace renders missing session notice with shared subpanel chrome', () => {
render(
<CreationAgentWorkspace
session={null}
theme={testTheme}
loadingText="正在准备"
composerPlaceholder="输入消息"
primaryActionLabel="生成结果页"
onBack={() => {}}
onSubmitText={() => {}}
onPrimaryAction={() => {}}
/>,
);
const noticePanel = screen
.getByText('正在准备')
.closest('.platform-subpanel');
expect(noticePanel?.className).toContain('rounded-[1rem]');
expect(noticePanel?.className).toContain('sm:p-5');
expect(noticePanel?.className).toContain('text-[var(--platform-text-base)]');
});
function ensureScrollApis() {
if (!Element.prototype.scrollIntoView) {
Element.prototype.scrollIntoView = () => {};
@@ -58,11 +81,55 @@ test('creation agent workspace keeps initial chat progress at zero percent', ()
const progressbar = screen.getByRole('progressbar');
expect(progressbar.getAttribute('aria-valuenow')).toBe('0');
expect(progressbar.getAttribute('aria-labelledby')).toBe(
'creation-agent-progress-label',
);
expect(progressbar.className).toContain('platform-progress-track');
expect(
(progressbar.firstElementChild as HTMLElement | null)?.style.width,
).toBe('0%');
});
test('creation agent workspace renders operation banner with shared status message', () => {
ensureScrollApis();
render(
<CreationAgentWorkspace
session={{
sessionId: 'creation-agent-session-1',
title: null,
currentTurn: 0,
progressPercent: 0,
anchors: [],
messages: [],
}}
theme={testTheme}
loadingText="正在准备"
composerPlaceholder="输入消息"
primaryActionLabel="生成结果页"
activeOperation={{
operationId: 'operation-1',
status: 'running',
phaseLabel: '正在整理设定',
phaseDetail: '正在归纳角色和场景',
progress: 36,
}}
onBack={() => {}}
onSubmitText={() => {}}
onPrimaryAction={() => {}}
/>,
);
const banner = screen.getByText('正在整理设定').parentElement?.parentElement;
const progressbar = screen.getAllByRole('progressbar').at(-1);
expect(banner?.className).toContain('platform-remap-surface');
expect(banner?.className).toContain('bg-[var(--platform-cool-bg)]');
expect(screen.getByText('正在归纳角色和场景')).toBeTruthy();
expect(progressbar?.className).toContain('platform-progress-track');
expect(progressbar?.getAttribute('aria-valuenow')).toBe('36');
});
test('creation agent workspace filters duplicate recommended replies', () => {
const consoleErrorSpy = vi
.spyOn(console, 'error')
@@ -514,6 +581,47 @@ test('creation agent workspace appends parsed document text into composer', asyn
});
});
test('creation agent workspace renders selected reference image with shared preview row', async () => {
ensureScrollApis();
const onClearReferenceImage = vi.fn();
render(
<CreationAgentWorkspace
session={{
sessionId: 'creation-agent-session-1',
title: null,
currentTurn: 0,
progressPercent: 0,
anchors: [],
messages: [],
}}
theme={testTheme}
loadingText="正在准备"
composerPlaceholder="输入消息"
primaryActionLabel="生成结果页"
referenceImagePreviewSrc="data:image/png;base64,reference"
referenceImageLabel="设定参考图.png"
onBack={() => {}}
onSubmitText={() => {}}
onPrimaryAction={() => {}}
onClearReferenceImage={onClearReferenceImage}
/>,
);
const image = screen.getByRole('img', { name: '参考图' });
const row = screen.getByText('设定参考图.png').parentElement;
const removeButton = screen.getByRole('button', { name: '移除参考图' });
expect(image.getAttribute('src')).toBe('data:image/png;base64,reference');
expect(row?.className).toContain('bg-white/70');
expect(row?.className).toContain('mx-4');
fireEvent.click(removeButton);
expect(onClearReferenceImage).toHaveBeenCalledTimes(1);
});
test('creation agent workspace shows document parse error near composer', async () => {
ensureScrollApis();