1
This commit is contained in:
@@ -18,7 +18,11 @@ import type {
|
||||
PuzzleAnchorPack,
|
||||
PuzzleResultDraft,
|
||||
} from '../../../packages/shared/src/contracts/puzzleAgentDraft';
|
||||
import type { PuzzleAgentSessionSnapshot } from '../../../packages/shared/src/contracts/puzzleAgentSession';
|
||||
import type { PuzzleAgentActionRequest } from '../../../packages/shared/src/contracts/puzzleAgentActions';
|
||||
import type {
|
||||
CreatePuzzleAgentSessionRequest,
|
||||
PuzzleAgentSessionSnapshot,
|
||||
} from '../../../packages/shared/src/contracts/puzzleAgentSession';
|
||||
import type { PuzzleRunSnapshot } from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { RpgCreationResultView } from '../../../packages/shared/src/contracts/rpgCreationResultView';
|
||||
@@ -183,6 +187,15 @@ async function openDraftHub(user: ReturnType<typeof userEvent.setup>) {
|
||||
).toBeTruthy();
|
||||
}
|
||||
|
||||
async function expectDraftHubGeneratingBadgeCountAtLeast(count: number) {
|
||||
const panel = getPlatformTabPanel('saves');
|
||||
await waitFor(() => {
|
||||
expect(within(panel).getAllByText('生成中').length).toBeGreaterThanOrEqual(
|
||||
count,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async function openDiscoverHub(user: ReturnType<typeof userEvent.setup>) {
|
||||
await clickFirstButtonByName(user, '发现');
|
||||
const panel = getPlatformTabPanel('category');
|
||||
@@ -450,6 +463,16 @@ vi.mock('../../services/match3dGeneratedModelCache', () => ({
|
||||
),
|
||||
),
|
||||
),
|
||||
normalizeMatch3DGeneratedItemAssetsForRuntime: vi.fn(
|
||||
(assets: Match3DWorkSummary['generatedItemAssets']) =>
|
||||
assets ? [...assets] : [],
|
||||
),
|
||||
mergeMatch3DGeneratedItemAssetsForRuntime: vi.fn(
|
||||
(
|
||||
primaryAssets: Match3DWorkSummary['generatedItemAssets'],
|
||||
fallbackAssets: Match3DWorkSummary['generatedItemAssets'],
|
||||
) => (primaryAssets ? [...primaryAssets] : fallbackAssets ? [...fallbackAssets] : []),
|
||||
),
|
||||
preloadMatch3DGeneratedRuntimeAssets: vi.fn(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
@@ -541,22 +564,21 @@ vi.mock('../puzzle-agent/PuzzleAgentWorkspace', () => ({
|
||||
isBusy,
|
||||
error,
|
||||
onBack,
|
||||
onExecuteAction,
|
||||
onCreateFromForm,
|
||||
}: {
|
||||
session: { sessionId: string; messages: Array<{ text: string }> } | null;
|
||||
isBusy?: boolean;
|
||||
error?: string | null;
|
||||
onBack: () => void;
|
||||
onCreateFromForm?: (payload: {
|
||||
seedText: string;
|
||||
workTitle: string;
|
||||
workDescription: string;
|
||||
pictureDescription: string;
|
||||
referenceImageSrc: string | null;
|
||||
}) => void;
|
||||
onExecuteAction: (payload: PuzzleAgentActionRequest) => void;
|
||||
onCreateFromForm?: (payload: CreatePuzzleAgentSessionRequest) => void;
|
||||
}) => (
|
||||
<div className="puzzle-agent-workspace-mock">
|
||||
<div>拼图工作区:{session?.sessionId ?? 'missing-session'}</div>
|
||||
<div data-testid="puzzle-workspace-busy-state">
|
||||
{isBusy ? 'busy' : 'idle'}
|
||||
</div>
|
||||
{session?.messages.map((message) => (
|
||||
<div key={`${session.sessionId}-${message.text}`}>{message.text}</div>
|
||||
))}
|
||||
@@ -565,13 +587,23 @@ vi.mock('../puzzle-agent/PuzzleAgentWorkspace', () => ({
|
||||
type="button"
|
||||
disabled={isBusy}
|
||||
onClick={() => {
|
||||
onCreateFromForm?.({
|
||||
const payload = {
|
||||
seedText: '暖灯猫街',
|
||||
workTitle: '暖灯猫街',
|
||||
workDescription: '一套雨夜猫街主题拼图。',
|
||||
pictureDescription: '一只猫在雨夜灯牌下回头。',
|
||||
referenceImageSrc: null,
|
||||
});
|
||||
};
|
||||
if (session) {
|
||||
onExecuteAction({
|
||||
action: 'compile_puzzle_draft',
|
||||
promptText: payload.pictureDescription,
|
||||
...payload,
|
||||
candidateCount: 1,
|
||||
});
|
||||
return;
|
||||
}
|
||||
onCreateFromForm?.(payload);
|
||||
}}
|
||||
>
|
||||
生成草稿
|
||||
@@ -1209,6 +1241,27 @@ function buildPuzzleAnchorPack(): PuzzleAnchorPack {
|
||||
};
|
||||
}
|
||||
|
||||
function buildMockPuzzleAgentSession(
|
||||
overrides: Partial<PuzzleAgentSessionSnapshot> = {},
|
||||
): PuzzleAgentSessionSnapshot {
|
||||
return {
|
||||
sessionId: 'puzzle-session-1',
|
||||
seedText: '暖灯猫街',
|
||||
currentTurn: 0,
|
||||
progressPercent: 0,
|
||||
stage: 'collecting_anchors',
|
||||
anchorPack: buildPuzzleAnchorPack(),
|
||||
draft: null,
|
||||
messages: [],
|
||||
lastAssistantReply: '先说一个你最想做成拼图的画面。',
|
||||
publishedProfileId: null,
|
||||
suggestedActions: [],
|
||||
resultPreview: null,
|
||||
updatedAt: '2026-05-14T10:00:00.000Z',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function buildClearedPuzzleRun(params: {
|
||||
runId: string;
|
||||
entryProfileId: string;
|
||||
@@ -1700,6 +1753,71 @@ beforeEach(() => {
|
||||
),
|
||||
),
|
||||
);
|
||||
vi.mocked(
|
||||
match3dGeneratedModelCache.normalizeMatch3DGeneratedItemAssetsForRuntime,
|
||||
).mockImplementation((assets) => {
|
||||
if (!assets?.length) {
|
||||
return [];
|
||||
}
|
||||
const musicCarrier = assets.find((asset) =>
|
||||
asset.backgroundMusic?.audioSrc?.trim(),
|
||||
);
|
||||
if (!musicCarrier) {
|
||||
return [...assets];
|
||||
}
|
||||
return assets.map((asset, index) =>
|
||||
index === 0
|
||||
? {
|
||||
...asset,
|
||||
backgroundMusic: asset.backgroundMusic ?? musicCarrier.backgroundMusic,
|
||||
}
|
||||
: {
|
||||
...asset,
|
||||
backgroundMusic: null,
|
||||
backgroundMusicTitle: null,
|
||||
backgroundMusicStyle: null,
|
||||
backgroundMusicPrompt: null,
|
||||
}
|
||||
);
|
||||
});
|
||||
vi.mocked(
|
||||
match3dGeneratedModelCache.mergeMatch3DGeneratedItemAssetsForRuntime,
|
||||
).mockImplementation((primaryAssets, fallbackAssets) => {
|
||||
const primary = primaryAssets ?? [];
|
||||
const fallback = fallbackAssets ?? [];
|
||||
if (primary.length <= 0) {
|
||||
return match3dGeneratedModelCache.normalizeMatch3DGeneratedItemAssetsForRuntime(
|
||||
fallback,
|
||||
);
|
||||
}
|
||||
if (fallback.length <= 0) {
|
||||
return match3dGeneratedModelCache.normalizeMatch3DGeneratedItemAssetsForRuntime(
|
||||
primary,
|
||||
);
|
||||
}
|
||||
const fallbackById = new Map(fallback.map((asset) => [asset.itemId, asset]));
|
||||
return match3dGeneratedModelCache.normalizeMatch3DGeneratedItemAssetsForRuntime(
|
||||
primary.map((asset) => {
|
||||
const fallbackAsset = fallbackById.get(asset.itemId);
|
||||
return fallbackAsset
|
||||
? {
|
||||
...asset,
|
||||
imageSrc: asset.imageSrc ?? fallbackAsset.imageSrc ?? null,
|
||||
imageObjectKey:
|
||||
asset.imageObjectKey ?? fallbackAsset.imageObjectKey ?? null,
|
||||
imageViews:
|
||||
asset.imageViews && asset.imageViews.length > 0
|
||||
? asset.imageViews
|
||||
: (fallbackAsset.imageViews ?? []),
|
||||
backgroundMusic:
|
||||
asset.backgroundMusic ?? fallbackAsset.backgroundMusic ?? null,
|
||||
backgroundAsset:
|
||||
asset.backgroundAsset ?? fallbackAsset.backgroundAsset ?? null,
|
||||
}
|
||||
: asset;
|
||||
}),
|
||||
);
|
||||
});
|
||||
vi.mocked(
|
||||
match3dGeneratedModelCache.preloadMatch3DGeneratedRuntimeAssets,
|
||||
).mockResolvedValue(undefined);
|
||||
@@ -2749,7 +2867,7 @@ test('running match3d form generation can return to draft tab and reopen progres
|
||||
await openDraftHub(user);
|
||||
|
||||
expect(await screen.findByText('抓大鹅草稿')).toBeTruthy();
|
||||
expect(screen.getAllByText('生成中').length).toBeGreaterThan(0);
|
||||
await expectDraftHubGeneratingBadgeCountAtLeast(1);
|
||||
|
||||
await user.click(
|
||||
screen.getByRole('button', { name: /继续创作《抓大鹅草稿》/u }),
|
||||
@@ -2761,6 +2879,93 @@ test('running match3d form generation can return to draft tab and reopen progres
|
||||
});
|
||||
});
|
||||
|
||||
test('running match3d persisted draft reopens progress instead of unfinished result', async () => {
|
||||
const user = userEvent.setup();
|
||||
const runningSession = buildMockMatch3DAgentSession({
|
||||
sessionId: 'match3d-running-persisted-session',
|
||||
draft: null,
|
||||
stage: 'collecting_config',
|
||||
});
|
||||
const persistedRunningSession = buildMockMatch3DAgentSession({
|
||||
sessionId: 'match3d-running-persisted-session',
|
||||
stage: 'draft_ready',
|
||||
draft: {
|
||||
profileId: 'match3d-running-persisted-profile',
|
||||
gameName: '赛博水果摊',
|
||||
themeText: '赛博水果摊',
|
||||
summary: '',
|
||||
tags: ['水果', '抓大鹅'],
|
||||
coverImageSrc: null,
|
||||
referenceImageSrc: null,
|
||||
clearCount: 12,
|
||||
difficulty: 4,
|
||||
generatedItemAssets: [],
|
||||
},
|
||||
});
|
||||
const persistedRunningWork: Match3DWorkSummary = {
|
||||
workId: 'match3d-running-persisted-work',
|
||||
profileId: 'match3d-running-persisted-profile',
|
||||
ownerUserId: 'user-1',
|
||||
sourceSessionId: 'match3d-running-persisted-session',
|
||||
gameName: '赛博水果摊',
|
||||
themeText: '赛博水果摊',
|
||||
summary: '正在生成玩法素材。',
|
||||
tags: ['水果', '抓大鹅'],
|
||||
coverImageSrc: null,
|
||||
referenceImageSrc: null,
|
||||
clearCount: 12,
|
||||
difficulty: 4,
|
||||
publicationStatus: 'draft',
|
||||
playCount: 0,
|
||||
updatedAt: '2026-05-14T10:30:00.000Z',
|
||||
publishedAt: null,
|
||||
publishReady: false,
|
||||
generatedItemAssets: [],
|
||||
};
|
||||
vi.mocked(match3dCreationClient.createSession).mockResolvedValue({
|
||||
session: runningSession,
|
||||
});
|
||||
vi.mocked(match3dCreationClient.executeAction).mockRejectedValueOnce(
|
||||
new Error('素材生成仍在后台处理'),
|
||||
);
|
||||
vi.mocked(match3dCreationClient.getSession).mockResolvedValue({
|
||||
session: persistedRunningSession,
|
||||
});
|
||||
vi.mocked(listMatch3DWorks).mockResolvedValue({
|
||||
items: [persistedRunningWork],
|
||||
});
|
||||
vi.mocked(getMatch3DWorkDetail).mockResolvedValue({
|
||||
item: persistedRunningWork,
|
||||
});
|
||||
|
||||
render(<TestWrapper withAuth />);
|
||||
|
||||
await openCreateTemplateHub(user);
|
||||
await user.click(screen.getByRole('tab', { name: '抓大鹅' }));
|
||||
await user.click(
|
||||
await screen.findByRole('button', { name: '生成抓大鹅草稿' }),
|
||||
);
|
||||
expect(await screen.findByText('抓大鹅草稿生成进度')).toBeTruthy();
|
||||
expect(
|
||||
await screen.findAllByText('素材生成仍在后台处理'),
|
||||
).not.toHaveLength(0);
|
||||
vi.mocked(match3dCreationClient.getSession).mockClear();
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '返回创作中心' }));
|
||||
await openDraftHub(user);
|
||||
await expectDraftHubGeneratingBadgeCountAtLeast(1);
|
||||
|
||||
await user.click(
|
||||
await screen.findByRole('button', { name: /继续创作《赛博水果摊》/u }),
|
||||
);
|
||||
|
||||
expect(await screen.findByText('抓大鹅草稿生成进度')).toBeTruthy();
|
||||
expect(screen.queryByText('抓大鹅结果页')).toBeNull();
|
||||
expect(match3dCreationClient.getSession).toHaveBeenCalledWith(
|
||||
'match3d-running-persisted-session',
|
||||
);
|
||||
});
|
||||
|
||||
test('running match3d form generation keeps other creation templates available', async () => {
|
||||
const user = userEvent.setup();
|
||||
const runningSession = buildMockMatch3DAgentSession({
|
||||
@@ -2966,8 +3171,8 @@ test('running match3d form generation keeps same template generation available',
|
||||
await openDraftHub(user);
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByText('抓大鹅草稿').length).toBeGreaterThanOrEqual(2);
|
||||
expect(screen.getAllByText('生成中').length).toBeGreaterThanOrEqual(2);
|
||||
});
|
||||
await expectDraftHubGeneratingBadgeCountAtLeast(2);
|
||||
|
||||
await act(async () => {
|
||||
resolveFirstCompile({
|
||||
@@ -2983,6 +3188,126 @@ test('running match3d form generation keeps same template generation available',
|
||||
});
|
||||
});
|
||||
|
||||
test('running puzzle form generation creates a new puzzle draft on same template submit', async () => {
|
||||
const user = userEvent.setup();
|
||||
const firstSession = buildMockPuzzleAgentSession({
|
||||
sessionId: 'puzzle-parallel-session-1',
|
||||
});
|
||||
const secondSession = buildMockPuzzleAgentSession({
|
||||
sessionId: 'puzzle-parallel-session-2',
|
||||
});
|
||||
let resolveFirstCompile!: (value: {
|
||||
operation: {
|
||||
operationId: string;
|
||||
type: 'compile_puzzle_draft';
|
||||
status: 'completed';
|
||||
phaseLabel: string;
|
||||
phaseDetail: string;
|
||||
progress: number;
|
||||
};
|
||||
session: PuzzleAgentSessionSnapshot;
|
||||
}) => void;
|
||||
let resolveSecondCompile!: (value: {
|
||||
operation: {
|
||||
operationId: string;
|
||||
type: 'compile_puzzle_draft';
|
||||
status: 'completed';
|
||||
phaseLabel: string;
|
||||
phaseDetail: string;
|
||||
progress: number;
|
||||
};
|
||||
session: PuzzleAgentSessionSnapshot;
|
||||
}) => void;
|
||||
vi.mocked(createPuzzleAgentSession)
|
||||
.mockResolvedValueOnce({ session: firstSession })
|
||||
.mockResolvedValueOnce({ session: secondSession });
|
||||
vi.mocked(executePuzzleAgentAction)
|
||||
.mockReturnValueOnce(
|
||||
new Promise((resolve) => {
|
||||
resolveFirstCompile = resolve;
|
||||
}),
|
||||
)
|
||||
.mockReturnValueOnce(
|
||||
new Promise((resolve) => {
|
||||
resolveSecondCompile = resolve;
|
||||
}),
|
||||
);
|
||||
|
||||
render(<TestWrapper withAuth />);
|
||||
|
||||
await openCreateTemplateHub(user);
|
||||
await user.click(await screen.findByRole('button', { name: '生成草稿' }));
|
||||
expect(await screen.findByText('拼图草稿生成进度')).toBeTruthy();
|
||||
|
||||
await user.click(screen.getByRole('button', { name: '返回创作中心' }));
|
||||
const puzzleTab = await screen.findByRole('tab', { name: '拼图' });
|
||||
expect((puzzleTab as HTMLButtonElement).disabled).toBe(false);
|
||||
await user.click(puzzleTab);
|
||||
|
||||
expect(await screen.findByText('拼图工作区:missing-session')).toBeTruthy();
|
||||
expect(screen.getByTestId('puzzle-workspace-busy-state')).toHaveProperty(
|
||||
'textContent',
|
||||
'idle',
|
||||
);
|
||||
const secondGenerateButton = await screen.findByRole('button', {
|
||||
name: '生成草稿',
|
||||
});
|
||||
expect((secondGenerateButton as HTMLButtonElement).disabled).toBe(false);
|
||||
await user.click(secondGenerateButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(createPuzzleAgentSession).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
expect(executePuzzleAgentAction).toHaveBeenCalledTimes(2);
|
||||
expect(executePuzzleAgentAction).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'puzzle-parallel-session-1',
|
||||
expect.objectContaining({ action: 'compile_puzzle_draft' }),
|
||||
);
|
||||
expect(executePuzzleAgentAction).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
'puzzle-parallel-session-2',
|
||||
expect.objectContaining({ action: 'compile_puzzle_draft' }),
|
||||
);
|
||||
|
||||
expect(await screen.findByText('拼图草稿生成进度')).toBeTruthy();
|
||||
await user.click(screen.getByRole('button', { name: '返回创作中心' }));
|
||||
await openDraftHub(user);
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByText('拼图草稿').length).toBeGreaterThanOrEqual(2);
|
||||
});
|
||||
await expectDraftHubGeneratingBadgeCountAtLeast(2);
|
||||
|
||||
await act(async () => {
|
||||
resolveFirstCompile({
|
||||
operation: {
|
||||
operationId: 'compile-puzzle-parallel-1',
|
||||
type: 'compile_puzzle_draft',
|
||||
status: 'completed',
|
||||
phaseLabel: '已完成',
|
||||
phaseDetail: '草稿已生成',
|
||||
progress: 1,
|
||||
},
|
||||
session: buildMockPuzzleAgentSession({
|
||||
sessionId: 'puzzle-parallel-session-1',
|
||||
}),
|
||||
});
|
||||
resolveSecondCompile({
|
||||
operation: {
|
||||
operationId: 'compile-puzzle-parallel-2',
|
||||
type: 'compile_puzzle_draft',
|
||||
status: 'completed',
|
||||
phaseLabel: '已完成',
|
||||
phaseDetail: '草稿已生成',
|
||||
progress: 1,
|
||||
},
|
||||
session: buildMockPuzzleAgentSession({
|
||||
sessionId: 'puzzle-parallel-session-2',
|
||||
}),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('match3d result trial passes generated models into first runtime mount', async () => {
|
||||
const user = userEvent.setup();
|
||||
const generatedItemAssets: Match3DWorkSummary['generatedItemAssets'] = [
|
||||
@@ -3318,6 +3643,134 @@ test('match3d draft generation auto starts trial and runtime back opens draft re
|
||||
expect(screen.getByText('自动试玩抓大鹅')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('completed match3d draft notice first opens trial then reopens result', async () => {
|
||||
const user = userEvent.setup();
|
||||
const generatedItemAssets: Match3DWorkSummary['generatedItemAssets'] = [
|
||||
{
|
||||
itemId: 'match3d-notice-item-1',
|
||||
itemName: '草莓',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/items/match3d-notice-item-1-item/image.png',
|
||||
imageObjectKey:
|
||||
'generated-match3d-assets/session/profile/items/match3d-notice-item-1-item/image.png',
|
||||
imageViews: [],
|
||||
modelSrc: null,
|
||||
modelObjectKey: null,
|
||||
modelFileName: null,
|
||||
taskUuid: 'task-notice-strawberry',
|
||||
subscriptionKey: 'sub-notice-strawberry',
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
},
|
||||
];
|
||||
const runningSession = buildMockMatch3DAgentSession({
|
||||
sessionId: 'match3d-notice-session-1',
|
||||
draft: null,
|
||||
stage: 'collecting_config',
|
||||
});
|
||||
const generatedSession = buildMockMatch3DAgentSession({
|
||||
sessionId: 'match3d-notice-session-1',
|
||||
stage: 'draft_ready',
|
||||
draft: {
|
||||
profileId: 'match3d-notice-profile-1',
|
||||
gameName: '红点自动试玩抓大鹅',
|
||||
themeText: '水果',
|
||||
summary: '',
|
||||
tags: ['水果', '抓大鹅'],
|
||||
coverImageSrc: null,
|
||||
referenceImageSrc: null,
|
||||
clearCount: 12,
|
||||
difficulty: 4,
|
||||
generatedItemAssets,
|
||||
},
|
||||
});
|
||||
const generatedProfile: Match3DWorkSummary = {
|
||||
workId: 'match3d-notice-work-1',
|
||||
profileId: 'match3d-notice-profile-1',
|
||||
ownerUserId: 'user-1',
|
||||
sourceSessionId: 'match3d-notice-session-1',
|
||||
gameName: '红点自动试玩抓大鹅',
|
||||
themeText: '水果',
|
||||
summary: '',
|
||||
tags: ['水果', '抓大鹅'],
|
||||
coverImageSrc: null,
|
||||
referenceImageSrc: null,
|
||||
clearCount: 12,
|
||||
difficulty: 4,
|
||||
publicationStatus: 'draft',
|
||||
playCount: 0,
|
||||
updatedAt: '2026-05-14T10:00:00.000Z',
|
||||
publishedAt: null,
|
||||
publishReady: false,
|
||||
generatedItemAssets,
|
||||
};
|
||||
vi.mocked(match3dCreationClient.createSession).mockResolvedValue({
|
||||
session: runningSession,
|
||||
});
|
||||
let resolveCompile!: (value: {
|
||||
session: Match3DAgentSessionSnapshot;
|
||||
}) => void;
|
||||
vi.mocked(match3dCreationClient.executeAction).mockReturnValue(
|
||||
new Promise((resolve) => {
|
||||
resolveCompile = resolve;
|
||||
}),
|
||||
);
|
||||
vi.mocked(match3dCreationClient.getSession).mockResolvedValue({
|
||||
session: generatedSession,
|
||||
});
|
||||
vi.mocked(getMatch3DWorkDetail).mockResolvedValue({
|
||||
item: generatedProfile,
|
||||
});
|
||||
vi.mocked(listMatch3DWorks).mockResolvedValue({
|
||||
items: [generatedProfile],
|
||||
});
|
||||
match3dServerRuntimeAdapterMock.startRun.mockResolvedValue({
|
||||
run: buildMockMatch3DRun(generatedProfile.profileId),
|
||||
});
|
||||
|
||||
render(<TestWrapper withAuth />);
|
||||
|
||||
await openCreateTemplateHub(user);
|
||||
await user.click(screen.getByRole('tab', { name: '抓大鹅' }));
|
||||
await user.click(
|
||||
await screen.findByRole('button', { name: '生成抓大鹅草稿' }),
|
||||
);
|
||||
expect(await screen.findByText('抓大鹅草稿生成进度')).toBeTruthy();
|
||||
await user.click(screen.getByRole('button', { name: '返回创作中心' }));
|
||||
await openDraftHub(user);
|
||||
await expectDraftHubGeneratingBadgeCountAtLeast(1);
|
||||
|
||||
await act(async () => {
|
||||
resolveCompile({ session: generatedSession });
|
||||
});
|
||||
|
||||
expect(await screen.findByLabelText('新生成完成')).toBeTruthy();
|
||||
await user.click(
|
||||
await screen.findByRole('button', {
|
||||
name: /继续创作《红点自动试玩抓大鹅》/u,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(await screen.findByText(/抓大鹅运行态/u)).toBeTruthy();
|
||||
expect(screen.queryByText('抓大鹅草稿生成进度')).toBeNull();
|
||||
expect(match3dServerRuntimeAdapterMock.startRun).toHaveBeenCalledTimes(1);
|
||||
await user.click(screen.getByRole('button', { name: '返回' }));
|
||||
expect(await screen.findByText('抓大鹅结果页')).toBeTruthy();
|
||||
await user.click(screen.getByRole('button', { name: '返回' }));
|
||||
|
||||
await openDraftHub(user);
|
||||
expect(screen.queryByLabelText('新生成完成')).toBeNull();
|
||||
await user.click(
|
||||
await screen.findByRole('button', {
|
||||
name: /继续创作《红点自动试玩抓大鹅》/u,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(await screen.findByText('抓大鹅结果页')).toBeTruthy();
|
||||
expect(screen.queryByText(/抓大鹅运行态/u)).toBeNull();
|
||||
expect(match3dServerRuntimeAdapterMock.startRun).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('puzzle draft generation auto starts trial and runtime back opens draft result', async () => {
|
||||
const user = userEvent.setup();
|
||||
const generatedDraft: PuzzleResultDraft = {
|
||||
@@ -3364,6 +3817,22 @@ test('puzzle draft generation auto starts trial and runtime back opens draft res
|
||||
selectedCandidateId: 'candidate-1',
|
||||
coverImageSrc: '/puzzle/auto-candidate.png',
|
||||
coverAssetId: 'asset-1',
|
||||
uiBackgroundPrompt: '水果乐园竖屏纯背景',
|
||||
uiBackgroundImageSrc:
|
||||
'/generated-puzzle-assets/puzzle-session-auto-1/ui/background.png',
|
||||
uiBackgroundImageObjectKey:
|
||||
'generated-puzzle-assets/puzzle-session-auto-1/ui/background.png',
|
||||
backgroundMusic: {
|
||||
taskId: 'music-task-auto-1',
|
||||
provider: 'vector-engine-suno',
|
||||
assetObjectId: 'asset-music-auto-1',
|
||||
assetKind: 'puzzle_background_music',
|
||||
audioSrc:
|
||||
'/generated-puzzle-assets/puzzle-session-auto-1/audio/background.mp3',
|
||||
prompt: '',
|
||||
title: '水果乐园',
|
||||
updatedAt: '2026-05-14T10:00:00.000Z',
|
||||
},
|
||||
generationStatus: 'ready',
|
||||
},
|
||||
],
|
||||
@@ -3412,6 +3881,16 @@ test('puzzle draft generation auto starts trial and runtime back opens draft res
|
||||
expect.objectContaining({
|
||||
levelName: '雨夜猫街',
|
||||
coverImageSrc: '/puzzle/auto-candidate.png',
|
||||
levels: [
|
||||
expect.objectContaining({
|
||||
uiBackgroundImageSrc:
|
||||
'/generated-puzzle-assets/puzzle-session-auto-1/ui/background.png',
|
||||
backgroundMusic: expect.objectContaining({
|
||||
audioSrc:
|
||||
'/generated-puzzle-assets/puzzle-session-auto-1/audio/background.mp3',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
expect(screen.queryByText('拼图结果页')).toBeNull();
|
||||
@@ -4958,9 +5437,10 @@ test('puzzle draft result back button returns to creation hub', async () => {
|
||||
await user.click(screen.getByRole('button', { name: '返回' }));
|
||||
|
||||
expect(await screen.findByRole('tablist', { name: '选择模板' })).toBeTruthy();
|
||||
expect(await screen.findByText('拼图工作区:missing-session')).toBeTruthy();
|
||||
expect(
|
||||
screen.getByText('雨夜里有一只会发光的猫站在遗迹台阶上。'),
|
||||
).toBeTruthy();
|
||||
screen.queryByText('雨夜里有一只会发光的猫站在遗迹台阶上。'),
|
||||
).toBeNull();
|
||||
expect(screen.queryByText('拼图结果页')).toBeNull();
|
||||
});
|
||||
|
||||
@@ -5872,7 +6352,7 @@ test('running custom world draft generation can return to creation center with s
|
||||
await openDraftHub(user);
|
||||
|
||||
expect(await screen.findByText('潮雾列岛')).toBeTruthy();
|
||||
expect(screen.getAllByText('生成中').length).toBeGreaterThan(0);
|
||||
await expectDraftHubGeneratingBadgeCountAtLeast(1);
|
||||
});
|
||||
|
||||
test('refresh restores running draft generation progress instead of agent workspace', async () => {
|
||||
|
||||
Reference in New Issue
Block a user