Files
makelore/tests/unit/game-asset-selection-message.test.ts
2026-07-29 17:22:35 +08:00

93 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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]);
});
});