diablo2-web/tests/boss.test.ts

139 lines
4.5 KiB
TypeScript

import { describe, it, expect, beforeAll } from 'vitest'
import { ACT_BOSSES, type BossPreset } from '../src/boss.ts'
import { getEmbeddedDropTables } from '../src/game/embedded-drop-tables.ts'
import { executeDropPipeline, type DropTables } from '../src/game/drop-pipeline.ts'
import { formatItemTooltip } from '../src/game/item-tooltip.ts'
import type { Item } from '../src/game/items.ts'
describe('Act Boss Loot Simulator (boss.html)', () => {
let dropTables: DropTables
beforeAll(() => {
dropTables = getEmbeddedDropTables()
})
it('1. ACT_BOSSES catalog includes all 5 canonical Act Bosses', () => {
expect(ACT_BOSSES).toHaveLength(5)
const bossIds = ACT_BOSSES.map(b => b.id)
expect(bossIds).toEqual(['andariel', 'duriel', 'mephisto', 'diablo', 'baal'])
})
it('2. All standard TCs and Quest TCs resolve to valid nodes in TreasureClassEx', () => {
const difficulties: Array<'normal' | 'nightmare' | 'hell'> = ['normal', 'nightmare', 'hell']
for (const boss of ACT_BOSSES) {
for (const diff of difficulties) {
const stdTc = boss.tc[diff]
const questTc = boss.questTc[diff]
const stdNode = dropTables.tcTable.get(stdTc)
const questNode = dropTables.tcTable.get(questTc)
expect(stdNode, `Boss ${boss.id} [${diff}] std TC ${stdTc} should exist`).toBeDefined()
expect(questNode, `Boss ${boss.id} [${diff}] quest TC ${questTc} should exist`).toBeDefined()
expect(stdNode?.picks).toBeGreaterThan(0)
expect(questNode?.picks).toBeGreaterThan(0)
}
}
})
it('3. Simulates single Hell Mephisto kill and generates realistic dropped items with attributes', () => {
const drops: Item[] = executeDropPipeline({
tcName: 'Mephistoq (H)',
nLevel: 87,
dropTables,
difficulty: 'hell',
playerMf: 300,
gamePlayers: 1,
partyPlayers: 1,
monsterRng: 42,
})
expect(drops.length).toBeGreaterThan(0)
for (const item of drops) {
expect(item.name.length).toBeGreaterThan(0)
expect(item.code).toBeDefined()
expect(item.code!.length).toBeGreaterThan(0)
expect(item.base).toBeDefined()
const tooltip = formatItemTooltip(item)
expect(tooltip.title.length).toBeGreaterThan(0)
expect(tooltip.quality.length).toBeGreaterThan(0)
expect(tooltip.ilvl).toBe(87)
// If equipment, verify stats formatting
if (item.base.kind === 'weapon' || item.base.kind === 'armor') {
expect(tooltip.baseType).toMatch(/武器|防具/)
}
}
})
it('4. Simulates Hell Baal kill with 7 Players (low NoDrop) and rolls multi-tier affixes', () => {
const drops: Item[] = executeDropPipeline({
tcName: 'Baal (H)',
nLevel: 99,
dropTables,
difficulty: 'hell',
playerMf: 250,
gamePlayers: 7,
partyPlayers: 1,
monsterRng: 99999,
})
expect(drops.length).toBeGreaterThan(0)
const qualities = drops.map(d => d.rarity)
expect(qualities.length).toBe(drops.length)
})
it('5. Verifies formatItemTooltip generates correct properties for Unique, Rare, and Magic items', () => {
// 5.1 Unique Item Tooltip Test
const dummyUniqueBase = dropTables.getBase('uap')! // Shako
const dummyUniqueDef = dropTables.uniques.getEnabledByCode('uap')[0]!
const uniqueItem: Item = {
base: dummyUniqueBase,
prefix: null,
suffix: null,
level: 87,
ilvl: 87,
name: dummyUniqueDef.index,
stats: { defense: 141, allskills: 2, mag: 50 },
invWidth: dummyUniqueBase.invWidth,
invHeight: dummyUniqueBase.invHeight,
stack: 1,
value: 10000,
rarity: 'unique',
uniqueItemDef: dummyUniqueDef,
}
const uniqueTooltip = formatItemTooltip(uniqueItem)
expect(uniqueTooltip.title).toBe(dummyUniqueDef.index)
expect(uniqueTooltip.quality).toBe('unique')
expect(uniqueTooltip.lines.length).toBeGreaterThan(0)
// 5.2 Rune Tooltip Test
const dummyRuneBase = dropTables.getBase('r30')! // Ber Rune
const runeItem: Item = {
base: dummyRuneBase,
prefix: null,
suffix: null,
level: 63,
ilvl: 63,
name: 'Ber Rune',
code: 'r30 ',
stats: {},
invWidth: 1,
invHeight: 1,
stack: 1,
value: 100,
rarity: 'normal',
}
const runeTooltip = formatItemTooltip(runeItem)
expect(runeTooltip.title).toContain('30#')
expect(runeTooltip.quality).toContain('符文')
expect(runeTooltip.lines.some(l => l.text.includes('压碎打击'))).toBe(true)
})
})