import { describe, expect, it } from 'vitest'; import { appendSoundEffectPromptPreset, SOUND_EFFECT_PROMPT_PRESET_GROUPS, SOUND_EFFECT_PROMPT_PRESETS, } from './ImageCanvasSoundEffectPresetModel'; describe('ImageCanvasSoundEffectPresetModel', () => { it('freezes 40 event presets and 12 requirements with unique identities', () => { expect(SOUND_EFFECT_PROMPT_PRESETS).toHaveLength(52); expect( SOUND_EFFECT_PROMPT_PRESETS.filter( (preset) => preset.category === 'event', ), ).toHaveLength(40); expect( SOUND_EFFECT_PROMPT_PRESETS.filter( (preset) => preset.category === 'requirement', ), ).toHaveLength(12); expect(new Set(SOUND_EFFECT_PROMPT_PRESETS.map(({ id }) => id)).size).toBe( 52, ); expect(SOUND_EFFECT_PROMPT_PRESETS.map(({ id }) => id)).toEqual([ 'button-tap', 'operation-confirm', 'back-cancel', 'page-transition', 'notification', 'operation-error', 'coin-pickup', 'item-pickup', 'reward-received', 'chest-open', 'content-unlock', 'rare-drop', 'item-craft', 'character-level-up', 'quest-complete', 'achievement-unlocked', 'challenge-victory', 'challenge-defeat', 'character-jump', 'character-land', 'light-hit', 'heavy-hit', 'attack-swing', 'attack-hit', 'block-success', 'object-break', 'skill-charge', 'magic-cast', 'healing', 'shield-create', 'teleport', 'ice-skill', 'fire-skill', 'status-buff', 'door-open', 'mechanism-start', 'lever-trigger', 'stone-move', 'portal-open', 'countdown-warning', 'casual-cute', 'retro-arcade', 'sci-fi-electronic', 'fantasy-magic', 'realistic-natural', 'cartoon-exaggerated', 'gentle-feedback', 'strong-feedback', 'short-feedback', 'two-stage-rise', 'clean-prominent', 'soft-not-harsh', ]); expect( new Set(SOUND_EFFECT_PROMPT_PRESETS.map(({ label }) => label)).size, ).toBe(52); expect( new Set(SOUND_EFFECT_PROMPT_PRESETS.map(({ group }) => group)), ).toEqual(new Set(SOUND_EFFECT_PROMPT_PRESET_GROUPS)); }); it('locks the visible labels and prompt text in authoritative order', () => { expect( SOUND_EFFECT_PROMPT_PRESETS.map(({ category, group, label, prompt }) => [ category, group, label, prompt, ]), ).toEqual([ ['event', 'ui-operation', '轻触按钮', '柔和的按钮点击声'], ['event', 'ui-operation', '确认操作', '明亮的确认提示音'], ['event', 'ui-operation', '返回取消', '轻微下降的取消提示音'], ['event', 'ui-operation', '页面切换', '快速掠过的界面切换声'], ['event', 'ui-operation', '通知提醒', '清晰柔和的通知提示音'], ['event', 'ui-operation', '操作错误', '短促克制的错误提示音'], ['event', 'pickup-reward', '金币拾取', '金币拾取时清脆的金属叮当声'], ['event', 'pickup-reward', '道具拾取', '拾取道具时轻快的提示音'], ['event', 'pickup-reward', '获得奖励', '奖励出现时明亮的提示音'], [ 'event', 'pickup-reward', '宝箱开启', '金属锁扣弹开,随后响起明亮的奖励提示音', ], [ 'event', 'pickup-reward', '解锁内容', '锁定状态解除,随后响起解锁提示音', ], ['event', 'pickup-reward', '稀有掉落', '稀有物品出现时闪耀的奖励提示音'], [ 'event', 'growth-result', '物品合成', '两件物品融合,随后响起明亮的完成提示音', ], [ 'event', 'growth-result', '角色升级', '能量快速上升,随后响起明亮的升级提示音', ], [ 'event', 'growth-result', '任务完成', '任务完成提示音,随后响起简短的奖励音符', ], [ 'event', 'growth-result', '成就达成', '明亮的成就提示音,随后响起简短的庆祝音符', ], [ 'event', 'growth-result', '挑战胜利', '明亮的胜利提示音,随后响起短暂的庆祝音符', ], ['event', 'growth-result', '挑战失败', '低沉的失败提示音'], ['event', 'character-combat', '角色跳跃', '角色轻盈跳起的声音'], ['event', 'character-combat', '角色落地', '角色落地时轻微的撞击声'], ['event', 'character-combat', '轻度受击', '轻微撞击的受击声'], ['event', 'character-combat', '重度受击', '沉重有力的撞击声'], ['event', 'character-combat', '攻击挥动', '武器快速挥过空气的呼啸声'], ['event', 'character-combat', '攻击命中', '武器击中目标的清晰撞击声'], ['event', 'character-combat', '格挡成功', '武器碰撞,随后被挡开的金属声'], ['event', 'character-combat', '物体破碎', '物体撞击地面后快速破碎的声音'], ['event', 'skill-status', '技能蓄力', '能量逐渐聚集的低沉嗡鸣声'], [ 'event', 'skill-status', '魔法释放', '柔和的魔法能量扩散,带有圆润空灵的闪光声', ], [ 'event', 'skill-status', '治疗恢复', '柔和能量扩散,带有温暖圆润的提示音', ], ['event', 'skill-status', '护盾生成', '能量向外展开,形成稳定的护盾声'], [ 'event', 'skill-status', '瞬间移动', '能量快速收缩,随后以短促的空气抽离声消失', ], [ 'event', 'skill-status', '冰冻技能', '冰霜能量扩散,随后响起清脆的冻结声', ], ['event', 'skill-status', '火焰技能', '火焰迅速喷发,带有短促的燃烧声'], [ 'event', 'skill-status', '状态强化', '能量逐渐上升,形成稳定明亮的提示音', ], [ 'event', 'mechanism-scene-interaction', '门开启', '门锁解除,随后厚重的木门缓慢打开', ], [ 'event', 'mechanism-scene-interaction', '机关启动', '机关解锁,随后齿轮开始转动', ], [ 'event', 'mechanism-scene-interaction', '拉杆触发', '拉杆被扳动,随后远处机关启动', ], [ 'event', 'mechanism-scene-interaction', '石块移动', '大型石块缓慢移动时低沉的摩擦声', ], [ 'event', 'mechanism-scene-interaction', '传送门开启', '能量旋转聚集,随后响起持续、空灵的传送门展开声', ], [ 'event', 'mechanism-scene-interaction', '倒计时警告', '逐渐加快的倒计时提示音', ], ['requirement', 'style-direction', '休闲可爱', '轻快可爱的卡通风格'], ['requirement', 'style-direction', '复古街机', '复古街机风格'], ['requirement', 'style-direction', '科幻电子', '干净的科幻电子音色'], ['requirement', 'style-direction', '奇幻魔法', '柔和梦幻的魔法音色'], ['requirement', 'style-direction', '写实自然', '自然真实的声音质感'], ['requirement', 'style-direction', '卡通夸张', '夸张鲜明的卡通风格'], ['requirement', 'feedback-requirement', '轻柔反馈', '轻柔克制'], ['requirement', 'feedback-requirement', '有力反馈', '更有力的撞击感'], ['requirement', 'feedback-requirement', '短促反馈', '短促的单次声音'], ['requirement', 'feedback-requirement', '两段递进', '由弱到强的两段变化'], [ 'requirement', 'feedback-requirement', '干净突出', '主体声音清晰,减少杂音', ], [ 'requirement', 'feedback-requirement', '柔和不刺耳', '圆润柔和,避免尖锐高频', ], ]); }); it('canonicalizes and appends with the frozen ECMAScript trim rule', () => { const preset = SOUND_EFFECT_PROMPT_PRESETS[40]; expect(appendSoundEffectPromptPreset('\uFEFF\u2003', preset)).toBe( preset.prompt, ); expect(appendSoundEffectPromptPreset('金币落地', preset)).toBe( `金币落地,${preset.prompt}`, ); expect(appendSoundEffectPromptPreset('金币落地!\uFEFF', preset)).toBe( `金币落地!${preset.prompt}`, ); }); it('allows duplicates and preserves overlong text without truncation', () => { const preset = SOUND_EFFECT_PROMPT_PRESETS[0]; const once = appendSoundEffectPromptPreset('按钮', preset); expect(appendSoundEffectPromptPreset(once, preset)).toBe( `按钮,${preset.prompt},${preset.prompt}`, ); const overlong = '声'.repeat(2048); const appended = appendSoundEffectPromptPreset(overlong, preset); expect(appended).toBe(`${overlong},${preset.prompt}`); expect(Array.from(appended).length).toBeGreaterThan(2048); }); });