133 lines
4.6 KiB
TypeScript
133 lines
4.6 KiB
TypeScript
import { remoteFixture } from '../fixtures/remote-config.ts';
|
|
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { StartupOrchestrator } from '../../YouleNexus/assets/framework/platform/startup.ts';
|
|
import { PlatformSession } from '../../YouleNexus/assets/framework/platform/session.ts';
|
|
import { EventBus } from '../../YouleNexus/assets/framework/core/events.ts';
|
|
import type { NetClientEvents } from '../../YouleNexus/assets/framework/net/net-client.ts';
|
|
import type { BootstrapResult } from '../../YouleNexus/assets/framework/config/bootstrap.ts';
|
|
|
|
const IDENTITY = { agentid: 'A', channelid: 'C', gameid: 'G', marketid: 4, version: 10000 };
|
|
|
|
function bootstrapOf(): BootstrapResult {
|
|
return {
|
|
mode: 'debug', isDebugger: true,
|
|
identity: IDENTITY,
|
|
servers: ['ws://test'],
|
|
...remoteFixture(),
|
|
profile: { name: 'debug' },
|
|
};
|
|
}
|
|
|
|
test('StartupOrchestrator: 启动流程 bootstrap → onLogin → ready', async () => {
|
|
const bus = new EventBus<NetClientEvents>();
|
|
const session = new PlatformSession(bus);
|
|
let startedRoomBus = false;
|
|
|
|
const orch = new StartupOrchestrator({
|
|
session,
|
|
bus,
|
|
getBootstrapResult: async () => bootstrapOf(),
|
|
makeNetClient: () => ({ bus }) as any,
|
|
identity: IDENTITY,
|
|
roomBusFactory: () => ({
|
|
start() { startedRoomBus = true; },
|
|
stop() { startedRoomBus = false; },
|
|
} as any),
|
|
});
|
|
|
|
await orch.bootstrap();
|
|
assert.equal(orch.bootstrapResult?.servers[0], 'ws://test');
|
|
assert.equal(session.app.state.value.servers[0], 'ws://test', 'servers 应写入 AppStore');
|
|
assert.equal(session.app.state.value.identity?.agentid, 'A', 'identity 应写入 AppStore');
|
|
|
|
// 模拟 NetClient 发出 login 事件(让 session 把 phase 推到 loggedIn)
|
|
bus.emit('login', { state: 0, playerid: 100, nickname: '甲', agentid: 'A', channelid: 'C' } as any);
|
|
|
|
await orch.onLogin();
|
|
assert.equal(session.app.state.value.phase, 'loggedIn');
|
|
assert.equal(startedRoomBus, true, 'RoomRPCBus 应已 start');
|
|
assert.equal(orch.isReady(), true);
|
|
|
|
await orch.waitForReady();
|
|
});
|
|
|
|
test('StartupOrchestrator: bootstrap 失败显式抛错', async () => {
|
|
const bus = new EventBus<NetClientEvents>();
|
|
const session = new PlatformSession(bus);
|
|
const orch = new StartupOrchestrator({
|
|
session,
|
|
bus,
|
|
getBootstrapResult: async () => { throw new Error('远程配置抓取失败'); },
|
|
makeNetClient: () => ({} as any),
|
|
identity: IDENTITY,
|
|
roomBusFactory: () => ({ start() {}, stop() {} } as any),
|
|
});
|
|
await assert.rejects(() => orch.bootstrap(), /远程配置抓取失败/);
|
|
assert.equal(orch.bootstrapResult, null, 'bootstrap 失败时不写入 result');
|
|
});
|
|
|
|
test('StartupOrchestrator: waitForReady 在 ready 之前不 resolve', async () => {
|
|
const bus = new EventBus<NetClientEvents>();
|
|
const session = new PlatformSession(bus);
|
|
const orch = new StartupOrchestrator({
|
|
session,
|
|
bus,
|
|
getBootstrapResult: async () => bootstrapOf(),
|
|
makeNetClient: () => ({}) as any,
|
|
identity: IDENTITY,
|
|
roomBusFactory: () => ({ start() {}, stop() {} } as any),
|
|
});
|
|
|
|
let resolved = false;
|
|
const p = orch.waitForReady().then(() => { resolved = true; });
|
|
await new Promise((r) => setImmediate(r));
|
|
assert.equal(resolved, false, 'ready 之前不应 resolve');
|
|
|
|
await orch.onLogin();
|
|
await p;
|
|
assert.equal(resolved, true);
|
|
});
|
|
|
|
test('StartupOrchestrator: shutdown 停止 RoomRPCBus', async () => {
|
|
const bus = new EventBus<NetClientEvents>();
|
|
const session = new PlatformSession(bus);
|
|
let stopped = false;
|
|
const orch = new StartupOrchestrator({
|
|
session,
|
|
bus,
|
|
getBootstrapResult: async () => bootstrapOf(),
|
|
makeNetClient: () => ({}) as any,
|
|
identity: IDENTITY,
|
|
roomBusFactory: () => ({
|
|
start() {},
|
|
stop() { stopped = true; },
|
|
} as any),
|
|
});
|
|
|
|
await orch.bootstrap();
|
|
await orch.onLogin();
|
|
orch.shutdown();
|
|
assert.equal(stopped, true);
|
|
});
|
|
|
|
test('StartupOrchestrator: bootstrap 可独立调用(不依赖 onLogin)', async () => {
|
|
const bus = new EventBus<NetClientEvents>();
|
|
const session = new PlatformSession(bus);
|
|
const orch = new StartupOrchestrator({
|
|
session,
|
|
bus,
|
|
getBootstrapResult: async () => bootstrapOf(),
|
|
makeNetClient: () => ({}) as any,
|
|
identity: IDENTITY,
|
|
roomBusFactory: () => ({ start() {}, stop() {} } as any),
|
|
});
|
|
|
|
await orch.bootstrap();
|
|
// waitForReady 还未 resolve(未调 onLogin)
|
|
const ready = orch.waitForReady();
|
|
let resolved = false;
|
|
ready.then(() => { resolved = true; });
|
|
await new Promise((r) => setImmediate(r));
|
|
assert.equal(resolved, false, '仅 bootstrap 不足以触发 ready');
|
|
}); |