import { describe, it, expect } from 'vitest'; // ─── Test: EquipmentTab barrel export ────────────────────────────────────────── describe('EquipmentTab module structure', () => { it('exports EquipmentTab from barrel index', async () => { const mod = await import('./EquipmentTab'); expect(mod.EquipmentTab).toBeDefined(); expect(typeof mod.EquipmentTab).toBe('function'); }); it('EquipmentTab has correct displayName', async () => { const { EquipmentTab } = await import('./EquipmentTab'); expect(EquipmentTab.displayName).toBe('EquipmentTab'); }); }); // ─── Test: Barrel export includes EquipmentTab ───────────────────────────────── describe('Tab barrel export', () => { it('includes EquipmentTab in the tabs index', async () => { const mod = await import('@/components/game/tabs'); expect(mod.EquipmentTab).toBeDefined(); expect(typeof mod.EquipmentTab).toBe('function'); }); }); // ─── Test: Equipment slot definitions ────────────────────────────────────────── describe('Equipment slot definitions', () => { it('has exactly 8 equipment slots', async () => { const { EQUIPMENT_SLOTS } = await import('@/lib/game/data/equipment'); expect(EQUIPMENT_SLOTS).toHaveLength(8); }); it('all slots have display names', async () => { const { SLOT_NAMES, EQUIPMENT_SLOTS } = await import('@/lib/game/data/equipment'); for (const slot of EQUIPMENT_SLOTS) { expect(SLOT_NAMES[slot]).toBeDefined(); expect(SLOT_NAMES[slot].length).toBeGreaterThan(0); } }); it('includes mainHand, offHand, head, body, hands, feet, accessory1, accessory2', async () => { const { EQUIPMENT_SLOTS } = await import('@/lib/game/data/equipment'); expect(EQUIPMENT_SLOTS).toContain('mainHand'); expect(EQUIPMENT_SLOTS).toContain('offHand'); expect(EQUIPMENT_SLOTS).toContain('head'); expect(EQUIPMENT_SLOTS).toContain('body'); expect(EQUIPMENT_SLOTS).toContain('hands'); expect(EQUIPMENT_SLOTS).toContain('feet'); expect(EQUIPMENT_SLOTS).toContain('accessory1'); expect(EQUIPMENT_SLOTS).toContain('accessory2'); }); }); // ─── Test: Equipment type definitions ────────────────────────────────────────── describe('Equipment type definitions', () => { it('all equipment types have required fields', async () => { const { EQUIPMENT_TYPES } = await import('@/lib/game/data/equipment'); for (const [id, type] of Object.entries(EQUIPMENT_TYPES)) { expect(type.id).toBe(id); expect(type.name).toBeTruthy(); expect(type.category).toBeTruthy(); expect(type.slot).toBeTruthy(); expect(type.baseCapacity).toBeGreaterThan(0); } }); it('accessory category types can equip in accessory slots', async () => { const { EQUIPMENT_TYPES, getValidSlotsForEquipmentType } = await import('@/lib/game/data/equipment'); const accessories = Object.values(EQUIPMENT_TYPES).filter((t) => t.category === 'accessory'); expect(accessories.length).toBeGreaterThan(0); for (const acc of accessories) { const slots = getValidSlotsForEquipmentType(acc); expect(slots).toContain('accessory1'); expect(slots).toContain('accessory2'); } }); }); // ─── Test: Starting equipment ────────────────────────────────────────────────── describe('Starting equipment', () => { it('crafting store initial state has valid equippedInstances', async () => { const { useCraftingStore } = await import('@/lib/game/stores/craftingStore'); const state = useCraftingStore.getState(); expect(state.equippedInstances.mainHand).toBeTruthy(); expect(state.equippedInstances.body).toBeTruthy(); expect(state.equippedInstances.feet).toBeTruthy(); expect(state.equippedInstances.offHand).toBeNull(); expect(state.equippedInstances.head).toBeNull(); expect(state.equippedInstances.hands).toBeNull(); expect(state.equippedInstances.accessory1).toBeNull(); expect(state.equippedInstances.accessory2).toBeNull(); expect(Object.keys(state.equipmentInstances).length).toBe(3); }); it('starting equipment instances have valid fields', async () => { const { useCraftingStore } = await import('@/lib/game/stores/craftingStore'); const { equipmentInstances } = useCraftingStore.getState(); for (const instance of Object.values(equipmentInstances)) { expect(instance.instanceId).toBeTruthy(); expect(instance.typeId).toBeTruthy(); expect(instance.name).toBeTruthy(); expect(instance.rarity).toBe('common'); expect(instance.quality).toBe(100); expect(instance.usedCapacity).toBeGreaterThanOrEqual(0); expect(instance.totalCapacity).toBeGreaterThan(0); } }); }); // ─── Test: Equipment actions ─────────────────────────────────────────────────── describe('Equipment actions', () => { it('equipItem is a function', async () => { const { equipItem } = await import('@/lib/game/crafting-actions/equipment-actions'); expect(typeof equipItem).toBe('function'); }); it('unequipItem is a function', async () => { const { unequipItem } = await import('@/lib/game/crafting-actions/equipment-actions'); expect(typeof unequipItem).toBe('function'); }); it('deleteEquipmentInstance is a function', async () => { const { deleteEquipmentInstance } = await import('@/lib/game/crafting-actions/equipment-actions'); expect(typeof deleteEquipmentInstance).toBe('function'); }); it('createEquipmentInstance is a function', async () => { const { createEquipmentInstance } = await import('@/lib/game/crafting-actions/equipment-actions'); expect(typeof createEquipmentInstance).toBe('function'); }); }); // ─── Test: Equipment effects ─────────────────────────────────────────────────── describe('Equipment effects computation', () => { it('computeEquipmentEffects returns empty for no equipment', async () => { const { computeEquipmentEffects } = await import('@/lib/game/effects'); const result = computeEquipmentEffects({}, { mainHand: null, offHand: null, head: null, body: null, hands: null, feet: null, accessory1: null, accessory2: null }); expect(Object.keys(result.bonuses)).toHaveLength(0); expect(Object.keys(result.multipliers)).toHaveLength(0); expect(result.specials.size).toBe(0); }); it('computeEquipmentEffects detects enchantment bonuses', async () => { const { computeEquipmentEffects } = await import('@/lib/game/effects'); const instances = { test1: { instanceId: 'test1', typeId: 'basicStaff', name: 'Test Staff', enchantments: [{ effectId: 'spell_manaBolt', stacks: 1, actualCost: 50 }], usedCapacity: 50, totalCapacity: 50, rarity: 'common' as const, quality: 100, tags: [], }, }; const equipped = { mainHand: 'test1', offHand: null, head: null, body: null, hands: null, feet: null, accessory1: null, accessory2: null }; const result = computeEquipmentEffects(instances, equipped); // Should at least not crash and return a valid structure expect(result).toHaveProperty('bonuses'); expect(result).toHaveProperty('multipliers'); expect(result).toHaveProperty('specials'); }); }); // ─── Test: File size limits ──────────────────────────────────────────────────── describe('File size limits (400 lines max)', () => { it('EquipmentTab.tsx is under 400 lines', async () => { const fs = await import('fs'); const path = await import('path'); const filePath = path.join(__dirname, 'EquipmentTab.tsx'); const content = fs.readFileSync(filePath, 'utf-8'); const lines = content.split('\n').length; expect(lines).toBeLessThan(400); }); it('EquipmentSlotGrid.tsx is under 400 lines', async () => { const fs = await import('fs'); const path = await import('path'); const filePath = path.join(__dirname, 'EquipmentTab/EquipmentSlotGrid.tsx'); const content = fs.readFileSync(filePath, 'utf-8'); const lines = content.split('\n').length; expect(lines).toBeLessThan(400); }); it('InventoryList.tsx is under 400 lines', async () => { const fs = await import('fs'); const path = await import('path'); const filePath = path.join(__dirname, 'EquipmentTab/InventoryList.tsx'); const content = fs.readFileSync(filePath, 'utf-8'); const lines = content.split('\n').length; expect(lines).toBeLessThan(400); }); it('EquipmentEffectsSummary.tsx is under 400 lines', async () => { const fs = await import('fs'); const path = await import('path'); const filePath = path.join(__dirname, 'EquipmentTab/EquipmentEffectsSummary.tsx'); const content = fs.readFileSync(filePath, 'utf-8'); const lines = content.split('\n').length; expect(lines).toBeLessThan(400); }); });