142 lines
3.8 KiB
TypeScript
142 lines
3.8 KiB
TypeScript
import { expect, test, vi } from 'vitest';
|
|
|
|
import {
|
|
readCreativeAgentResultFromSse,
|
|
readCreativeAgentSessionFromSse,
|
|
} from './creativeAgentSse';
|
|
|
|
function createChunkedStreamResponse(chunks: Uint8Array[]) {
|
|
const stream = new ReadableStream<Uint8Array>({
|
|
start(controller) {
|
|
for (const chunk of chunks) {
|
|
controller.enqueue(chunk);
|
|
}
|
|
controller.close();
|
|
},
|
|
});
|
|
|
|
return new Response(stream, {
|
|
headers: {
|
|
'Content-Type': 'text/event-stream; charset=utf-8',
|
|
},
|
|
});
|
|
}
|
|
|
|
test('readCreativeAgentSessionFromSse parses typed creative agent events', async () => {
|
|
const encoder = new TextEncoder();
|
|
const onEvent = vi.fn();
|
|
const session = {
|
|
sessionId: 'creative-session-1',
|
|
stage: 'waiting_template_confirmation',
|
|
inputSummary: {
|
|
text: '做一套生日拼图',
|
|
entryContext: 'creation_home',
|
|
images: [],
|
|
materialSummary: null,
|
|
unsupportedCapabilities: [],
|
|
},
|
|
messages: [],
|
|
puzzleTemplateCatalog: [],
|
|
puzzleTemplateSelection: null,
|
|
puzzleImageGenerationPlan: null,
|
|
targetBinding: null,
|
|
updatedAt: '2026-05-05T10:00:00.000Z',
|
|
};
|
|
const response = createChunkedStreamResponse([
|
|
encoder.encode(
|
|
'event: stage\r\ndata: {"sessionId":"creative-session-1","stage":"perceiving"}\r\n\r\n',
|
|
),
|
|
encoder.encode(
|
|
'event: thought_summary_delta\r\ndata: {"sessionId":"creative-session-1","thoughtId":"thought-1","textDelta":"正在理解素材"}\r\n\r\n',
|
|
),
|
|
encoder.encode(
|
|
'event: puzzle_template_catalog\r\ndata: {"sessionId":"creative-session-1","templates":[]}\r\n\r\n',
|
|
),
|
|
encoder.encode(
|
|
`event: session\r\ndata: ${JSON.stringify({ session })}\r\n\r\n`,
|
|
),
|
|
]);
|
|
|
|
await expect(
|
|
readCreativeAgentSessionFromSse(response, {
|
|
fallbackMessage: '发送失败',
|
|
incompleteMessage: '结果不完整',
|
|
onEvent,
|
|
}),
|
|
).resolves.toEqual(session);
|
|
expect(onEvent).toHaveBeenCalledWith({
|
|
event: 'stage',
|
|
data: {
|
|
sessionId: 'creative-session-1',
|
|
stage: 'perceiving',
|
|
},
|
|
});
|
|
expect(onEvent).toHaveBeenCalledWith({
|
|
event: 'thought_summary_delta',
|
|
data: {
|
|
sessionId: 'creative-session-1',
|
|
thoughtId: 'thought-1',
|
|
textDelta: '正在理解素材',
|
|
},
|
|
});
|
|
expect(onEvent).toHaveBeenCalledWith({
|
|
event: 'puzzle_template_catalog',
|
|
data: {
|
|
sessionId: 'creative-session-1',
|
|
templates: [],
|
|
},
|
|
});
|
|
});
|
|
|
|
test('readCreativeAgentResultFromSse keeps draft edit payload when present', async () => {
|
|
const encoder = new TextEncoder();
|
|
const session = {
|
|
sessionId: 'creative-session-1',
|
|
stage: 'target_ready',
|
|
inputSummary: {
|
|
text: null,
|
|
entryContext: 'creation_home',
|
|
images: [],
|
|
materialSummary: null,
|
|
unsupportedCapabilities: [],
|
|
},
|
|
messages: [],
|
|
puzzleTemplateCatalog: [],
|
|
puzzleTemplateSelection: null,
|
|
puzzleImageGenerationPlan: null,
|
|
targetBinding: null,
|
|
updatedAt: '2026-05-05T10:00:00.000Z',
|
|
};
|
|
const puzzleSession = {
|
|
sessionId: 'puzzle-session-1',
|
|
currentTurn: 1,
|
|
progressPercent: 100,
|
|
stage: 'ready_to_publish',
|
|
anchorPack: {},
|
|
draft: null,
|
|
messages: [],
|
|
lastAssistantReply: null,
|
|
publishedProfileId: null,
|
|
suggestedActions: [],
|
|
resultPreview: null,
|
|
updatedAt: '2026-05-05T10:00:00.000Z',
|
|
};
|
|
const response = createChunkedStreamResponse([
|
|
encoder.encode(
|
|
`event: draft_edit_result\ndata: ${JSON.stringify({
|
|
editInstructions: [],
|
|
session,
|
|
puzzleSession,
|
|
})}\n\n`,
|
|
),
|
|
]);
|
|
|
|
const result = await readCreativeAgentResultFromSse(response, {
|
|
fallbackMessage: '修改失败',
|
|
incompleteMessage: '结果不完整',
|
|
});
|
|
|
|
expect(result.session).toEqual(session);
|
|
expect(result.draftEditResult?.puzzleSession).toEqual(puzzleSession);
|
|
});
|