服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
29 lines
2.2 KiB
TypeScript
29 lines
2.2 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
import { createItemNameSession } from '../src/gui/itemNames';
|
|
function deferred<T>() { let resolve!: (value: T) => void; const promise=new Promise<T>(r=>{resolve=r;});return{resolve,promise}; }
|
|
describe('礼包关联物品名称',()=>{
|
|
it('合并普通与自选奖励 ID,只查询一次重复 ID,保留未知物品标记',async()=>{
|
|
const read=vi.fn(async()=>({'1':'药剂','4':'装备😀'}));const session=createItemNameSession(read);
|
|
await session.load(['1','4','1',' 1 ','999','','invalid']);
|
|
expect(read).toHaveBeenCalledExactlyOnceWith(['1','4','999']);expect(session.names.value).toEqual({'1':'药剂','4':'装备😀','999':''});
|
|
});
|
|
it('修改奖励 ID 后淘汰旧名称,延迟结果不能覆盖新奖励',async()=>{
|
|
const old=deferred<Record<string,string>>(),next=deferred<Record<string,string>>();let calls=0;
|
|
const session=createItemNameSession(()=>++calls===1?old.promise:next.promise);
|
|
const first=session.load(['1']);const second=session.load(['2']);next.resolve({'2':'新奖励'});await second;
|
|
old.resolve({'1':'旧奖励'});await first;expect(session.names.value).toEqual({'2':'新奖励'});
|
|
});
|
|
it('切换归档清空名称并忽略旧归档响应,防止同 ID 串名',async()=>{
|
|
const pending=deferred<Record<string,string>>();const session=createItemNameSession(()=>pending.promise);
|
|
const first=session.load(['1']);session.invalidate(true);pending.resolve({'1':'旧归档'});await first;
|
|
expect(session.names.value).toEqual({});expect(session.loading.value).toBe(false);
|
|
});
|
|
it('同归档刷新保留已显示名称,失败后可以重试,空列表不发请求',async()=>{
|
|
const read=vi.fn().mockResolvedValueOnce({'1':'原名称'}).mockRejectedValueOnce(new Error('read failed')).mockResolvedValueOnce({'1':'更新名称'});
|
|
const session=createItemNameSession(read);await session.load(['1']);session.invalidate();await session.load(['1']);
|
|
expect(session.names.value['1']).toBe('原名称');expect(session.error.value).toContain('read failed');
|
|
await session.load(['1']);expect(session.names.value['1']).toBe('更新名称');expect(session.error.value).toBe('');
|
|
await session.load([]);expect(session.names.value).toEqual({});expect(read).toHaveBeenCalledTimes(3);
|
|
});
|
|
});
|