fix: refine jump hop draft detail flow
This commit is contained in:
@@ -83,6 +83,24 @@ test('跳一跳结果页默认角色预览使用陶泥儿透明 logo', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('跳一跳结果页根容器允许移动端向下滚动到操作按钮', () => {
|
||||
const { container } = render(
|
||||
<JumpHopResultView
|
||||
profile={buildProfile()}
|
||||
onBack={() => {}}
|
||||
onEdit={() => {}}
|
||||
onStartTestRun={() => {}}
|
||||
onPublish={() => {}}
|
||||
onRegenerateTiles={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
const root = container.firstElementChild as HTMLElement;
|
||||
expect(root.className).toContain('overflow-y-auto');
|
||||
expect(root.className).toContain('overscroll-contain');
|
||||
expect(root.className).toContain('safe-area-inset-bottom');
|
||||
});
|
||||
|
||||
test('跳一跳草稿结果页不请求公开排行榜', () => {
|
||||
render(
|
||||
<JumpHopResultView
|
||||
|
||||
@@ -300,7 +300,7 @@ export function JumpHopResultView({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="platform-remap-surface mx-auto flex h-full min-h-0 w-full max-w-5xl flex-col px-3 pb-3 pt-3 sm:px-4 sm:pt-4">
|
||||
<div className="platform-remap-surface mx-auto flex h-full min-h-0 w-full max-w-5xl flex-col overflow-y-auto overscroll-contain px-3 pb-[max(1.5rem,env(safe-area-inset-bottom))] pt-3 sm:px-4 sm:pt-4">
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -12878,12 +12878,18 @@ export function PlatformEntryFlowShellImpl({
|
||||
}
|
||||
|
||||
try {
|
||||
const detail = await jumpHopClient.getWorkDetail(item.profileId);
|
||||
const detail = await jumpHopClient.getWorkDetail(item.profileId, {
|
||||
audience: 'creation',
|
||||
});
|
||||
setJumpHopSession(null);
|
||||
setJumpHopRun(null);
|
||||
setJumpHopWork(detail.item);
|
||||
setJumpHopRuntimeReturnStage('jump-hop-result');
|
||||
enterCreateTab();
|
||||
pushAppHistoryPath('/creation/jump-hop/result');
|
||||
writeCreationUrlState(
|
||||
buildJumpHopCreationUrlState({ work: detail.item }),
|
||||
);
|
||||
setSelectionStage('jump-hop-result');
|
||||
} catch (error) {
|
||||
setJumpHopError(
|
||||
@@ -14073,7 +14079,11 @@ export function PlatformEntryFlowShellImpl({
|
||||
let work: JumpHopWorkProfileResponse | null = null;
|
||||
try {
|
||||
if (profileId) {
|
||||
work = (await jumpHopClient.getWorkDetail(profileId)).item;
|
||||
work = (
|
||||
await jumpHopClient.getWorkDetail(profileId, {
|
||||
audience: 'creation',
|
||||
})
|
||||
).item;
|
||||
}
|
||||
} catch {
|
||||
work = null;
|
||||
|
||||
@@ -8055,10 +8055,84 @@ test('direct jump hop result route restores work detail by profile id', async ()
|
||||
expect(screen.queryByText('跳一跳草稿未恢复')).toBeNull();
|
||||
expect(jumpHopClient.getWorkDetail).toHaveBeenCalledWith(
|
||||
'jump-hop-profile-restore-1',
|
||||
{ audience: 'creation' },
|
||||
);
|
||||
expect(jumpHopClient.getSession).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('completed unpublished jump hop draft opens result page without starting runtime', async () => {
|
||||
const user = userEvent.setup();
|
||||
const work = buildMockJumpHopWork({
|
||||
summary: {
|
||||
runtimeKind: 'jump-hop',
|
||||
workId: 'jump-hop-work-draft-ready-1',
|
||||
profileId: 'jump-hop-profile-draft-ready-1',
|
||||
ownerUserId: 'user-1',
|
||||
sourceSessionId: 'jump-hop-session-draft-ready-1',
|
||||
themeText: '未发布跳一跳草稿',
|
||||
workTitle: '未发布跳一跳草稿',
|
||||
workDescription: '已经生成完成,但还没有发布。',
|
||||
themeTags: ['草稿'],
|
||||
difficulty: 'standard',
|
||||
stylePreset: 'paper-toy',
|
||||
coverImageSrc: null,
|
||||
publicationStatus: 'draft',
|
||||
playCount: 0,
|
||||
updatedAt: '2026-05-30T10:00:00.000Z',
|
||||
publishedAt: null,
|
||||
publishReady: true,
|
||||
generationStatus: 'ready',
|
||||
},
|
||||
});
|
||||
vi.mocked(jumpHopClient.listWorks).mockResolvedValue({
|
||||
items: [work.summary],
|
||||
});
|
||||
vi.mocked(jumpHopClient.getWorkDetail).mockResolvedValueOnce({
|
||||
item: work,
|
||||
} satisfies JumpHopWorkDetailResponse);
|
||||
vi.mocked(fetchCreationEntryConfig).mockResolvedValueOnce({
|
||||
...testCreationEntryConfig,
|
||||
creationTypes: [
|
||||
...testCreationEntryConfig.creationTypes,
|
||||
{
|
||||
id: 'jump-hop',
|
||||
title: '跳一跳',
|
||||
subtitle: '主题驱动平台跳跃',
|
||||
badge: '可创建',
|
||||
imageSrc: '/creation-type-references/jump-hop.webp',
|
||||
visible: true,
|
||||
open: true,
|
||||
sortOrder: 55,
|
||||
categoryId: 'recommended',
|
||||
categoryLabel: '热门推荐',
|
||||
categorySortOrder: 20,
|
||||
updatedAtMicros: 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
render(<TestWrapper withAuth />);
|
||||
|
||||
await openDraftHub(user);
|
||||
const draftPanel = getPlatformTabPanel('saves');
|
||||
await user.click(
|
||||
await within(draftPanel).findByRole('button', {
|
||||
name: /继续创作《未发布跳一跳草稿》/u,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(await screen.findByText('未发布跳一跳草稿')).toBeTruthy();
|
||||
expect(jumpHopClient.getWorkDetail).toHaveBeenCalledWith(
|
||||
'jump-hop-profile-draft-ready-1',
|
||||
{ audience: 'creation' },
|
||||
);
|
||||
expect(jumpHopClient.startRun).not.toHaveBeenCalled();
|
||||
expect(window.location.pathname).toBe('/creation/jump-hop/result');
|
||||
expect(window.location.search).toContain(
|
||||
'profileId=jump-hop-profile-draft-ready-1',
|
||||
);
|
||||
});
|
||||
|
||||
test('embedded puzzle form maps raw bearer token errors to user-facing auth copy', async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
|
||||
@@ -185,9 +185,16 @@ export function executeJumpHopCreationAction(
|
||||
.then(normalizeJumpHopActionResponse);
|
||||
}
|
||||
|
||||
export async function getJumpHopWorkDetail(profileId: string) {
|
||||
export async function getJumpHopWorkDetail(
|
||||
profileId: string,
|
||||
options: { audience?: 'creation' | 'runtime' } = {},
|
||||
) {
|
||||
const base =
|
||||
options.audience === 'creation'
|
||||
? JUMP_HOP_WORKS_API_BASE
|
||||
: `${JUMP_HOP_RUNTIME_API_BASE}/works`;
|
||||
const response = await requestJson<JumpHopWorkDetailResponse>(
|
||||
`${JUMP_HOP_RUNTIME_API_BASE}/works/${encodeURIComponent(profileId)}`,
|
||||
`${base}/${encodeURIComponent(profileId)}`,
|
||||
{ method: 'GET' },
|
||||
'读取跳一跳作品详情失败',
|
||||
);
|
||||
|
||||
@@ -529,6 +529,44 @@ describe('miniGameDraftGenerationProgress', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test('jump hop generation anchors hide unused style preset fallback', () => {
|
||||
const entries = buildJumpHopGenerationAnchorEntries({
|
||||
sessionId: 'jump-hop-session-style-hidden',
|
||||
ownerUserId: 'user-1',
|
||||
status: 'generating',
|
||||
draft: {
|
||||
templateId: 'jump-hop',
|
||||
templateName: '跳一跳',
|
||||
profileId: 'jump-hop-profile-style-hidden',
|
||||
themeText: '水果',
|
||||
workTitle: '水果跳一跳',
|
||||
workDescription: '水果主题跳一跳。',
|
||||
themeTags: ['水果'],
|
||||
difficulty: 'standard',
|
||||
stylePreset: 'minimal-blocks',
|
||||
characterPrompt: '内置默认 3D 角色',
|
||||
tilePrompt: '',
|
||||
endMoodPrompt: null,
|
||||
characterAsset: null,
|
||||
tileAtlasAsset: null,
|
||||
tileAssets: [],
|
||||
path: null,
|
||||
coverComposite: null,
|
||||
generationStatus: 'generating',
|
||||
},
|
||||
createdAt: '2026-06-06T10:00:00.000Z',
|
||||
updatedAt: '2026-06-06T10:00:00.000Z',
|
||||
});
|
||||
|
||||
expect(entries).toEqual([
|
||||
{
|
||||
id: 'jump-hop-theme',
|
||||
label: '主题',
|
||||
value: '水果',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('wooden fish draft generation exposes hit object, background and back button pipeline', () => {
|
||||
const state = createMiniGameDraftGenerationState('wooden-fish');
|
||||
|
||||
|
||||
@@ -1074,7 +1074,7 @@ export function buildJumpHopGenerationAnchorEntries(
|
||||
workTitle?: string;
|
||||
themeText?: string;
|
||||
characterPrompt?: string;
|
||||
stylePreset?: string;
|
||||
tilePrompt?: string;
|
||||
} | null;
|
||||
}
|
||||
| null
|
||||
@@ -1098,7 +1098,7 @@ export function buildJumpHopGenerationAnchorEntries(
|
||||
value:
|
||||
formPayload?.tilePrompt?.trim() ||
|
||||
config?.tilePrompt?.trim() ||
|
||||
draft?.stylePreset?.trim() ||
|
||||
draft?.tilePrompt?.trim() ||
|
||||
'',
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user