feat: wire lobby task and VIP prefab flows and sync UI assets
This commit is contained in:
@@ -59,6 +59,50 @@ function makeCommands(store: PlatformStore): {
|
||||
};
|
||||
}
|
||||
|
||||
test('VIP query and both entry forms use the exact agent protocol',()=>{
|
||||
const store=makeStore('outside'),{commands,sent}=makeCommands(store);
|
||||
commands.getVipRooms(['123456']);commands.joinVipRoom('123456',null);commands.joinVipRoom(900001,{city:'测试'});
|
||||
assert.deepEqual(sent[0],{app:'youle',route:'agent',rpc:'getInfoByShortCode',data:{agentid:'agent-from-config',gameid:'game-from-config',shortcodeList:['123456']}});
|
||||
assert.deepEqual(sent[1],{app:'youle',route:'agent',rpc:'self_join_room',data:{agentid:'agent-from-config',playerid:430511,gameid:'game-from-config',roomcode:'123456',joinmode:0,location:null,ip:store.getState().players.entities[430511].ip}});
|
||||
assert.equal((sent[2].data as {roomcode:number}).roomcode,900001);
|
||||
assert.throws(()=>makeCommands(new PlatformStore()).commands.getVipRooms([]),/logged-in/);
|
||||
});
|
||||
|
||||
test('task requests preserve legacy identity fields and reject unclaimable entries',()=>{
|
||||
const store=makeStore('outside');const {commands,sent}=makeCommands(store);
|
||||
commands.getPlayerTasks();
|
||||
store.applyTaskList({tasks:[{taskid:7,title:'任务',award:1,finish:1,total:1,state:1}]});
|
||||
commands.claimTask(7);
|
||||
assert.deepEqual(sent,[
|
||||
{app:'youle',route:'agent',rpc:'get_player_task',data:{agentid:'agent-from-config',playerid:430511,gameid:'game-from-config'}},
|
||||
{app:'youle',route:'agent',rpc:'get_task_award',data:{agentid:'agent-from-config',playerid:430511,taskid:7}},
|
||||
]);
|
||||
store.applyTaskAward({taskid:7,taskstate:0});
|
||||
assert.equal(store.getState().tasks?.[0].state,2);
|
||||
assert.equal(store.getState().players.entities[430511].taskstate,0);
|
||||
assert.throws(()=>commands.claimTask(7),/claimable/);
|
||||
const before=store.getState();
|
||||
assert.throws(()=>store.applyTaskList({tasks:[{taskid:7}]}));
|
||||
assert.equal(store.getState(),before);
|
||||
assert.throws(()=>makeCommands(new PlatformStore()).commands.getPlayerTasks(),/logged-in/);
|
||||
});
|
||||
|
||||
test('task numeric strings normalize at ingestion and invalid values never commit',()=>{
|
||||
const store=makeStore('outside');
|
||||
const task={taskid:'7',title:'任务',award:'3',finish:'2',total:'5',state:'0'};
|
||||
store.applyTaskList({tasks:[task]});
|
||||
assert.deepEqual(store.getState().tasks,[{...task,award:3,finish:2,total:5,state:0}]);
|
||||
assert.equal(task.award,'3');
|
||||
const before=store.getState();
|
||||
for(const field of ['award','finish','total','state']){
|
||||
for(const value of ['', ' ', 'abc', 'Infinity', null, true, [], {}, undefined]){
|
||||
assert.throws(()=>store.applyTaskList({tasks:[{...task,[field]:value}]}),new RegExp(field));
|
||||
assert.equal(store.getState(),before);
|
||||
}
|
||||
}
|
||||
assert.throws(()=>store.applyTaskList({tasks:[{...task,state:'1.5'}]}),/state/);
|
||||
});
|
||||
|
||||
test('prepare and exitRoom use the first-slice builders with authoritative config and room state', () => {
|
||||
const { commands, sent } = makeCommands(makeStore('inside', 0));
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ test('applyLoginSuccess commits the complete login once and notifies once', () =
|
||||
sex: 0,
|
||||
bean: 0,
|
||||
ip: '127.0.0.1',
|
||||
roomcard: 3, taskstate: 1, score: 0, sign: null,
|
||||
roomcard: 3, taskstate: 1, advanced: 0, score: 0, sign: null,
|
||||
});
|
||||
assert.deepEqual(state.room, { kind: 'outside' });
|
||||
});
|
||||
|
||||
@@ -310,6 +310,39 @@ function makeRuntime(config: RuntimeConfig = runtimeConfig(), entry = makeGameEn
|
||||
return { runtime, wire, scene, clock, factoryConfigs, config };
|
||||
}
|
||||
|
||||
test('VIP wire query response reaches canonical state and clears on login replacement',async()=>{
|
||||
const {runtime,wire}=makeRuntime();await runtime.start();
|
||||
wire.emit({type:'open',server:'ws://agent'});runtime.login(ACCOUNT);
|
||||
const login=()=>wire.emit({type:'message',message:{route:'agent',rpc:'player_login',data:fixture('player-login-success.json')}});
|
||||
login();runtime.getVipRooms(['123456']);
|
||||
wire.emit({type:'message',message:{route:'agent',rpc:'getInfoByShortCode',data:{roomInfo:[{shortCode:123456,owner:'房主',playerList:[]}]}}});
|
||||
assert.equal(runtime.state.vipRooms?.[0].shortCode,123456);
|
||||
wire.emit({type:'message',message:{route:'agent',rpc:'getInfoByShortCode',data:{roomInfo:[]}}});
|
||||
assert.deepEqual(runtime.state.vipRooms,[]);
|
||||
login();assert.equal(runtime.state.vipRooms,undefined);runtime.stop();
|
||||
});
|
||||
|
||||
test('task wire responses reach the store and claim does not invent reward balances',async()=>{
|
||||
const {runtime,wire}=makeRuntime();await runtime.start();
|
||||
wire.emit({type:'open',server:'ws://agent'});runtime.login(ACCOUNT);
|
||||
wire.emit({type:'message',message:{route:'agent',rpc:'player_login',data:fixture('player-login-success.json')}});
|
||||
runtime.getPlayerTasks();
|
||||
wire.emit({type:'message',message:{route:'agent',rpc:'get_player_task',data:{tasks:[{taskid:7,title:'任务',award:'3',finish:'1',total:'1',state:'1'}]}}});
|
||||
assert.equal(runtime.state.tasks?.[0].award,3);
|
||||
const balance=runtime.state.players.entities[430511].roomcard;
|
||||
runtime.claimTask(7);
|
||||
wire.emit({type:'message',message:{route:'agent',rpc:'get_task_award',data:{taskid:'7',taskstate:0}}});
|
||||
assert.equal(runtime.state.tasks?.[0].state,2);
|
||||
assert.equal(runtime.state.players.entities[430511].taskstate,0);
|
||||
assert.equal(runtime.state.players.entities[430511].roomcard,balance);
|
||||
wire.emit({type:'message',message:{route:'agent',rpc:'update_roomcard',data:{roomcard:25}}});
|
||||
assert.equal(runtime.state.players.entities[430511].roomcard,25);
|
||||
wire.emit({type:'message',message:{route:'agent',rpc:'player_finish_task',data:{state:1}}});
|
||||
assert.equal(runtime.state.players.entities[430511].taskstate,1);
|
||||
wire.emit({type:'slow'});assert.throws(()=>runtime.getPlayerTasks(),/logged-in/);
|
||||
runtime.stop();
|
||||
});
|
||||
|
||||
test('UI observes canonical commits and unsubscribe is idempotent', async () => {
|
||||
const { runtime, wire } = makeRuntime();
|
||||
const seen: unknown[] = [];
|
||||
|
||||
Reference in New Issue
Block a user