真机联调发现:服务器实发单层 {app,route,rpc,data};旧客户端的'外层 data'是浏览器
MessageEvent(00_minhttp.js:266 ws.onmessage=config.onmessage),非协议层。框架传输层
已取 ev.data,decodeFrame 不应再剥一层。修正后 kick_server 等业务包能正确解析。
- decodeFrame 单层化 + 测试改单层帧
- 更正 docs/protocol/01 §3.2(双层→单层,附 MessageEvent 依据)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
58 lines
2.3 KiB
TypeScript
58 lines
2.3 KiB
TypeScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { NetClient } from '../../YouleNexus/assets/framework/net/net-client.ts';
|
|
import { FakeTransport } from '../helpers/fake-transport.ts';
|
|
import { parseLoginResponse } from '../../YouleNexus/assets/framework/protocol/login.ts';
|
|
import type { Clock } from '../../YouleNexus/assets/framework/net/heartbeat.ts';
|
|
|
|
const realishClock: Clock = { setTimeout: (fn, ms) => setTimeout(fn, ms), clearTimeout: (h: any) => clearTimeout(h) };
|
|
const IDENTITY = { agentid: 1, gameid: 2, openid: 'o', nickname: 'n', avatar: 'a', sex: 0, province: '', city: '', unionid: 'u', version: '1', channelid: 0, marketid: 0 };
|
|
|
|
test('login 全流程:握手→登录→业务包,且 parseLoginResponse 识别房间恢复', async () => {
|
|
const t = new FakeTransport();
|
|
const client = new NetClient({ servers: 'ws://srv', transportFactory: () => t, clock: realishClock });
|
|
client.setIdentity(IDENTITY);
|
|
|
|
let loginData: any = null;
|
|
const business: any[] = [];
|
|
client.on('login', (d: any) => { loginData = d; });
|
|
client.on('message', (m: any) => business.push(m));
|
|
|
|
client.start();
|
|
await t.flush();
|
|
|
|
// 服务器先发握手包(原始串,应被忽略)
|
|
t.serverPush('@toconconHELLO');
|
|
await t.flush();
|
|
|
|
// 客户端应已发出 player_login
|
|
assert.equal(JSON.parse(t.sent[0]).rpc, 'player_login');
|
|
|
|
// 服务器回 login 响应(单层,带房间恢复 + 对局)
|
|
t.serverPush(JSON.stringify({
|
|
route: 'agent', rpc: 'player_login',
|
|
data: { state: 0, playerid: 42, bean: 500, roomcode: 'ROOM1', isbattle: 1, deskinfo: { round: 3 } },
|
|
}));
|
|
await t.flush();
|
|
|
|
assert.ok(loginData);
|
|
const parsed = parseLoginResponse(loginData);
|
|
assert.equal(parsed.ok, true);
|
|
assert.equal(parsed.playerid, 42);
|
|
assert.equal(parsed.inRoom, true);
|
|
assert.equal(parsed.hasBattle, true);
|
|
assert.deepEqual(parsed.deskinfo, { round: 3 });
|
|
|
|
// 心跳包(单层,忽略,不进 business)
|
|
t.serverPush(JSON.stringify({ com: '@serverheartbeat' }));
|
|
// 正常业务推送(单层,门控已清,放行)
|
|
t.serverPush(JSON.stringify({ route: 'room', rpc: 'other_join_room', data: { seat: 2 } }));
|
|
await t.flush();
|
|
|
|
assert.equal(business.length, 1);
|
|
assert.equal(business[0].rpc, 'other_join_room');
|
|
assert.equal(business[0].data.seat, 2);
|
|
|
|
client.stop();
|
|
});
|