From dbc5d19e61337a3c05f06c674efc09376fd36e1b Mon Sep 17 00:00:00 2001 From: Joywayer Date: Sun, 28 Jun 2026 14:27:56 +0800 Subject: [PATCH] =?UTF-8?q?test(framework):=20login=20=E5=85=A8=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E9=9B=86=E6=88=90=E6=B5=8B=E8=AF=95(over=20FakeTransp?= =?UTF-8?q?ort)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 集成测试在断言处调用 parseLoginResponse(any login 数据),规避 TS6 对闭包内赋值变量经 assert.ok 收窄为 never 的 CFA 行为;断言与覆盖范围不变。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../integration/login-flow.test.ts | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 cocoscreator_projects/framework-tests/integration/login-flow.test.ts diff --git a/cocoscreator_projects/framework-tests/integration/login-flow.test.ts b/cocoscreator_projects/framework-tests/integration/login-flow.test.ts new file mode 100644 index 0000000..00bfe63 --- /dev/null +++ b/cocoscreator_projects/framework-tests/integration/login-flow.test.ts @@ -0,0 +1,57 @@ +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(JSON.stringify({ data: '@toconconHELLO' })); + await t.flush(); + + // 客户端应已发出 player_login + assert.equal(JSON.parse(t.sent[0]).rpc, 'player_login'); + + // 服务器回 login 响应(带房间恢复 + 对局) + t.serverPush(JSON.stringify({ data: 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({ data: JSON.stringify({ com: '@serverheartbeat' }) })); + // 正常业务推送(门控已清,放行) + t.serverPush(JSON.stringify({ data: 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(); +});