387a1c26e3
清理已跟踪原始日志与个人本地配置 修复前后端有效门禁、测试和构建问题 补齐生产 Jenkins、SpacetimeDB 本地命令与文档约束 收紧图片编辑器状态、附件与媒体引用测试 排除已下线旧创作入口测试并清理 warning
163 lines
4.6 KiB
TypeScript
163 lines
4.6 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import {
|
|
cleanup,
|
|
fireEvent,
|
|
render,
|
|
screen,
|
|
within,
|
|
} from '@testing-library/react';
|
|
import { expect, test, vi } from 'vitest';
|
|
|
|
import {
|
|
PuzzleOnboardingLoginOverlay,
|
|
type PuzzleOnboardingPhase,
|
|
PuzzleOnboardingView,
|
|
} from './PuzzleOnboardingView';
|
|
|
|
function renderOnboarding({
|
|
prompt = '月亮糖果工厂',
|
|
phase = 'input',
|
|
error = null,
|
|
onPromptChange = vi.fn(),
|
|
onSubmit = vi.fn(),
|
|
onSkip = vi.fn(),
|
|
}: {
|
|
prompt?: string;
|
|
phase?: PuzzleOnboardingPhase;
|
|
error?: string | null;
|
|
onPromptChange?: (value: string) => void;
|
|
onSubmit?: () => void;
|
|
onSkip?: () => void;
|
|
} = {}) {
|
|
render(
|
|
<PuzzleOnboardingView
|
|
prompt={prompt}
|
|
phase={phase}
|
|
error={error}
|
|
copy="把梦做成拼图"
|
|
onPromptChange={onPromptChange}
|
|
onSubmit={onSubmit}
|
|
onSkip={onSkip}
|
|
/>,
|
|
);
|
|
|
|
return { onPromptChange, onSubmit, onSkip };
|
|
}
|
|
|
|
test('PuzzleOnboardingView uses shared dark textarea and error status chrome', () => {
|
|
const { onPromptChange } = renderOnboarding({
|
|
error: '拼图生成失败',
|
|
});
|
|
|
|
const textarea = screen.getByPlaceholderText('把你的梦讲给我听吧');
|
|
fireEvent.change(textarea, { target: { value: '一座会唱歌的城堡' } });
|
|
|
|
expect(textarea.tagName).toBe('TEXTAREA');
|
|
expect(textarea.className).toContain('platform-text-field--editor-dark');
|
|
expect(textarea.className).toContain('min-h-32');
|
|
expect(onPromptChange).toHaveBeenCalledWith('一座会唱歌的城堡');
|
|
expect(screen.getByText('拼图生成失败').className).toContain(
|
|
'platform-status-message',
|
|
);
|
|
expect(screen.getByText('拼图生成失败').className).toContain(
|
|
'border-rose-300/15',
|
|
);
|
|
expect(screen.queryByRole('dialog')).toBeNull();
|
|
});
|
|
|
|
test('PuzzleOnboardingView preserves submit, skip, and disabled phase behavior', () => {
|
|
const { onSubmit, onSkip } = renderOnboarding();
|
|
const submitButton = screen.getByRole('button', { name: '生成' });
|
|
const skipButton = screen.getByRole('button', { name: '跳过' });
|
|
|
|
expect(submitButton.className).toContain('platform-action-button--accent');
|
|
expect(submitButton.className).toContain('bg-amber-200');
|
|
expect(submitButton.className).toContain('w-full');
|
|
expect(skipButton.className).toContain(
|
|
'platform-action-button--editor-dark',
|
|
);
|
|
expect(skipButton.className).toContain('rounded-full');
|
|
expect(skipButton.className).toContain('absolute');
|
|
|
|
fireEvent.click(submitButton);
|
|
fireEvent.click(skipButton);
|
|
|
|
expect(onSubmit).toHaveBeenCalledTimes(1);
|
|
expect(onSkip).toHaveBeenCalledTimes(1);
|
|
|
|
cleanup();
|
|
renderOnboarding({ prompt: '', phase: 'input' });
|
|
expect(screen.getByRole('button', { name: '生成' })).toHaveProperty(
|
|
'disabled',
|
|
true,
|
|
);
|
|
|
|
cleanup();
|
|
renderOnboarding({ phase: 'generating' });
|
|
expect(screen.getByPlaceholderText('把你的梦讲给我听吧')).toHaveProperty(
|
|
'disabled',
|
|
true,
|
|
);
|
|
expect(screen.getByRole('button', { name: '跳过' })).toHaveProperty(
|
|
'disabled',
|
|
true,
|
|
);
|
|
|
|
cleanup();
|
|
renderOnboarding({ phase: 'generated' });
|
|
expect(screen.getByPlaceholderText('把你的梦讲给我听吧')).toHaveProperty(
|
|
'disabled',
|
|
true,
|
|
);
|
|
expect(screen.getByRole('button', { name: '生成' })).toHaveProperty(
|
|
'disabled',
|
|
true,
|
|
);
|
|
});
|
|
|
|
test('PuzzleOnboardingLoginOverlay uses shared error status and keeps login action', () => {
|
|
const onLogin = vi.fn();
|
|
const { rerender } = render(
|
|
<PuzzleOnboardingLoginOverlay
|
|
isSaving={false}
|
|
error="保存首访拼图失败"
|
|
copy="登录后保存你的拼图"
|
|
onLogin={onLogin}
|
|
/>,
|
|
);
|
|
|
|
const dialog = screen.getByRole('dialog', { name: '登录后保存你的拼图' });
|
|
|
|
expect(dialog.className).toContain('platform-modal-shell');
|
|
expect(dialog.className).toContain('!max-w-[24rem]');
|
|
expect(dialog.parentElement?.className).toContain('z-[110]');
|
|
expect(
|
|
within(dialog).queryByRole('button', { name: '关闭' }),
|
|
).toBeNull();
|
|
|
|
fireEvent.click(screen.getByRole('button', { name: '注册账号 / 登录' }));
|
|
|
|
expect(onLogin).toHaveBeenCalledTimes(1);
|
|
expect(screen.getByRole('button', { name: '注册账号 / 登录' }).className).toContain(
|
|
'platform-action-button--accent',
|
|
);
|
|
expect(screen.getByText('保存首访拼图失败').className).toContain(
|
|
'platform-status-message',
|
|
);
|
|
|
|
rerender(
|
|
<PuzzleOnboardingLoginOverlay
|
|
isSaving
|
|
error={null}
|
|
copy="登录后保存你的拼图"
|
|
onLogin={onLogin}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByRole('button', { name: '注册账号 / 登录' })).toHaveProperty(
|
|
'disabled',
|
|
true,
|
|
);
|
|
});
|