fix: route recommend puzzle next through feed

This commit is contained in:
2026-06-07 14:14:16 +08:00
parent e56a25243c
commit 8f460feb41
11 changed files with 84 additions and 126 deletions

View File

@@ -13,16 +13,16 @@ import type {
CustomWorldAgentSessionSnapshot,
CustomWorldWorkSummary,
} from '../../../packages/shared/src/contracts/customWorldAgent';
import type {
BabyObjectMatchDraft,
CreateBabyObjectMatchDraftRequest,
} from '../../../packages/shared/src/contracts/edutainmentBabyObject';
import type {
JumpHopRuntimeRunSnapshotResponse,
JumpHopWorkDetailResponse,
JumpHopWorkProfileResponse,
JumpHopWorkSummaryResponse,
} from '../../../packages/shared/src/contracts/jumpHop';
import type {
BabyObjectMatchDraft,
CreateBabyObjectMatchDraftRequest,
} from '../../../packages/shared/src/contracts/edutainmentBabyObject';
import type { Match3DAgentSessionSnapshot } from '../../../packages/shared/src/contracts/match3dAgent';
import type { Match3DRunSnapshot } from '../../../packages/shared/src/contracts/match3dRuntime';
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
@@ -71,7 +71,6 @@ import {
submitBigFishInput,
} from '../../services/big-fish-runtime';
import { listBigFishWorks } from '../../services/big-fish-works';
import { jumpHopClient } from '../../services/jump-hop/jumpHopClient';
import {
type CreationEntryConfig,
fetchCreationEntryConfig,
@@ -91,6 +90,7 @@ import {
regenerateBabyObjectMatchDraftAssets,
saveBabyObjectMatchDraft,
} from '../../services/edutainment-baby-object';
import { jumpHopClient } from '../../services/jump-hop/jumpHopClient';
import { match3dCreationClient } from '../../services/match3d-creation';
import { createServerMatch3DRuntimeAdapter } from '../../services/match3d-runtime';
import {
@@ -334,10 +334,6 @@ const ISOLATED_RUNTIME_AUTH_OPTIONS = {
notifyAuthStateChange: false,
clearAuthOnUnauthorized: false,
};
const RECOMMEND_RUNTIME_AUTH_OPTIONS = {
...ISOLATED_RUNTIME_AUTH_OPTIONS,
runtimeGuestToken: 'runtime-guest-token',
};
const LOGGED_IN_RECOMMEND_RUNTIME_AUTH_OPTIONS = ISOLATED_RUNTIME_AUTH_OPTIONS;
function getPlatformTabPanel(tab: string) {
@@ -7505,7 +7501,7 @@ test('logged out home recommendation next starts the next puzzle work', async ()
});
});
test('home recommendation puzzle next level switches to similar work detail', async () => {
test('home recommendation puzzle next level uses unified recommend switching', async () => {
const user = userEvent.setup();
const entryWork = {
workId: 'puzzle-work-public-guest-1',
@@ -7547,17 +7543,17 @@ test('home recommendation puzzle next level switches to similar work detail', as
},
],
} satisfies PuzzleWorkSummary;
const similarWork = {
const nextRecommendWork = {
...entryWork,
workId: 'puzzle-work-similar-guest-1',
profileId: 'puzzle-profile-similar-guest-1',
workId: 'puzzle-work-public-guest-2',
profileId: 'puzzle-profile-public-guest-2',
levelName: '风塔试炼',
summary: '另一套奇幻机关拼图。',
summary: '另一套推荐拼图。',
levels: [
{
levelId: 'similar-level-1',
levelId: 'next-recommend-level-1',
levelName: '风塔试炼',
pictureDescription: '相似作品首关。',
pictureDescription: '推荐队列下一张拼图。',
candidates: [],
selectedCandidateId: null,
coverImageSrc: null,
@@ -7586,47 +7582,35 @@ test('home recommendation puzzle next level switches to similar work detail', as
entryWork.profileId,
entryWork.levelName,
);
const similarRun = {
...buildMockPuzzleRun(similarWork.profileId, similarWork.levelName),
runId: clearedRun.runId,
entryProfileId: entryWork.profileId,
currentLevelIndex: 2,
currentLevel: {
...buildMockPuzzleRun(similarWork.profileId, similarWork.levelName)
.currentLevel!,
runId: clearedRun.runId,
levelIndex: 2,
levelId: 'similar-level-1',
startedAtMs: Date.now(),
},
};
const nextRecommendRun = buildMockPuzzleRun(
nextRecommendWork.profileId,
nextRecommendWork.levelName,
);
vi.mocked(listPuzzleGallery).mockResolvedValue({
items: [entryWork],
items: [entryWork, nextRecommendWork],
});
vi.mocked(getPuzzleGalleryDetail).mockImplementation(async (profileId) => ({
item: profileId === similarWork.profileId ? similarWork : entryWork,
item: profileId === nextRecommendWork.profileId ? nextRecommendWork : entryWork,
}));
vi.mocked(startPuzzleRun).mockResolvedValue({
run: {
...startedRun,
currentLevel: {
...startedRun.currentLevel!,
startedAtMs: Date.now(),
vi.mocked(startPuzzleRun).mockImplementation(async (payload) => {
const run =
payload.profileId === nextRecommendWork.profileId
? nextRecommendRun
: startedRun;
return {
run: {
...run,
currentLevel: {
...run.currentLevel!,
startedAtMs: Date.now(),
},
},
},
};
});
vi.mocked(submitPuzzleLeaderboard).mockResolvedValue({
run: clearedRunWithSameWorkNext,
});
let resolveAdvancePuzzleNextLevel!: (value: {
run: PuzzleRunSnapshot;
}) => void;
vi.mocked(advancePuzzleNextLevel).mockReturnValue(
new Promise((resolve) => {
resolveAdvancePuzzleNextLevel = resolve;
}),
);
vi.mocked(swapLocalPuzzlePieces).mockReturnValue(clearedRun);
render(<TestWrapper withAuth />);
@@ -7655,24 +7639,23 @@ test('home recommendation puzzle next level switches to similar work detail', as
await user.click(within(dialog).getByRole('button', { name: '下一关' }));
await waitFor(() => {
expect(advancePuzzleNextLevel).toHaveBeenCalledWith(clearedRun.runId, {
preferSimilarWork: true,
});
expect(startPuzzleRun).toHaveBeenCalledWith(
{
profileId: nextRecommendWork.profileId,
levelId: null,
},
LOGGED_IN_RECOMMEND_RUNTIME_AUTH_OPTIONS,
);
});
expect(advancePuzzleNextLevel).not.toHaveBeenCalled();
expect(screen.getByTestId('puzzle-board')).toBeTruthy();
expect(screen.queryByText('加载中...')).toBeNull();
resolveAdvancePuzzleNextLevel({ run: similarRun });
await waitFor(() => {
expect(getPuzzleGalleryDetail).toHaveBeenCalledWith(similarWork.profileId);
});
expect(
await screen.findByLabelText('风塔试炼 作品信息', undefined, {
timeout: 3000,
}),
).toBeTruthy();
expect(screen.getAllByText('风塔试炼').length).toBeGreaterThan(0);
expect(startPuzzleRun).toHaveBeenCalledTimes(1);
expect(startPuzzleRun).toHaveBeenCalledTimes(2);
});
test('home recommendation Match3D runtime keeps profile generated models when card summary is stale', async () => {