Files
joywayerandClaude Opus 5 77be6c0d19 feat(framework): AppStore + PlatformSession(登录接入)
AppStore(=旧 GameData 子集): setIdentity/setServers/setPhase/applyLogin
- applyLogin 区分两类字段语义:
  * 身份字段(agentid/channelid/agentmode/gameversion)缺省保留旧值
  * 显示字段(agentname)缺省重置为空字符串
- phase 仅由 session 驱动,applyLogin 不写 phase

PlatformSession: 订阅 NetClient 事件总线 → 扇出到三 Store
- 'open' → phase=connected
- 'login'(state==0) → 三 Store 填充 + phase=loggedIn
- 'login'(state!=0) → phase=loginFailed, 不污染 playerid/roomcode
- 'reconnecting' → phase=reconnecting
- 'slow' → phase=slow
- 'kicked' → phase=kicked

110/110 tests pass, typecheck exit 0。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 19:46:14 +08:00

74 lines
3.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { EventBus } from '../../YouleNexus/assets/framework/core/events.ts';
import { PlatformSession } from '../../YouleNexus/assets/framework/platform/session.ts';
import type { NetClientEvents } from '../../YouleNexus/assets/framework/net/net-client.ts';
// 真实联调实测的 login 响应(取自 plan Task 12 fixture)
const REAL_LOGIN = {
state: 0, playerid: 430511, agentid: 'veRa0qrBf', channelid: 'FtJf073aa',
nickname: '测试号', avatar: 'http://a', openid: 'o1', sex: 0, unionid: 'test_unionid',
roomcard: 3, bean: 0, score: 0, invitecode: null, advanced: 0, taskstate: 1, ip: '127.0.0.1',
bankpower: 1, bank: 0, sign: null, tel: null, initCard: '3', initBean: '0', bankpwd: 0,
agentname: '进贤', agentmode: 2, gameversion: 41,
} as any;
test('login(真实响应): 三 Store 填充 + phase=loggedIn', () => {
const bus = new EventBus<NetClientEvents>();
const session = new PlatformSession(bus);
bus.emit('login', REAL_LOGIN);
assert.equal(session.player.state.value.playerid, 430511);
assert.equal(session.player.state.value.nickname, '测试号');
assert.equal(session.player.state.value.roomcard, 3);
assert.equal(session.app.state.value.agentname, '进贤');
assert.equal(session.app.state.value.gameversion, 41);
assert.equal(session.app.state.value.phase, 'loggedIn');
assert.equal(session.room.state.value.inRoom, false); // 无 roomcode
});
test('login 含 roomcode: room.inRoom=true + deskinfo 透传', () => {
const bus = new EventBus<NetClientEvents>();
const session = new PlatformSession(bus);
const deskinfo = { round: 3 };
bus.emit('login', { ...REAL_LOGIN, roomcode: 'ROOM1', isbattle: 1, seat: 2, deskinfo });
assert.equal(session.room.state.value.inRoom, true);
assert.equal(session.room.state.value.roomcode, 'ROOM1');
assert.equal(session.room.state.value.isbattle, 1);
assert.equal(session.room.state.value.seat, 2);
assert.equal(session.room.state.value.deskinfo, deskinfo, 'deskinfo 引用相等(不深拷贝)');
});
test('login 失败(state!=0): phase=loginFailed, 三 Store 不填充敏感字段', () => {
const bus = new EventBus<NetClientEvents>();
const session = new PlatformSession(bus);
bus.emit('login', { state: 1, playerid: -1 });
assert.equal(session.app.state.value.phase, 'loginFailed');
assert.equal(session.player.state.value.playerid, 0, '失败时 playerid 走初始,不写入 -1');
assert.equal(session.room.state.value.inRoom, false);
});
test('open/reconnecting/slow/kicked 驱动 phase 流转', () => {
const bus = new EventBus<NetClientEvents>();
const session = new PlatformSession(bus);
bus.emit('open');
assert.equal(session.app.state.value.phase, 'connected');
bus.emit('reconnecting', 'ws://x');
assert.equal(session.app.state.value.phase, 'reconnecting');
bus.emit('slow');
assert.equal(session.app.state.value.phase, 'slow');
bus.emit('kicked', { msg: 'x' });
assert.equal(session.app.state.value.phase, 'kicked');
});
test('session: 二次 login 应清空旧 room 状态再填充', () => {
const bus = new EventBus<NetClientEvents>();
const session = new PlatformSession(bus);
bus.emit('login', { ...REAL_LOGIN, roomcode: 'ROOM1', seat: 1 });
assert.equal(session.room.state.value.inRoom, true);
bus.emit('login', REAL_LOGIN); // 第二次无 roomcode
assert.equal(session.room.state.value.inRoom, false, '无 roomcode → room.clear()');
assert.equal(session.room.state.value.roomcode, null);
});