diablo2-web/tests/p0-521-gold-duplication.tes...

57 lines
2.1 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { GameEngine } from '../src/server/engine/engine.ts'
describe('Issue #521: Gold Conservation Invariant & Single Source of Truth', () => {
it('maintains strict gold conservation across drop and pickup without duplication', () => {
const engine = new GameEngine('sor')
engine.bag.gold = 5000
// Drop 2000 gold (server-authoritative `dropPlayerGold`)
const pile = engine.dropPlayerGold(2000)
expect(pile?.goldAmount).toBe(2000)
expect(engine.bag.gold).toBe(3000)
const goldPiles = engine.groundItems.all.filter(g => g.isGold)
expect(goldPiles.length).toBe(1)
expect(goldPiles[0]!.goldAmount).toBe(2000)
// Total gold in system (player + ground) is conserved at 5000
expect(engine.bag.gold + (goldPiles[0]!.goldAmount ?? 0)).toBe(5000)
// Pick up gold pile
const picked = engine.pickupGroundGoldPile(goldPiles[0]!.id)
expect(picked).toBe(2000)
expect(engine.bag.gold).toBe(5000)
expect(engine.groundItems.all.filter(g => g.isGold).length).toBe(0)
})
it('clamps gold pickup to playerLevel * 10,000 capacity and leaves remainder on ground', () => {
const engine = new GameEngine('pal')
// Level 1 capacity = 10,000
expect(engine.maxGoldCapacity).toBe(10_000)
engine.bag.gold = 8500
const pile = engine.groundItems.spawnGold(engine.world.player.x, engine.world.player.y, 4000, 0)
const picked = engine.pickupGroundGoldPile(pile.id)
expect(picked).toBe(1500)
expect(engine.bag.gold).toBe(10_000)
const remainingPile = engine.groundItems.get(pile.id)
expect(remainingPile).toBeDefined()
expect(remainingPile!.goldAmount).toBe(2500)
})
it('rejects negative, zero, or NaN gold drops without mutating state', () => {
const engine = new GameEngine('ama')
engine.bag.gold = 1200
expect(engine.dropPlayerGold(0)).toBeNull()
expect(engine.dropPlayerGold(-500)).toBeNull()
expect(engine.dropPlayerGold(Number.NaN)).toBeNull()
expect(engine.bag.gold).toBe(1200)
expect(engine.groundItems.count).toBe(0)
})
})