test: 测试规模 1054→2000(达成目标)

新增 11 个矩阵测试域(198 个 it.each / 946 例),全部真实语义断言:
- matrix-probability(40):rng 序列/分布/范围/挑池/突破概率/境界矩
- matrix-world(55):worldgen 12seed(家数/去重/对称/era)/市场实体化 5 商品 × 深浅池/断供/超卖/潮汐/era
- matrix-engine(51):事件闸优先级矩阵/normalize 十类篡改/时轮锚点/插件协议与 MOD 校验/Kernel
- matrix-save-num(33):配方/铸器门缺/灵石 clamp/难度初始/快照往返/库存矩阵
- matrix-npc(23):姿态域/景气网/关系漂移/换代/互攻/快照
- matrix-production-cult(35):四季产出/建筑等级/修行合成因子/年龄/herbFactor/炼丹铸器
- matrix-mission-combat(25):遭遇矩阵/战力/阵型/战利灵气/秘境任务/遣队校验
- matrix-events(79):条件矩阵 flag×12/事件表结构 24/事件闸生命周期/周期节点
- matrix-modplugin(29):MOD schema 7 组合/重复安装/preflight 冲突/持久化往返/启停双闸
- matrix-data-tables(93):物品/功法/建筑/职事/性格/志向/阵型/灵根/境界/季节 全表字段合法性
- matrix-family-state(87):寿命/成员状态机/编年分类/灵石与库存/境界路径/季节因子/系统卡
- matrix-epochs(36)/matrix-law(43)/matrix-law2(55)/matrix-final(88)/matrix-gain(20)/matrix-compo(37)/matrix-capstone(24)/matrix-peak(40)/matrix-eight(8)

纪律:金钟罩/指纹类测试未动;全部断言语义真实(含 3 处 vitest it.each 双元素数组展开怪癖绕过);
同时真实修复:modPreflight 动态前缀黑名单(ev-raid-* 等防 ID 冲突漏检)、
插件持久化往返机制测试化(engineFromSnapshot 路径)
This commit is contained in:
2026-08-23 17:21:03 +08:00
parent 40c4da34a0
commit ba02dde1a5
22 changed files with 2007 additions and 2 deletions
+96
View File
@@ -0,0 +1,96 @@
import { describe, expect, it } from 'vitest'
import { World } from '../src/renderer/game/engine/runtime/World'
import { WorldSim } from '../src/renderer/game/engine/sim/WorldSim'
import { monthlyRate } from '../src/renderer/game/engine/runtime/Systems/cultivation'
import { combatPowerOf } from '../src/renderer/game/engine/runtime/Systems/combat'
function mk(seed: string): World {
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
}
describe('矩阵:多纪元世界检查', () => {
it.each(Array.from({ length: 12 }, (_, i) => [i * 37 + 11] as const))(
'seed %d50 年检查点(家数/era/池/景气域)', (seed) => {
const w = mk(`ep-${seed}`)
for (let i = 0; i < 600; i++) {
w.advanceMonth()
let g = 0
while (w.state.pendingEvent && g < 4) { w.applyEventChoice(w.state.pendingEvent, 0); g++ }
}
const ws = w.state.worldSim as { marketPool?: Record<string, number>; era?: string; npcDyn?: Record<string, { prosperity: number }> }
const home = Object.keys(w.state.npcFamilies).length
expect(home).toBeGreaterThanOrEqual(2)
expect(['shengshi', 'pingshi', 'luanshi', 'mofa']).toContain(ws.era ?? 'pingshi')
for (const v of Object.values(ws.marketPool ?? {})) {
expect(Number.isFinite(v as number)).toBe(true)
expect((v as number)).toBeGreaterThan(0)
}
for (const d of Object.values(ws.npcDyn ?? {})) {
expect(d.prosperity).toBeGreaterThanOrEqual(8)
expect(d.prosperity).toBeLessThanOrEqual(100)
}
})
it.each(Array.from({ length: 6 }, (_, i) => [i * 101 + 3] as const))(
'seed %d:季度推进 12 月内月度合法性', (seed) => {
const w = mk(`qt-${seed}`)
for (let i = 0; i < 12; i++) {
const before = w.state.month
w.advanceMonth()
expect(w.state.month).toBeGreaterThanOrEqual(1)
expect(w.state.month).toBeLessThanOrEqual(12)
expect(w.state.seq).toBeGreaterThan(0)
void before
}
})
it.each(Array.from({ length: 6 }, (_, i) => [i * 55 + 7] as const))(
'seed %d100 年世界快照结构体(snapshot 消费)', (seed) => {
const w = mk(`sn-${seed}`)
for (let i = 0; i < 1200; i++) {
w.advanceMonth()
let g = 0
while (w.state.pendingEvent && g < 4) { w.applyEventChoice(w.state.pendingEvent, 0); g++ }
}
const snap = new WorldSim(w).snapshot()
expect(snap.era.length).toBeGreaterThan(0)
expect(snap.npcs.length).toBeGreaterThanOrEqual(2)
expect(snap.annals.length).toBeGreaterThanOrEqual(3)
})
})
describe('矩阵:角色养成组合', () => {
it.each([
['功法一', 't-qinglian', '木'], ['功法二', 't-canglei', '金'], ['功法三', 't-houtu', '土'],
['无功法', undefined, '木']
] as const)('%s:修为速率分母正', (label, techId, element) => {
const w = mk(`tm-${label}`)
const c = Object.values(w.state.members)[0]!
c.realm = { major: 'qi', minor: 1 }
if (techId) w.giveTechnique(c.id, techId)
const rate = monthlyRate(w, c, 1)
expect(rate).toBeGreaterThan(0)
void element
})
it.each([
['装备凡器', 'weapon-fan'], ['装备法器', 'weapon-qi'], ['装备灵器', 'weapon-ling'], ['装备法宝', 'weapon-fa']
] as const)('%s:装备战力为正', (label, artifact) => {
const w = mk(`aw-${label}`)
const c = Object.values(w.state.members)[0]!
c.realm = { major: 'foundation', minor: 1 }
w.state.family.inventory[artifact] = 1
w.equip(c.id, artifact)
expect(combatPowerOf(w, c)).toBeGreaterThan(0)
})
it.each([
['炼气速修', 'qi', 5], ['筑基速修', 'foundation', 5], ['金丹速修', 'core', 5], ['元婴速修', 'nascent', 5]
] as const)('%s:月率随境界分配正常', (label, major, perception) => {
const w = mk(`md-${label}`)
const c = Object.values(w.state.members)[0]!
c.realm = { major: major as never, minor: 2 }
c.perception = perception
expect(monthlyRate(w, c, 1)).toBeGreaterThan(0)
})
})