135 lines
4.9 KiB
TypeScript
Executable File
135 lines
4.9 KiB
TypeScript
Executable File
import { describe, it, expect } from 'vitest';
|
|
import { calculateEffectCapacityCost, ENCHANTMENT_EFFECTS } from '../data/enchantment-effects';
|
|
import { EQUIPMENT_TYPES } from '../data/equipment';
|
|
import { ATTUNEMENTS_DEF, getAttunementConversionRate } from '../data/attunements';
|
|
|
|
describe('Enchantment Capacity Validation', () => {
|
|
it('should calculate capacity cost for single stack effects', () => {
|
|
// Mana Bolt spell effect has base capacity cost of 50
|
|
const cost = calculateEffectCapacityCost('spell_manaBolt', 1, 0);
|
|
expect(cost).toBe(50);
|
|
});
|
|
|
|
it('should apply scaling for multiple stacks', () => {
|
|
// damage_5 has base cost 15, each additional stack costs 20% more
|
|
const cost1 = calculateEffectCapacityCost('damage_5', 1, 0);
|
|
const cost2 = calculateEffectCapacityCost('damage_5', 2, 0);
|
|
|
|
// First stack: 15
|
|
// Second stack: 15 * 1.2 = 18
|
|
// Total: 33
|
|
expect(cost1).toBe(15);
|
|
expect(cost2).toBe(Math.floor(15 + 15 * 1.2));
|
|
});
|
|
|
|
it('should apply efficiency bonus to reduce cost', () => {
|
|
const costWithoutEfficiency = calculateEffectCapacityCost('spell_manaBolt', 1, 0);
|
|
const costWithEfficiency = calculateEffectCapacityCost('spell_manaBolt', 1, 0.1); // 10% reduction
|
|
|
|
expect(costWithEfficiency).toBe(Math.floor(costWithoutEfficiency * 0.9));
|
|
});
|
|
|
|
it('should respect equipment base capacity', () => {
|
|
// Civilian Shirt has base capacity 30
|
|
const shirt = EQUIPMENT_TYPES['civilianShirt'];
|
|
expect(shirt.baseCapacity).toBe(30);
|
|
|
|
// Basic Staff has base capacity 50
|
|
const staff = EQUIPMENT_TYPES['basicStaff'];
|
|
expect(staff.baseCapacity).toBe(50);
|
|
});
|
|
|
|
it('should reject enchantment designs exceeding equipment capacity', () => {
|
|
// Mana Bolt spell effect costs 50 capacity
|
|
// Civilian Shirt only has 30 capacity
|
|
const manaBoltCost = calculateEffectCapacityCost('spell_manaBolt', 1, 0);
|
|
const shirtCapacity = EQUIPMENT_TYPES['civilianShirt'].baseCapacity;
|
|
|
|
expect(manaBoltCost).toBeGreaterThan(shirtCapacity);
|
|
});
|
|
});
|
|
|
|
describe('Attunement Mana Type Unlocking', () => {
|
|
it('should define primary mana types for attunements', () => {
|
|
// Enchanter should have transference as primary mana
|
|
const enchanter = ATTUNEMENTS_DEF['enchanter'];
|
|
expect(enchanter.primaryManaType).toBe('transference');
|
|
|
|
// Fabricator should have earth as primary mana
|
|
const fabricator = ATTUNEMENTS_DEF['fabricator'];
|
|
expect(fabricator.primaryManaType).toBe('earth');
|
|
});
|
|
|
|
it('should have conversion rates for attunements with primary mana', () => {
|
|
// Enchanter should have a conversion rate
|
|
const enchanter = ATTUNEMENTS_DEF['enchanter'];
|
|
expect(enchanter.conversionRate).toBeGreaterThan(0);
|
|
|
|
// Get scaled conversion rate at level 1
|
|
const level1Rate = getAttunementConversionRate('enchanter', 1);
|
|
expect(level1Rate).toBe(enchanter.conversionRate);
|
|
|
|
// Higher level should have higher rate
|
|
const level5Rate = getAttunementConversionRate('enchanter', 5);
|
|
expect(level5Rate).toBeGreaterThan(level1Rate);
|
|
});
|
|
|
|
it('should have raw mana regen for all attunements', () => {
|
|
Object.values(ATTUNEMENTS_DEF).forEach(attunement => {
|
|
expect(attunement.rawManaRegen).toBeGreaterThanOrEqual(0);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Floor HP State', () => {
|
|
it('should have getFloorMaxHP function that returns positive values', async () => {
|
|
const { getFloorMaxHP } = await import('../computed-stats');
|
|
|
|
for (let floor = 1; floor <= 100; floor++) {
|
|
const hp = getFloorMaxHP(floor);
|
|
expect(hp).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it('should scale HP correctly with floor progression', async () => {
|
|
const { getFloorMaxHP } = await import('../computed-stats');
|
|
|
|
const hp1 = getFloorMaxHP(1);
|
|
const hp10 = getFloorMaxHP(10);
|
|
const hp50 = getFloorMaxHP(50);
|
|
const hp100 = getFloorMaxHP(100);
|
|
|
|
expect(hp10).toBeGreaterThan(hp1);
|
|
expect(hp50).toBeGreaterThan(hp10);
|
|
expect(hp100).toBeGreaterThan(hp50);
|
|
});
|
|
});
|
|
|
|
describe('Element State', () => {
|
|
it('should have utility elements defined', async () => {
|
|
const { ELEMENTS } = await import('../constants');
|
|
|
|
// Check that utility element exists (transference is the only utility element now)
|
|
expect(ELEMENTS['transference']).toBeDefined();
|
|
|
|
// Check categories
|
|
expect(ELEMENTS['transference'].cat).toBe('utility');
|
|
});
|
|
|
|
it('should have composite elements with recipes', async () => {
|
|
const { ELEMENTS } = await import('../constants');
|
|
|
|
// Metal is fire + earth
|
|
expect(ELEMENTS['metal'].cat).toBe('composite');
|
|
expect(ELEMENTS['metal'].recipe).toEqual(['fire', 'earth']);
|
|
|
|
// Sand is earth + water
|
|
expect(ELEMENTS['sand'].cat).toBe('composite');
|
|
expect(ELEMENTS['sand'].recipe).toEqual(['earth', 'water']);
|
|
|
|
// Lightning is fire + air
|
|
expect(ELEMENTS['lightning'].cat).toBe('composite');
|
|
expect(ELEMENTS['lightning'].recipe).toEqual(['fire', 'air']);
|
|
});
|
|
});
|