Files
Genarrative/src/components/image-editor/ImageCanvasSoundEffectPresetModel.test.ts
T
lhk229 5c316fc680 统一SFX提示词 trim 规范化
将 SFX Prompt 首尾规范化改为 ECMAScript String.trim 语义并同步 Rust 等值实现

更新共享边界 fixture、前后端与 Worker 回归测试

同步权威设计、实施计划、决策日志和 External OpenAPI 描述
2026-08-07 07:27:52 +00:00

277 lines
9.2 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 {
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);
});
});