246 lines
8.9 KiB
TypeScript
246 lines
8.9 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import {
|
|
heroItemFighter1Data,
|
|
encounterDesertData,
|
|
enemyDesertData,
|
|
enemyIntentDesertData,
|
|
effectDesertData,
|
|
} from '@/samples/slay-the-spire-like/data';
|
|
|
|
describe('heroItemFighter1.csv import', () => {
|
|
it('should import data as an array', () => {
|
|
expect(Array.isArray(heroItemFighter1Data)).toBe(true);
|
|
expect(heroItemFighter1Data.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should have expected number of items', () => {
|
|
expect(heroItemFighter1Data.length).toBe(24);
|
|
});
|
|
|
|
it('should have correct fields for each item', () => {
|
|
for (const item of heroItemFighter1Data) {
|
|
expect(item).toHaveProperty('type');
|
|
expect(item).toHaveProperty('name');
|
|
expect(item).toHaveProperty('shape');
|
|
expect(item).toHaveProperty('costType');
|
|
expect(item).toHaveProperty('costCount');
|
|
expect(item).toHaveProperty('targetType');
|
|
expect(item).toHaveProperty('desc');
|
|
}
|
|
});
|
|
|
|
it('should parse costCount as number', () => {
|
|
for (const item of heroItemFighter1Data) {
|
|
expect(typeof item.costCount).toBe('number');
|
|
}
|
|
});
|
|
|
|
it('should contain expected items by name', () => {
|
|
const names = heroItemFighter1Data.map(item => item.name);
|
|
expect(names).toContain('剑');
|
|
expect(names).toContain('盾');
|
|
expect(names).toContain('绷带');
|
|
expect(names).toContain('火把');
|
|
});
|
|
|
|
it('should have valid type values', () => {
|
|
const validTypes = ['weapon', 'armor', 'consumable', 'tool'];
|
|
for (const item of heroItemFighter1Data) {
|
|
expect(validTypes).toContain(item.type);
|
|
}
|
|
});
|
|
|
|
it('should have valid costType values', () => {
|
|
const validCostTypes = ['energy', 'uses'];
|
|
for (const item of heroItemFighter1Data) {
|
|
expect(validCostTypes).toContain(item.costType);
|
|
}
|
|
});
|
|
|
|
it('should have valid targetType values', () => {
|
|
const validTargetTypes = ['single', 'none'];
|
|
for (const item of heroItemFighter1Data) {
|
|
expect(validTargetTypes).toContain(item.targetType);
|
|
}
|
|
});
|
|
|
|
it('should have correct item counts by type', () => {
|
|
const typeCounts = heroItemFighter1Data.reduce((acc, item) => {
|
|
acc[item.type] = (acc[item.type] || 0) + 1;
|
|
return acc;
|
|
}, {} as Record<string, number>);
|
|
|
|
expect(typeCounts['weapon']).toBe(6);
|
|
expect(typeCounts['armor']).toBe(6);
|
|
expect(typeCounts['consumable']).toBe(6);
|
|
expect(typeCounts['tool']).toBe(6);
|
|
});
|
|
});
|
|
|
|
describe('encounterDesert.csv import', () => {
|
|
it('should import data as an array', () => {
|
|
expect(Array.isArray(encounterDesertData)).toBe(true);
|
|
expect(encounterDesertData.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should have correct encounter type counts', () => {
|
|
const typeCounts = encounterDesertData.reduce((acc, e) => {
|
|
acc[e.type] = (acc[e.type] || 0) + 1;
|
|
return acc;
|
|
}, {} as Record<string, number>);
|
|
|
|
expect(typeCounts['minion']).toBe(10);
|
|
expect(typeCounts['elite']).toBe(4);
|
|
expect(typeCounts['shop']).toBe(2);
|
|
expect(typeCounts['camp']).toBe(2);
|
|
expect(typeCounts['curio']).toBe(8);
|
|
expect(typeCounts['event']).toBe(1);
|
|
});
|
|
|
|
it('should have enemies for combat encounters', () => {
|
|
for (const e of encounterDesertData) {
|
|
if (e.type === 'minion' || e.type === 'elite') {
|
|
expect(Array.isArray(e.enemies)).toBe(true);
|
|
expect(e.enemies.length).toBeGreaterThan(0);
|
|
for (const [enemy, bonusHp] of e.enemies) {
|
|
expect(typeof enemy === 'string' || typeof enemy === 'object').toBe(true);
|
|
expect(typeof bonusHp).toBe('number');
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it('should have empty enemies for non-combat encounters', () => {
|
|
for (const e of encounterDesertData) {
|
|
if (e.type === 'shop' || e.type === 'camp') {
|
|
expect(e.enemies.length).toBe(0);
|
|
}
|
|
}
|
|
});
|
|
|
|
it('should have dialogue for curio and event encounters', () => {
|
|
for (const e of encounterDesertData) {
|
|
if (e.type === 'curio' || e.type === 'event') {
|
|
expect(e.dialogue).toBeTruthy();
|
|
expect(e.dialogue.startsWith('desert_')).toBe(true);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('effectDesert.csv import', () => {
|
|
it('should import data as an array', () => {
|
|
expect(Array.isArray(effectDesertData)).toBe(true);
|
|
expect(effectDesertData.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should have expected number of effects', () => {
|
|
expect(effectDesertData.length).toBe(19);
|
|
});
|
|
|
|
it('should have correct fields for each effect', () => {
|
|
for (const effect of effectDesertData) {
|
|
expect(effect).toHaveProperty('id');
|
|
expect(effect).toHaveProperty('name');
|
|
expect(effect).toHaveProperty('description');
|
|
expect(effect).toHaveProperty('timing');
|
|
}
|
|
});
|
|
|
|
it('should have valid timing values', () => {
|
|
const validTimings = ['instant', 'temporary', 'lingering', 'permanent', 'posture', 'card', 'cardDraw', 'cardHand'];
|
|
for (const effect of effectDesertData) {
|
|
expect(validTimings).toContain(effect.timing);
|
|
}
|
|
});
|
|
|
|
it('should contain core effect types', () => {
|
|
const ids = effectDesertData.map(e => e.id);
|
|
expect(ids).toContain('attack');
|
|
expect(ids).toContain('defend');
|
|
expect(ids).toContain('spike');
|
|
expect(ids).toContain('venom');
|
|
});
|
|
});
|
|
|
|
describe('enemyDesert.csv import', () => {
|
|
it('should import data as an array', () => {
|
|
expect(Array.isArray(enemyDesertData)).toBe(true);
|
|
expect(enemyDesertData.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should have expected number of enemies', () => {
|
|
expect(enemyDesertData.length).toBe(14);
|
|
});
|
|
|
|
it('should have correct fields for each enemy', () => {
|
|
for (const enemy of enemyDesertData) {
|
|
expect(enemy).toHaveProperty('id');
|
|
expect(enemy).toHaveProperty('initHp');
|
|
expect(enemy).toHaveProperty('initBuffs');
|
|
expect(enemy).toHaveProperty('initialIntent');
|
|
expect(typeof enemy.initHp).toBe('number');
|
|
expect(typeof enemy.initialIntent).toBe('string');
|
|
}
|
|
});
|
|
|
|
it('should have valid HP ranges', () => {
|
|
for (const enemy of enemyDesertData) {
|
|
expect(enemy.initHp).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it('should have minions with lower HP than elites', () => {
|
|
const minionIds = ['仙人掌怪', '蛇', '木乃伊', '枪手', '风卷草', '秃鹫', '沙蝎', '幼沙虫', '蜥蜴', '沙匪'];
|
|
const eliteIds = ['风暴之灵', '骑马枪手', '沙虫王', '沙漠守卫'];
|
|
const byId = Object.fromEntries(enemyDesertData.map(e => [e.id, e]));
|
|
|
|
for (const id of minionIds) {
|
|
expect(byId[id].initHp).toBeLessThan(40);
|
|
}
|
|
for (const id of eliteIds) {
|
|
expect(byId[id].initHp).toBeGreaterThanOrEqual(40);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('enemyIntentDesert.csv import', () => {
|
|
it('should import data as an array', () => {
|
|
expect(Array.isArray(enemyIntentDesertData)).toBe(true);
|
|
expect(enemyIntentDesertData.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should have expected number of intent rows', () => {
|
|
expect(enemyIntentDesertData.length).toBe(41);
|
|
});
|
|
|
|
it('should have correct fields for each intent', () => {
|
|
for (const intent of enemyIntentDesertData) {
|
|
expect(intent).toHaveProperty('enemy');
|
|
expect(intent).toHaveProperty('id');
|
|
expect(intent).toHaveProperty('nextIntents');
|
|
expect(intent).toHaveProperty('brokenIntent');
|
|
expect(intent).toHaveProperty('effects');
|
|
expect(intent.enemy).toHaveProperty('id');
|
|
expect(Array.isArray(intent.nextIntents)).toBe(true);
|
|
expect(Array.isArray(intent.brokenIntent)).toBe(true);
|
|
expect(Array.isArray(intent.effects)).toBe(true);
|
|
}
|
|
});
|
|
|
|
it('should have effects with target, effect ref, and value', () => {
|
|
for (const intent of enemyIntentDesertData) {
|
|
for (const [target, effect, value] of intent.effects) {
|
|
expect(target === 'self' || target === 'opponent').toBe(true);
|
|
expect(typeof effect === 'string' || typeof effect === 'object').toBe(true);
|
|
expect(typeof value).toBe('number');
|
|
}
|
|
}
|
|
});
|
|
|
|
it('should cover all 14 enemies', () => {
|
|
const enemyIds = new Set(enemyIntentDesertData.map(i => typeof i.enemy === 'string' ? i.enemy : i.enemy.id));
|
|
expect(enemyIds.size).toBe(14);
|
|
});
|
|
});
|