Files
90CNServer/pvf/frontend/tests/forge-gui.test.ts
T
hanfuit 645b64fe21 DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go):
- GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面
- GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新
- 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新)
- 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍
- 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0)
- 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算

启动器(Python/JS):
- 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭
- GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐)
- 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
2026-11-04 14:31:55 +08:00

50 lines
3.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { editForge } from "../src/gui/forge";
import { upgradeRange } from "../src/gui/upgrade";
import type { UpgradeRow } from "../bindings/pvfine/services/models";
function fixture() {
const normalized = "# 😀\n[table]\n2 1 10000 1\n3 2 5000 1.11\n[/table]\n[separate upgrade max]\n2\n[item weights by grade]\n96 3326 51\n100 3326 51\n[/item weights by grade]";
const field = (value: string, start: number) => ({ value: Number(value), start, end: start + value.length, tokenType: value.includes('.') ? 2 : 0 });
const row = (line: string, level: number, grade = false): UpgradeRow => {
const start = normalized.indexOf(line);
const fields = [...line.matchAll(/\d+(?:\.\d+)?/g)].map(m => field(m[0], start + m.index!));
return { level, fields: grade ? fields.slice(1) : fields, fieldsT2: [], costName: "强烈的气息" } as UpgradeRow;
};
return { text: normalized.replaceAll("\n", "\r\n"), rows: [row("2 1 10000 1",1), row("3 2 5000 1.11",2)], grades: [row("96 3326 51",96,true), row("100 3326 51",100,true)], max: [{ level: 1, fields: [field("2", normalized.indexOf("[separate upgrade max]\n") + "[separate upgrade max]\n".length)], fieldsT2: [], costName: "" } as UpgradeRow] };
}
describe("锻造 GUI 源码编辑", () => {
it("六列布局的归一化字段保留附加系数,只更新成功率", () => {
const text = "[table]\n2 1 2.6 1 10000 1\n[/table]";
const start = text.indexOf("10000");
const row = { level: 1, fields: [
{ value: 2, start: 8, end: 9, tokenType: 0 },
{ value: 1, start: 10, end: 11, tokenType: 0 },
{ value: 10000, start, end: start + 5, tokenType: 0 },
{ value: 1, start: start + 6, end: start + 7, tokenType: 0 },
], fieldsT2: [{ value: 2.6, start: 12, end: 15, tokenType: 2 }, { value: 1, start: 16, end: 17, tokenType: 0 }], costName: "" } as UpgradeRow;
expect(editForge(text, [row], "table", [{ column: 2, value: 75.25 }], 1)).toBe(text.replace("10000", "7525"));
});
it("成功率使用万分比,批量保留属性系数和 CRLF", () => {
const {text,rows}=fixture();
expect(editForge(text,rows,"table",[{column:2,value:75.25}],2)).toBe(text.replace("10000 1","7525 1").replace("5000 1.11","7525 1.11"));
expect(editForge(text,[rows[1]!],"table",[{column:3,value:1.5}],2)).toBe(text.replace("1.11","1.5"));
});
it("装备等级范围单独选择且仅替换材料和数量基数", () => {
const {text,grades}=fixture();
const chosen=upgradeRange(grades,[97,100]);
expect(chosen).toHaveLength(1);
expect(editForge(text,chosen,"grades",[{column:0,value:4444},{column:1,value:80}],2)).toBe(text.replace("100 3326 51","100 4444 80"));
});
it("最大等级限制及无效、过期和重叠数据拒绝", () => {
const {text,rows,max,grades}=fixture();
expect(editForge(text,max,"maximum",[{column:0,value:1}],2)).toBe(text.replace("[separate upgrade max]\r\n2","[separate upgrade max]\r\n1"));
for (const value of [0,3,1.5]) expect(()=>editForge(text,max,"maximum",[{column:0,value}],2)).toThrow();
expect(()=>editForge(text,rows,"table",[{column:2,value:101}],2)).toThrow();
expect(()=>editForge(text,rows,"table",[{column:0,value:1}],2)).toThrow();
expect(()=>editForge(text,grades,"grades",[{column:1,value:1.5}],2)).toThrow();
expect(()=>editForge(text,rows,"table",[{column:3,value:1.5}],2)).toThrow("整数");
expect(()=>editForge(text.replace("5000","6000"),rows,"table",[{column:2,value:1}],2)).toThrow("草稿已变化");
expect(()=>editForge(text,rows,"table",[{column:2,value:1},{column:2,value:2}],2)).toThrow("重叠");
});
});