fix: repair api server merge fallout

This commit is contained in:
kdletters
2026-05-02 14:18:12 +08:00
parent 8f4ca9abfa
commit 9b5aa25fe9
16 changed files with 330 additions and 37 deletions

View File

@@ -5,8 +5,8 @@ import userEvent from '@testing-library/user-event';
import { useState } from 'react';
import { expect, test, vi } from 'vitest';
import type { CustomWorldPlayableNpc, CustomWorldProfile } from '../types';
import * as rpgCreationAssetClient from '../services/rpg-creation/rpgCreationAssetClient';
import type { CustomWorldPlayableNpc, CustomWorldProfile } from '../types';
import { RpgCreationResultView } from './rpg-creation-result/RpgCreationResultView';
vi.mock('../services/rpg-creation/rpgCreationAssetClient', () => {
@@ -418,7 +418,7 @@ test('landmark tab previews every generated act image while keeping chapter deta
(screen.getByRole('img', {
name: '沉钟栈桥-钟楼回响',
}) as HTMLImageElement).getAttribute('src'),
).toBe('/generated-custom-world-scenes/scene-act-1.png');
).toBe('/generated-custom-world-scenes/scene-act-2.png');
});
test('readOnly result view hides edit and create actions for agent preview mode', async () => {

View File

@@ -142,8 +142,8 @@ import {
usePuzzleRuntimeProp as consumePuzzleRuntimeProp,
} from '../../services/puzzle-runtime';
import {
applyLocalPuzzleFreezeTime,
advanceLocalPuzzleLevel,
applyLocalPuzzleFreezeTime,
dragLocalPuzzlePiece,
extendLocalPuzzleTime,
isLocalPuzzleRun,
@@ -151,7 +151,6 @@ import {
resolvePuzzleRestartLevelId,
restartLocalPuzzleLevel,
setLocalPuzzlePaused,
startLocalPuzzleRun,
submitLocalPuzzleLeaderboard,
swapLocalPuzzlePieces,
} from '../../services/puzzle-runtime/puzzleLocalRuntime';
@@ -222,6 +221,7 @@ type PuzzleRuntimeReturnStage =
| 'platform';
type BigFishRuntimeReturnStage = 'big-fish-result' | 'work-detail' | 'platform';
type BigFishRuntimeSessionSource = 'draft' | 'work' | null;
type PuzzleSaveArchiveState = {
runtimeKind?: unknown;
@@ -953,12 +953,12 @@ export function PlatformEntryFlowShellImpl({
title: string;
publicWorkCode: string;
} | null>(null);
const [bigFishRuntimeWork, setBigFishRuntimeWork] =
const [_bigFishRuntimeWork, setBigFishRuntimeWork] =
useState<BigFishWorkSummary | null>(null);
const [bigFishRuntimeStartedAt, setBigFishRuntimeStartedAt] = useState<
number | null
>(null);
const [bigFishRuntimeSessionSource, setBigFishRuntimeSessionSource] =
const [_bigFishRuntimeSessionSource, setBigFishRuntimeSessionSource] =
useState<BigFishRuntimeSessionSource>(null);
const [bigFishRuntimeReturnStage, setBigFishRuntimeReturnStage] =
useState<BigFishRuntimeReturnStage>('platform');
@@ -2142,7 +2142,7 @@ export function PlatformEntryFlowShellImpl({
],
);
const buildPuzzleTestWork = useCallback(
const _buildPuzzleTestWork = useCallback(
(draft: PuzzleResultDraft) => {
const profileId =
puzzleSession?.publishedProfileId ??
@@ -2206,11 +2206,14 @@ export function PlatformEntryFlowShellImpl({
setPuzzleError(null);
try {
const { item } = await updatePuzzleWork(profileId, {
workTitle: draft.workTitle,
workDescription: draft.workDescription,
levelName: draft.levelName,
summary: draft.summary,
themeTags: draft.themeTags,
coverImageSrc: draft.coverImageSrc,
coverAssetId: draft.coverAssetId,
levels: draft.levels ?? [],
});
const { run } = await startPuzzleRun({ profileId: item.profileId });
setSelectedPuzzleDetail(item);

View File

@@ -61,9 +61,11 @@ import {
} from '../../services/puzzle-gallery';
import {
advancePuzzleNextLevel,
dragPuzzlePieceOrGroup,
getPuzzleRun,
startPuzzleRun,
submitPuzzleLeaderboard,
swapPuzzlePieces,
updatePuzzleRunPause,
usePuzzleRuntimeProp,
} from '../../services/puzzle-runtime';
@@ -220,6 +222,7 @@ vi.mock('../../services/puzzle-gallery', () => ({
vi.mock('../../services/puzzle-runtime', () => ({
advancePuzzleNextLevel: vi.fn(),
dragPuzzlePieceOrGroup: vi.fn(),
getPuzzleRun: vi.fn(),
startPuzzleRun: vi.fn(),
swapPuzzlePieces: vi.fn(),
@@ -1193,7 +1196,7 @@ beforeEach(() => {
vi.mocked(upsertProfileBrowseHistory).mockResolvedValue([]);
vi.mocked(clearProfileBrowseHistory).mockResolvedValue([]);
vi.mocked(deleteRpgEntryWorldProfile).mockResolvedValue([]);
vi.mocked(recordBigFishPlay).mockResolvedValue(undefined);
vi.mocked(recordBigFishPlay).mockResolvedValue({ items: [] });
vi.mocked(recordRpgEntryWorldGalleryPlay).mockImplementation(
async (ownerUserId, profileId) => ({
ownerUserId,
@@ -1676,28 +1679,30 @@ beforeEach(() => {
{
entityId: 'owned-1',
level: 1,
position: payload.direction,
position: payload,
radius: 12,
offscreenSeconds: 0,
},
],
wildEntities: [],
cameraCenter: payload.direction,
lastInput: payload.direction,
cameraCenter: payload,
lastInput: payload,
eventLog: ['机械鱼群继续巡游。'],
updatedAt: '2026-04-25T12:12:01.000Z',
},
}));
vi.mocked(recordBigFishPlay).mockResolvedValue(undefined);
vi.mocked(recordBigFishPlay).mockResolvedValue({ items: [] });
vi.mocked(match3dCreationClient.createSession).mockResolvedValue({
session: null,
session: buildMockMatch3DAgentSession(),
});
vi.mocked(match3dCreationClient.getSession).mockResolvedValue({
session: null,
session: buildMockMatch3DAgentSession(),
});
vi.mocked(match3dCreationClient.streamMessage).mockResolvedValue(null);
vi.mocked(match3dCreationClient.streamMessage).mockResolvedValue(
buildMockMatch3DAgentSession(),
);
vi.mocked(match3dCreationClient.executeAction).mockResolvedValue({
session: null,
session: buildMockMatch3DAgentSession(),
});
vi.mocked(listMatch3DWorks).mockResolvedValue({
items: [],
@@ -2931,6 +2936,12 @@ test('formal puzzle next level uses backend run and leaderboard keeps frontend l
},
},
});
vi.mocked(dragPuzzlePieceOrGroup).mockResolvedValue({
run: clearedSecondLevel,
});
vi.mocked(swapPuzzlePieces).mockResolvedValue({
run: clearedSecondLevel,
});
vi.mocked(dragLocalPuzzlePiece).mockReturnValue(clearedSecondLevel);
vi.mocked(swapLocalPuzzlePieces).mockReturnValue(clearedSecondLevel);
@@ -2983,7 +2994,7 @@ test('formal puzzle next level uses backend run and leaderboard keeps frontend l
await waitFor(() => {
expect(advancePuzzleNextLevel).toHaveBeenCalledWith(firstLevel.runId);
});
expect(advancePuzzleNextLevel).not.toHaveBeenCalled();
expect(advancePuzzleNextLevel).toHaveBeenCalledTimes(1);
expect((await screen.findAllByText('星桥机关')).length).toBeGreaterThan(0);
await user.click(document.querySelector('[data-piece-id="piece-0"]')!);

View File

@@ -77,6 +77,27 @@ export async function swapPuzzlePieces(
);
}
/**
* 提交拖拽拼图块或已合并拼图组后的目标格。
*/
export async function dragPuzzlePieceOrGroup(
runId: string,
payload: DragPuzzlePieceRequest,
) {
return requestJson<PuzzleRunResponse>(
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/drag`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
},
'拖动拼图块失败',
{
retry: PUZZLE_RUNTIME_WRITE_RETRY,
},
);
}
/**
* 进入推荐出的下一关。
*/