deea0e8655
自动发现 H5 HostBridge 真实能力调用链 补齐 runtime 回读与 wrapper 消费者扫描兜底 区分壳源码和 H5 业务调用链的禁替身词表 将视觉小说生产预览数据从 mock 命名收口为本地预览命名 更新原生壳验收文档和共享决策记录
149 lines
5.5 KiB
TypeScript
149 lines
5.5 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import { fireEvent, render, screen } from '@testing-library/react';
|
|
import type { ComponentProps } from 'react';
|
|
import { expect, test, vi } from 'vitest';
|
|
|
|
import { buildVisualNovelForbiddenCopyPattern } from '../visual-novel-runtime/visualNovelForbiddenCopy';
|
|
import { visualNovelLocalPreviewSession } from '../visual-novel-runtime/visualNovelLocalPreviewData';
|
|
import { VisualNovelAgentWorkspace } from './VisualNovelAgentWorkspace';
|
|
import {
|
|
buildVisualNovelEntryGenerationAnchorEntries,
|
|
buildVisualNovelEntryGenerationProgress,
|
|
} from './visualNovelEntryGeneration';
|
|
|
|
function renderWorkspace(
|
|
ui?: Partial<ComponentProps<typeof VisualNovelAgentWorkspace>>,
|
|
) {
|
|
return render(
|
|
<VisualNovelAgentWorkspace onBack={() => {}} session={null} {...ui} />,
|
|
);
|
|
}
|
|
|
|
test('visual novel workspace only exposes one-line input and visual style entry', () => {
|
|
const onCreateFromForm = vi.fn();
|
|
|
|
renderWorkspace({ onCreateFromForm, title: '视觉小说' });
|
|
|
|
expect(screen.getByText('BETA').className).toContain('rounded-full');
|
|
expect(screen.getByText('BETA').className).toContain(
|
|
'border-[var(--platform-warm-border)]',
|
|
);
|
|
expect(screen.getByLabelText('一句话创作')).toBeTruthy();
|
|
expect(screen.getByText('视觉画风')).toBeTruthy();
|
|
expect(screen.getByText('视觉画风').closest('div')?.className).toContain(
|
|
'platform-subpanel',
|
|
);
|
|
expect(screen.getByText('视觉画风').closest('div')?.className).toContain(
|
|
'bg-white/52',
|
|
);
|
|
expect(
|
|
screen
|
|
.getByRole('button', { name: '映画动画' })
|
|
.querySelector('img')
|
|
?.getAttribute('src'),
|
|
).toBe('/visual-novel-style-references/cinematic-anime.png');
|
|
expect(
|
|
screen
|
|
.getByRole('button', { name: '水彩绘本' })
|
|
.querySelector('img')
|
|
?.getAttribute('src'),
|
|
).toBe('/visual-novel-style-references/watercolor.png');
|
|
expect(
|
|
screen
|
|
.getByRole('button', { name: '像素霓虹' })
|
|
.querySelector('img')
|
|
?.getAttribute('src'),
|
|
).toBe('/visual-novel-style-references/pixel-noir.png');
|
|
expect(
|
|
screen
|
|
.getByRole('button', { name: '水墨幻想' })
|
|
.querySelector('img')
|
|
?.getAttribute('src'),
|
|
).toBe('/visual-novel-style-references/ink-fantasy.png');
|
|
expect(
|
|
screen
|
|
.getByRole('button', { name: '柔彩校园' })
|
|
.querySelector('img')
|
|
?.getAttribute('src'),
|
|
).toBe('/visual-novel-style-references/soft-pastel.png');
|
|
expect(
|
|
screen
|
|
.getByRole('button', { name: '暗色哥特' })
|
|
.querySelector('img')
|
|
?.getAttribute('src'),
|
|
).toBe('/visual-novel-style-references/dark-gothic.png');
|
|
expect(screen.getByText('消耗20泥点')).toBeTruthy();
|
|
expect(screen.queryByText(buildVisualNovelForbiddenCopyPattern())).toBeNull();
|
|
expect(screen.queryByRole('button', { name: '文档' })).toBeNull();
|
|
expect(screen.queryByRole('button', { name: '空白' })).toBeNull();
|
|
expect(screen.queryByLabelText('上传文档')).toBeNull();
|
|
expect(screen.queryByText('进入结果页')).toBeNull();
|
|
expect(screen.queryByText('Agent')).toBeNull();
|
|
});
|
|
|
|
test('visual novel workspace submits idea and selected visual style as seed text', () => {
|
|
const onCreateFromForm = vi.fn();
|
|
|
|
renderWorkspace({ onCreateFromForm });
|
|
|
|
fireEvent.change(screen.getByLabelText('一句话创作'), {
|
|
target: { value: '失忆画师在雨夜剧场寻找旧胶片。' },
|
|
});
|
|
fireEvent.click(screen.getByRole('button', { name: '像素霓虹' }));
|
|
fireEvent.click(screen.getByRole('button', { name: /生成视觉小说草稿/u }));
|
|
|
|
expect(onCreateFromForm).toHaveBeenCalledWith({
|
|
sourceMode: 'idea',
|
|
sourceAssetIds: [],
|
|
ideaText: '失忆画师在雨夜剧场寻找旧胶片。',
|
|
visualStyleId: 'pixel-noir',
|
|
visualStyleLabel: '像素霓虹',
|
|
visualStylePrompt:
|
|
'高可读像素视觉小说画风,霓虹反差、硬朗轮廓和复古界面气质。',
|
|
seedText:
|
|
'失忆画师在雨夜剧场寻找旧胶片。\n视觉画风:像素霓虹\n画风要求:高可读像素视觉小说画风,霓虹反差、硬朗轮廓和复古界面气质。',
|
|
});
|
|
});
|
|
|
|
test('visual novel workspace restores idea text from existing session', () => {
|
|
renderWorkspace({ session: visualNovelLocalPreviewSession });
|
|
|
|
expect(
|
|
(screen.getByLabelText('一句话创作') as HTMLTextAreaElement).value,
|
|
).toBe('想做一个雪夜列车和旧电台有关的悬疑视觉小说。');
|
|
});
|
|
|
|
test('visual novel generation helpers build process page data', () => {
|
|
const payload = {
|
|
sourceMode: 'idea' as const,
|
|
seedText: '雨夜书店\n视觉画风:水彩绘本\n画风要求:透明水彩与绘本质感。',
|
|
sourceAssetIds: [],
|
|
ideaText: '雨夜书店',
|
|
visualStyleId: 'watercolor' as const,
|
|
visualStyleLabel: '水彩绘本',
|
|
visualStylePrompt: '透明水彩与绘本质感。',
|
|
};
|
|
|
|
expect(buildVisualNovelEntryGenerationAnchorEntries(payload)).toEqual([
|
|
{ id: 'visual-novel-idea', label: '一句话', value: '雨夜书店' },
|
|
{ id: 'visual-novel-style', label: '视觉画风', value: '水彩绘本' },
|
|
{
|
|
id: 'visual-novel-target',
|
|
label: '生成目标',
|
|
value: '可编辑并可试玩的视觉小说草稿',
|
|
},
|
|
]);
|
|
|
|
const progress = buildVisualNovelEntryGenerationProgress(
|
|
1_000,
|
|
'generating',
|
|
8_000,
|
|
);
|
|
|
|
expect(progress.phaseId).toBe('visual-novel-world');
|
|
expect(progress.overallProgress).toBeGreaterThan(0);
|
|
expect(progress.phaseLabel).toBe('扩展世界观');
|
|
expect(progress.steps.some((step) => step.status === 'active')).toBe(true);
|
|
});
|