From 4bfc6db60fe620994229e0f3a95af40e81d1f7ae Mon Sep 17 00:00:00 2001 From: hyper Date: Sun, 12 Apr 2026 21:04:38 +0800 Subject: [PATCH] chore: add data import test --- .../data/heroItemFighter1.csv | 4 +- .../data/heroItemFighter1.csv.d.ts | 12 +++ src/samples/slay-the-spire-like/data/index.ts | 3 + .../slay-the-spire-like/data/index.test.ts | 73 +++++++++++++++++++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/samples/slay-the-spire-like/data/heroItemFighter1.csv.d.ts create mode 100644 src/samples/slay-the-spire-like/data/index.ts create mode 100644 tests/samples/slay-the-spire-like/data/index.test.ts diff --git a/src/samples/slay-the-spire-like/data/heroItemFighter1.csv b/src/samples/slay-the-spire-like/data/heroItemFighter1.csv index 750d2ec..3a36120 100644 --- a/src/samples/slay-the-spire-like/data/heroItemFighter1.csv +++ b/src/samples/slay-the-spire-like/data/heroItemFighter1.csv @@ -22,12 +22,12 @@ armor,披风,oers,energy,1,none,【防御2】,下回合【防御2】 armor,护腕,o,energy,0,none,【防御1】,抓1张牌 armor,大盾,oesswn,energy,1,none,【防御5】 armor,锁子甲,oers,energy,1,none,本回合受到伤害-3 -consumable,绷带,o,uses,3,none,随机移除1格伤口 +consumable,绷带,o,uses,3,none,从牌堆或弃牌堆随机移除1张伤口 consumable,淬毒药剂,o,uses,3,none,周围物品的【攻击】+2 consumable,强固药剂,o,uses,3,none,周围物品的【防御】+2 consumable,活力药剂,o,uses,3,none,获得1点能量 consumable,集中药剂,o,uses,3,none,抓2张牌 -consumable,治疗药剂,o,uses,3,none,移除3个随机伤口 +consumable,治疗药剂,o,uses,3,none,从牌堆或弃牌堆移除3张伤口 tool,水袋,os,energy,1,none,下回合开始时,获得1能量,抓2张牌 tool,绳索,ose,energy,1,none,周围物品的牌【防御】+2直到打出 tool,腰带,owre,energy,0,none,从牌堆周围物品的牌当中选择一张加入手牌 diff --git a/src/samples/slay-the-spire-like/data/heroItemFighter1.csv.d.ts b/src/samples/slay-the-spire-like/data/heroItemFighter1.csv.d.ts new file mode 100644 index 0000000..bdcce42 --- /dev/null +++ b/src/samples/slay-the-spire-like/data/heroItemFighter1.csv.d.ts @@ -0,0 +1,12 @@ +type HeroItemFighter1Table = readonly { + readonly type: string; + readonly name: string; + readonly shape: string; + readonly costType: string; + readonly costCount: number; + readonly targetType: string; + readonly desc: string; +}[]; + +declare const data: HeroItemFighter1Table; +export default data; diff --git a/src/samples/slay-the-spire-like/data/index.ts b/src/samples/slay-the-spire-like/data/index.ts new file mode 100644 index 0000000..55c011c --- /dev/null +++ b/src/samples/slay-the-spire-like/data/index.ts @@ -0,0 +1,3 @@ +import heroItemFighter1Csv from './heroItemFighter1.csv'; + +export const heroItemFighter1Data = heroItemFighter1Csv; diff --git a/tests/samples/slay-the-spire-like/data/index.test.ts b/tests/samples/slay-the-spire-like/data/index.test.ts new file mode 100644 index 0000000..51c2ba9 --- /dev/null +++ b/tests/samples/slay-the-spire-like/data/index.test.ts @@ -0,0 +1,73 @@ +import { describe, it, expect } from 'vitest'; +import { heroItemFighter1Data } 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', () => { + // CSV has 24 data rows (excluding header and type rows) + 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); + + expect(typeCounts['weapon']).toBe(6); + expect(typeCounts['armor']).toBe(6); + expect(typeCounts['consumable']).toBe(6); + expect(typeCounts['tool']).toBe(6); + }); +});