/** * 技能系统单元测试 * 测试纯函数,不依赖框架 */ describe('技能系统 - 纯函数测试', () => { describe('getNextLevelExp - 下一级经验计算', () => { test('应该正确计算下一级所需经验(默认公式)', () => { // 默认公式: (currentLevel + 1) * 100 const getNextLevelExp = (skillId, currentLevel) => { // 假设使用默认配置 return (currentLevel + 1) * 100 } expect(getNextLevelExp('sword', 0)).toBe(100) // 1级需要100 expect(getNextLevelExp('sword', 1)).toBe(200) // 2级需要200 expect(getNextLevelExp('sword', 5)).toBe(600) // 6级需要600 expect(getNextLevelExp('sword', 9)).toBe(1000) // 10级需要1000 }) test('应该正确处理自定义经验公式', () => { // 自定义公式: level * level * 50 const customExpPerLevel = (level) => level * level * 50 const getNextLevelExp = (skillId, currentLevel) => { return customExpPerLevel(currentLevel + 1) } expect(getNextLevelExp('magic', 0)).toBe(50) // 1级: 1*1*50 expect(getNextLevelExp('magic', 1)).toBe(200) // 2级: 2*2*50 expect(getNextLevelExp('magic', 4)).toBe(1250) // 5级: 5*5*50 }) test('边界值测试', () => { const getNextLevelExp = (skillId, currentLevel) => { return (currentLevel + 1) * 100 } expect(getNextLevelExp('test', 0)).toBe(100) expect(getNextLevelExp('test', 99)).toBe(10000) }) }) describe('技能升级逻辑', () => { test('应该正确添加经验并升级', () => { // 模拟升级逻辑 const addSkillExp = (skill, amount, expPerLevel) => { skill.exp += amount let leveledUp = false while (skill.exp >= expPerLevel(skill.level + 1)) { skill.exp -= expPerLevel(skill.level + 1) skill.level++ leveledUp = true } return { leveledUp, newLevel: skill.level } } const skill = { level: 1, exp: 0 } // 2级需要 200 经验 const expPerLevel = (level) => level * 100 // 添加200经验,正好升级到2级 let result = addSkillExp(skill, 200, expPerLevel) expect(result.leveledUp).toBe(true) expect(result.newLevel).toBe(2) expect(skill.exp).toBe(0) // 再添加300经验,升级到3级(需要300) result = addSkillExp(skill, 300, expPerLevel) expect(result.leveledUp).toBe(true) expect(result.newLevel).toBe(3) expect(skill.exp).toBe(0) }) test('应该正确处理连续升级', () => { const skill = { level: 1, exp: 0 } const expPerLevel = (level) => level * 100 // 添加500经验,应该从1级升到3级(200+300) const addSkillExp = (skill, amount, expPerLevel) => { skill.exp += amount let leveledUp = false while (skill.exp >= expPerLevel(skill.level + 1)) { skill.exp -= expPerLevel(skill.level + 1) skill.level++ leveledUp = true } return { leveledUp, newLevel: skill.level } } const result = addSkillExp(skill, 500, expPerLevel) expect(result.leveledUp).toBe(true) expect(result.newLevel).toBe(3) expect(skill.exp).toBe(0) }) test('经验不足时不应该升级', () => { const skill = { level: 1, exp: 0 } const expPerLevel = (level) => level * 100 const addSkillExp = (skill, amount, expPerLevel) => { skill.exp += amount let leveledUp = false while (skill.exp >= expPerLevel(skill.level + 1)) { skill.exp -= expPerLevel(skill.level + 1) skill.level++ leveledUp = true } return { leveledUp, newLevel: skill.level } } const result = addSkillExp(skill, 50, expPerLevel) expect(result.leveledUp).toBe(false) expect(result.newLevel).toBe(1) expect(skill.exp).toBe(50) }) test('部分成功时经验应该减半', () => { const EXP_PARTIAL_SUCCESS = 0.5 const calculatePartialExp = (amount) => { return Math.floor(amount * EXP_PARTIAL_SUCCESS) } expect(calculatePartialExp(100)).toBe(50) expect(calculatePartialExp(150)).toBe(75) expect(calculatePartialExp(99)).toBe(49) // 向下取整 }) }) describe('技能等级上限', () => { test('应该正确计算等级上限(玩家等级限制)', () => { // 技能上限 = 玩家等级 * 2 const playerLevel = 5 const maxSkillLevel = playerLevel * 2 expect(maxSkillLevel).toBe(10) const skillLevel = 10 const canLevelUp = skillLevel < maxSkillLevel expect(canLevelUp).toBe(false) }) test('应该正确计算等级上限(技能配置限制)', () => { const playerLevel = 10 const skillMaxLevel = 5 // 取最小值 const effectiveMaxLevel = Math.min(playerLevel * 2, skillMaxLevel) expect(effectiveMaxLevel).toBe(5) }) test('达到等级上限时不再升级', () => { const skill = { level: 5, exp: 0 } const maxLevel = 5 const addSkillExp = (skill, amount, maxLevel) => { if (skill.level >= maxLevel) { return { leveledUp: false, newLevel: skill.level, capped: true } } skill.exp += amount return { leveledUp: false, newLevel: skill.level, capped: false } } const result = addSkillExp(skill, 100, maxLevel) expect(result.leveledUp).toBe(false) expect(result.capped).toBe(true) expect(result.newLevel).toBe(5) }) }) describe('里程碑奖励', () => { test('应该正确检测里程碑等级', () => { const milestones = { 5: { effect: { damage: 5 } }, 10: { effect: { damage: 10 } } } const hasMilestone = (level) => { return !!milestones[level] } expect(hasMilestone(5)).toBe(true) expect(hasMilestone(10)).toBe(true) expect(hasMilestone(3)).toBe(false) }) test('应该正确应用里程碑奖励', () => { const skill = { level: 4 } const milestones = { 5: { effect: { strength: 2 } }, 10: { effect: { strength: 5 } } } const applyMilestone = (skill, milestones) => { if (milestones[skill.level]) { return milestones[skill.level].effect } return {} } // 5级时应用 skill.level = 5 const effect = applyMilestone(skill, milestones) expect(effect).toEqual({ strength: 2 }) // 10级时应用 skill.level = 10 const effect2 = applyMilestone(skill, milestones) expect(effect2).toEqual({ strength: 5 }) }) test('里程碑奖励应该只应用一次', () => { const appliedMilestones = new Set() const milestoneKey = 'sword_5' const canApplyMilestone = (key) => { return !appliedMilestones.has(key) } const applyMilestone = (key) => { if (canApplyMilestone(key)) { appliedMilestones.add(key) return true } return false } expect(applyMilestone(milestoneKey)).toBe(true) expect(applyMilestone(milestoneKey)).toBe(false) expect(appliedMilestones.has(milestoneKey)).toBe(true) }) }) describe('父技能系统', () => { test('父技能等级应该等于所有子技能的最高等级', () => { const childSkills = { sword: { level: 5 }, axe: { level: 3 }, spear: { level: 7 } } const calculateParentLevel = (childSkills) => { return Math.max(...Object.values(childSkills).map(s => s.level)) } expect(calculateParentLevel(childSkills)).toBe(7) }) test('子技能升级时应该更新父技能', () => { const skills = { sword: { level: 5 }, axe: { level: 3 }, combat: { level: 5 } // 父技能 } const updateParentSkill = (skillId) => { const childLevels = [skills.sword.level, skills.axe.level] skills.combat.level = Math.max(...childLevels) } // sword 升到 7 skills.sword.level = 7 updateParentSkill('sword') expect(skills.combat.level).toBe(7) }) test('父技能应该自动初始化', () => { const skills = { sword: { level: 3, unlocked: true }, axe: { level: 0, unlocked: false } } const initParentSkill = () => { if (!skills.combat) { skills.combat = { level: 0, unlocked: true } } } initParentSkill() expect(skills.combat).toBeDefined() expect(skills.combat.unlocked).toBe(true) }) }) describe('经验倍率计算', () => { test('应该正确计算基础经验倍率', () => { const globalBonus = 0.2 // 20%全局加成 const milestoneBonus = 0.1 // 10%里程碑加成 const totalBonus = globalBonus + milestoneBonus expect(totalBonus).toBeCloseTo(0.3, 1) }) test('父技能高于子技能时应该有1.5倍加成', () => { const parentLevel = 10 const childLevel = 5 const hasParentBonus = parentLevel > childLevel const expMultiplier = hasParentBonus ? 1.5 : 1.0 expect(expMultiplier).toBe(1.5) }) test('应该正确应用多个加成', () => { const baseExp = 100 const globalBonus = 1.2 // +20% const parentBonus = 1.5 // +50% const milestoneBonus = 1.1 // +10% const finalExp = baseExp * globalBonus * parentBonus * milestoneBonus expect(finalExp).toBeCloseTo(198, 0) // 100 * 1.2 * 1.5 * 1.1 = 198 }) }) describe('技能解锁条件', () => { test('应该正确检查物品条件', () => { const playerInventory = ['stick', 'sword'] const requiredItem = 'stick' const hasRequiredItem = (inventory, item) => { return inventory.includes(item) } expect(hasRequiredItem(playerInventory, requiredItem)).toBe(true) expect(hasRequiredItem(playerInventory, 'axe')).toBe(false) }) test('应该正确检查位置条件', () => { const playerLocation = 'camp' const requiredLocation = 'camp' const isInLocation = (current, required) => { return current === required } expect(isInLocation(playerLocation, requiredLocation)).toBe(true) expect(isInLocation(playerLocation, 'wild1')).toBe(false) }) test('应该正确检查前置技能等级', () => { const skills = { basic: { level: 5, unlocked: true }, advanced: { level: 0, unlocked: false } } const checkPrerequisite = (skillId, requiredLevel) => { const skill = skills[skillId] return skill && skill.level >= requiredLevel } expect(checkPrerequisite('basic', 5)).toBe(true) expect(checkPrerequisite('basic', 6)).toBe(false) }) }) describe('边界条件', () => { test('经验不能为负数', () => { const skill = { level: 1, exp: 50 } const addExpSafe = (skill, amount) => { skill.exp = Math.max(0, skill.exp + amount) return skill.exp } expect(addExpSafe(skill, -30)).toBe(20) expect(addExpSafe(skill, -100)).toBe(0) }) test('等级不能为负数', () => { const skill = { level: 1, exp: 0 } const levelUpSafe = (skill) => { skill.level = Math.max(0, skill.level + 1) return skill.level } expect(levelUpSafe(skill)).toBe(2) }) test('空技能对象应该有默认值', () => { const createSkill = () => ({ level: 0, exp: 0, unlocked: false }) const skill = createSkill() expect(skill.level).toBe(0) expect(skill.exp).toBe(0) expect(skill.unlocked).toBe(false) }) }) })