108 lines
3.4 KiB
TypeScript
108 lines
3.4 KiB
TypeScript
/* @vitest-environment jsdom */
|
||
|
||
import { render, screen, waitFor } from '@testing-library/react';
|
||
import userEvent from '@testing-library/user-event';
|
||
import { beforeEach, expect, test, vi } from 'vitest';
|
||
|
||
import type { JumpHopSessionResponse } from '../../../../packages/shared/src/contracts/jumpHop';
|
||
import { jumpHopClient } from '../../../services/jump-hop/jumpHopClient';
|
||
import { JumpHopCreationWorkspace } from './JumpHopCreationWorkspace';
|
||
|
||
vi.mock('../../../services/jump-hop/jumpHopClient', () => ({
|
||
jumpHopClient: {
|
||
createSession: vi.fn(),
|
||
},
|
||
}));
|
||
|
||
const mockCreateSession = vi.mocked(jumpHopClient.createSession);
|
||
|
||
beforeEach(() => {
|
||
mockCreateSession.mockReset();
|
||
});
|
||
|
||
function createSessionResponse(): JumpHopSessionResponse {
|
||
return {
|
||
session: {
|
||
sessionId: 'jump-session-1',
|
||
ownerUserId: 'user-1',
|
||
status: 'draft',
|
||
draft: null,
|
||
createdAt: '2026-05-30T10:00:00.000Z',
|
||
updatedAt: '2026-05-30T10:00:00.000Z',
|
||
},
|
||
};
|
||
}
|
||
|
||
test('jump hop workspace submits theme payload after required field is filled', async () => {
|
||
const user = userEvent.setup();
|
||
const onSubmitted = vi.fn();
|
||
const sessionResponse = createSessionResponse();
|
||
mockCreateSession.mockResolvedValue(sessionResponse);
|
||
|
||
render(
|
||
<JumpHopCreationWorkspace onBack={() => {}} onSubmitted={onSubmitted} />,
|
||
);
|
||
|
||
const submitButton = screen.getByRole('button', { name: '生成' });
|
||
expect(submitButton).toHaveProperty('disabled', true);
|
||
|
||
expect(screen.getByLabelText('主题')).toBeTruthy();
|
||
expect(screen.queryByLabelText('作品标题')).toBeNull();
|
||
expect(screen.queryByLabelText('角色提示词')).toBeNull();
|
||
|
||
await user.type(screen.getByLabelText('主题'), '云朵跳台');
|
||
|
||
expect(submitButton).toHaveProperty('disabled', false);
|
||
await user.click(submitButton);
|
||
|
||
await waitFor(() => {
|
||
expect(mockCreateSession).toHaveBeenCalledWith({
|
||
templateId: 'jump-hop',
|
||
themeText: '云朵跳台',
|
||
workTitle: '云朵跳台跳一跳',
|
||
workDescription: '云朵跳台主题的俯视角跳跃作品',
|
||
themeTags: ['云朵跳台', '跳一跳', '休闲'],
|
||
difficulty: 'standard',
|
||
stylePreset: 'minimal-blocks',
|
||
characterPrompt: '内置默认 3D 角色',
|
||
tilePrompt: '云朵跳台主题的正面30度视角主题物体图集,物体本身作为跳跃落点',
|
||
endMoodPrompt: null,
|
||
});
|
||
});
|
||
expect(onSubmitted).toHaveBeenCalledWith(
|
||
sessionResponse,
|
||
expect.objectContaining({
|
||
templateId: 'jump-hop',
|
||
themeText: '云朵跳台',
|
||
}),
|
||
);
|
||
});
|
||
|
||
test('jump hop workspace calls back when return button is clicked', async () => {
|
||
const user = userEvent.setup();
|
||
const onBack = vi.fn();
|
||
|
||
render(<JumpHopCreationWorkspace onBack={onBack} onSubmitted={() => {}} />);
|
||
|
||
await user.click(screen.getByRole('button', { name: '返回' }));
|
||
|
||
expect(onBack).toHaveBeenCalledTimes(1);
|
||
});
|
||
|
||
test('jump hop workspace can defer visible chrome to the unified creation page', () => {
|
||
const { container } = render(
|
||
<JumpHopCreationWorkspace
|
||
onBack={() => {}}
|
||
onSubmitted={() => {}}
|
||
showBackButton={false}
|
||
unifiedChrome
|
||
/>,
|
||
);
|
||
|
||
const workspace = container.querySelector('.jump-hop-workspace');
|
||
expect(workspace?.getAttribute('data-unified-chrome')).toBe('true');
|
||
expect(workspace?.className).toContain('max-w-none');
|
||
expect(workspace?.className).not.toContain('platform-remap-surface');
|
||
expect(screen.queryByRole('button', { name: '返回' })).toBeNull();
|
||
});
|