93 lines
4.4 KiB
TypeScript
93 lines
4.4 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
buildGameAssetReviewBatchMessage,
|
|
buildGameAssetReviewActionMessage,
|
|
buildGameAssetReviewMarker,
|
|
buildGameAssetConfirmationMessage,
|
|
findGameAssetRoundConfirmation,
|
|
GAME_ASSET_SELECTION_MARKER,
|
|
hasGameAssetReviewContent,
|
|
hasGameAssetSelectionMarker,
|
|
parseGameAssetReviewAction,
|
|
parseGameAssetReviewActions,
|
|
parseGameAssetReviewInvocation,
|
|
stripGameAssetSelectionMarker,
|
|
} from '@/lib/game-asset-selection-message';
|
|
|
|
describe('conversation-guided game asset selection', () => {
|
|
it('detects and hides the assistant selection marker', () => {
|
|
const message = { role: 'assistant' as const, content: `候选准备好了。\n${GAME_ASSET_SELECTION_MARKER}` };
|
|
expect(hasGameAssetSelectionMarker(message)).toBe(true);
|
|
expect(stripGameAssetSelectionMarker(String(message.content))).toBe('候选准备好了。');
|
|
});
|
|
|
|
it('round-trips an Agent-filled review marker and user action', () => {
|
|
const assistant = { role: 'assistant' as const, content: `候选准备好了。\n${buildGameAssetReviewMarker('review-1', ['hero', 'jump'])}` };
|
|
expect(hasGameAssetSelectionMarker(assistant)).toBe(true);
|
|
expect(parseGameAssetReviewInvocation(assistant)).toEqual({ invocationId: 'review-1', candidateIds: ['hero', 'jump'] });
|
|
expect(stripGameAssetSelectionMarker(String(assistant.content))).toBe('候选准备好了。');
|
|
|
|
const user = { role: 'user' as const, content: buildGameAssetReviewActionMessage({ invocationId: 'review-1', asset: { id: 'hero', name: '主角' }, action: 'approve' }) };
|
|
expect(parseGameAssetReviewAction(user)).toEqual({ invocationId: 'review-1', assetId: 'hero', action: 'approve' });
|
|
});
|
|
|
|
it('round-trips one grouped user message for the complete review batch', () => {
|
|
const message = {
|
|
role: 'user' as const,
|
|
content: buildGameAssetReviewBatchMessage({
|
|
invocationId: 'review-batch',
|
|
decisions: [
|
|
{ asset: { id: 'hero', name: '主角' }, action: 'approve' },
|
|
{ asset: { id: 'jump', name: '跳跃音效' }, action: 'discard' },
|
|
{ asset: { id: 'background', name: '背景' }, action: 'replace' },
|
|
],
|
|
}),
|
|
};
|
|
expect(message.content).toContain('游戏素材审核结果(本轮一次性提交)');
|
|
expect(message.content).toContain('纳入开发:');
|
|
expect(message.content).toContain('舍弃:');
|
|
expect(message.content).toContain('不合适,重新寻找:');
|
|
expect(parseGameAssetReviewActions(message)).toEqual({
|
|
invocationId: 'review-batch',
|
|
decisions: [
|
|
{ assetId: 'hero', action: 'approve' },
|
|
{ assetId: 'jump', action: 'discard' },
|
|
{ assetId: 'background', action: 'replace' },
|
|
],
|
|
});
|
|
});
|
|
|
|
it('detects a concrete preview list when the Agent omitted the review marker', () => {
|
|
const assistant = {
|
|
role: 'assistant' as const,
|
|
content: '已经找到 7 个素材候选。\n\n| 预览文件 | 是什么 |\n| --- | --- |\n| C-001-flappy-bird.png | 小鸟和管子 |',
|
|
};
|
|
expect(hasGameAssetReviewContent(assistant)).toBe(true);
|
|
expect(hasGameAssetReviewContent({ role: 'assistant', content: '我正在整理素材方向,暂时没有候选。' })).toBe(false);
|
|
});
|
|
|
|
it('builds a real user confirmation and associates it with the latest round', () => {
|
|
const confirmation = buildGameAssetConfirmationMessage([
|
|
{ id: 'hero', name: '主角' },
|
|
{ id: 'jump', name: '跳跃音效' },
|
|
]);
|
|
const messages = [
|
|
{ role: 'assistant' as const, content: GAME_ASSET_SELECTION_MARKER },
|
|
{ role: 'user' as const, content: confirmation },
|
|
];
|
|
expect(confirmation).toContain('「主角」(hero)、「跳跃音效」(jump)');
|
|
expect(findGameAssetRoundConfirmation(messages, 0)).toBe(messages[1]);
|
|
});
|
|
|
|
it('does not let a later round confirmation collapse an older unanswered round', () => {
|
|
const messages = [
|
|
{ role: 'assistant' as const, content: GAME_ASSET_SELECTION_MARKER },
|
|
{ role: 'user' as const, content: '换一批' },
|
|
{ role: 'assistant' as const, content: GAME_ASSET_SELECTION_MARKER },
|
|
{ role: 'user' as const, content: buildGameAssetConfirmationMessage([{ id: 'new', name: '新素材' }]) },
|
|
];
|
|
expect(findGameAssetRoundConfirmation(messages, 0)).toBeNull();
|
|
expect(findGameAssetRoundConfirmation(messages, 2)).toBe(messages[3]);
|
|
});
|
|
});
|