服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
47 lines
4.2 KiB
TypeScript
47 lines
4.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { createPinia, setActivePinia } from 'pinia';
|
|
import { nextTick } from 'vue';
|
|
import type { ItemCreateRequest } from '../bindings/pvfine/services/models';
|
|
const api=vi.hoisted(()=>({GetFileBasic:vi.fn(),GetFile:vi.fn(),GetAnnotations:vi.fn(),CreateItem:vi.fn(),refreshInfo:vi.fn(),events:new Map<string,Array<()=>void>>()}));
|
|
vi.mock('@wailsio/runtime',()=>({Events:{On:(name:string,fn:()=>void)=>api.events.set(name,[...(api.events.get(name)??[]),fn])}}));
|
|
vi.mock('../bindings/pvfine/services',()=>({EditorService:api,ArchiveService:api,FileGUIService:api}));
|
|
vi.mock('../src/stores/archive',()=>({useArchiveStore:()=>({refreshInfo:api.refreshInfo})}));
|
|
vi.mock('../src/stores/script',()=>({useScriptStore:()=>({})}));
|
|
vi.mock('../src/stores/explorer',()=>({useExplorerStore:()=>({getFilePath:()=>'',refreshTreeTags:vi.fn()})}));
|
|
import { useEditorStore } from '../src/stores/editor';
|
|
import { useFileGUIStore } from '../src/stores/fileGUI';
|
|
const meta=(index:number)=>({index,path:index===1?'stackable/stackable.lst':'stackable/source.stk',text:'original',editable:true,dataType:1,size:8,tags:[],annotations:[],modified:false});
|
|
const request:ItemCreateRequest={path:'stackable/new.stk',id:'999',name:'新物品',text:'[name]\n`copy`',revision:1,drafts:[]};
|
|
beforeEach(()=>{setActivePinia(createPinia());vi.resetAllMocks();api.events.clear();api.GetFileBasic.mockImplementation(async i=>meta(i));api.GetAnnotations.mockResolvedValue([]);api.GetFile.mockResolvedValue(null);});
|
|
describe('物品创建工作区',()=>{
|
|
it('提交包含所有未保存草稿,仅推进被消费列表的基线',async()=>{
|
|
const editor=useEditorStore();await editor.openGUIFile(1);await editor.openGUIFile(2);
|
|
editor.updateContent(1,'list draft');editor.updateContent(2,'source draft');
|
|
api.CreateItem.mockResolvedValue({fileIndex:3,path:request.path,id:'999',files:[{fileIndex:1,path:'stackable/stackable.lst',beforeText:'list draft',text:'registered list'}]});
|
|
await editor.createItem(request);
|
|
expect(api.CreateItem.mock.calls[0]![0].drafts).toEqual([{fileIndex:1,path:'stackable/stackable.lst',text:'list draft'},{fileIndex:2,path:'stackable/source.stk',text:'source draft'}]);
|
|
expect(editor.getFileDraft(1)).toMatchObject({text:'registered list',original:'registered list',modified:true});
|
|
expect(editor.getFileDraft(2)).toMatchObject({text:'source draft',original:'original'});
|
|
expect(editor.dirtyCount).toBe(1);expect(editor.saving).toBe(false);expect(editor.guiApplying).toBe(false);
|
|
});
|
|
it('创建期间锁定编辑,失败后保留草稿和状态',async()=>{
|
|
const editor=useEditorStore();await editor.openGUIFile(1);editor.updateContent(1,'draft');
|
|
let reject!:(e:Error)=>void;api.CreateItem.mockImplementation(()=>new Promise((_,r)=>{reject=r;}));
|
|
const work=editor.createItem(request);await nextTick();
|
|
expect(editor.guiApplying).toBe(true);editor.updateContent(1,'unexpected');expect(editor.getFileDraft(1)?.text).toBe('draft');
|
|
reject(new Error('ID conflict'));await expect(work).rejects.toThrow('ID conflict');
|
|
expect(editor.getFileDraft(1)).toMatchObject({text:'draft',original:'original'});expect(editor.guiApplying).toBe(false);
|
|
});
|
|
it('拒绝跨归档的旧返回值',async()=>{
|
|
const editor=useEditorStore(),gui=useFileGUIStore();await editor.openGUIFile(1);editor.updateContent(1,'draft');
|
|
let resolve!:(v:unknown)=>void;api.CreateItem.mockImplementation(()=>new Promise(r=>{resolve=r;}));
|
|
const work=editor.createItem(request);await nextTick();gui.epoch++;
|
|
resolve({fileIndex:3,path:request.path,id:'999',files:[{fileIndex:1,path:'stackable/stackable.lst',beforeText:'draft',text:'old response'}]});
|
|
await expect(work).rejects.toThrow('归档已切换');expect(editor.getFileDraft(1)?.text).toBe('draft');expect(editor.saving).toBe(false);
|
|
});
|
|
it('刷新失败仍返回已创建结果并保留提示,避免重复创建',async()=>{
|
|
const editor=useEditorStore();api.CreateItem.mockResolvedValue({fileIndex:3,path:request.path,id:'999',files:[]});api.refreshInfo.mockRejectedValue(new Error('refresh'));
|
|
expect((await editor.createItem(request)).fileIndex).toBe(3);expect(editor.guiRefreshWarning).toContain('已创建');
|
|
});
|
|
});
|