Merge remote-tracking branch 'origin/master' into issue-94-响应式查询(Reactive_Query_System)/_Event-driven_Query
This commit is contained in:
@@ -13,6 +13,8 @@ import { ServiceContainer } from './Core/ServiceContainer';
|
|||||||
import { PluginManager } from './Core/PluginManager';
|
import { PluginManager } from './Core/PluginManager';
|
||||||
import { IPlugin } from './Core/Plugin';
|
import { IPlugin } from './Core/Plugin';
|
||||||
import { WorldManager } from './ECS/WorldManager';
|
import { WorldManager } from './ECS/WorldManager';
|
||||||
|
import { DebugConfigService } from './Utils/Debug/DebugConfigService';
|
||||||
|
import { createInstance } from './Core/DI/Decorators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 游戏引擎核心类
|
* 游戏引擎核心类
|
||||||
@@ -202,14 +204,15 @@ export class Core {
|
|||||||
|
|
||||||
// 初始化调试管理器
|
// 初始化调试管理器
|
||||||
if (this._config.debugConfig?.enabled) {
|
if (this._config.debugConfig?.enabled) {
|
||||||
// 使用DI容器创建DebugManager(前两个参数从容器解析,config手动传入)
|
const configService = new DebugConfigService();
|
||||||
const config = this._config.debugConfig;
|
configService.setConfig(this._config.debugConfig);
|
||||||
this._debugManager = new DebugManager(
|
this._serviceContainer.registerInstance(DebugConfigService, configService);
|
||||||
this._serviceContainer.resolve(SceneManager),
|
|
||||||
this._serviceContainer.resolve(PerformanceMonitor),
|
this._serviceContainer.registerSingleton(DebugManager, (c) =>
|
||||||
config
|
createInstance(DebugManager, c)
|
||||||
);
|
);
|
||||||
this._serviceContainer.registerInstance(DebugManager, this._debugManager);
|
|
||||||
|
this._debugManager = this._serviceContainer.resolve(DebugManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initialize();
|
this.initialize();
|
||||||
@@ -476,13 +479,15 @@ export class Core {
|
|||||||
if (this._instance._debugManager) {
|
if (this._instance._debugManager) {
|
||||||
this._instance._debugManager.updateConfig(config);
|
this._instance._debugManager.updateConfig(config);
|
||||||
} else {
|
} else {
|
||||||
// 使用DI容器创建DebugManager
|
const configService = new DebugConfigService();
|
||||||
this._instance._debugManager = new DebugManager(
|
configService.setConfig(config);
|
||||||
this._instance._serviceContainer.resolve(SceneManager),
|
this._instance._serviceContainer.registerInstance(DebugConfigService, configService);
|
||||||
this._instance._serviceContainer.resolve(PerformanceMonitor),
|
|
||||||
config
|
this._instance._serviceContainer.registerSingleton(DebugManager, (c) =>
|
||||||
|
createInstance(DebugManager, c)
|
||||||
);
|
);
|
||||||
this._instance._serviceContainer.registerInstance(DebugManager, this._instance._debugManager);
|
|
||||||
|
this._instance._debugManager = this._instance._serviceContainer.resolve(DebugManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新Core配置
|
// 更新Core配置
|
||||||
@@ -659,11 +664,6 @@ export class Core {
|
|||||||
// 更新额外的 WorldManager
|
// 更新额外的 WorldManager
|
||||||
this._worldManager.updateAll();
|
this._worldManager.updateAll();
|
||||||
|
|
||||||
// 更新调试管理器(基于FPS的数据发送)
|
|
||||||
if (this._debugManager) {
|
|
||||||
this._debugManager.onFrameUpdate(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 结束性能监控
|
// 结束性能监控
|
||||||
this._performanceMonitor.endMonitoring('Core.update', frameStartTime);
|
this._performanceMonitor.endMonitoring('Core.update', frameStartTime);
|
||||||
}
|
}
|
||||||
|
|||||||
45
packages/core/src/Utils/Debug/DebugConfigService.ts
Normal file
45
packages/core/src/Utils/Debug/DebugConfigService.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { IECSDebugConfig } from '../../Types';
|
||||||
|
import { Injectable } from '../../Core/DI/Decorators';
|
||||||
|
import type { IService } from '../../Core/ServiceContainer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调试配置服务
|
||||||
|
*
|
||||||
|
* 管理调试系统的配置信息
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class DebugConfigService implements IService {
|
||||||
|
private _config: IECSDebugConfig;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._config = {
|
||||||
|
enabled: false,
|
||||||
|
websocketUrl: '',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public setConfig(config: IECSDebugConfig): void {
|
||||||
|
this._config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getConfig(): IECSDebugConfig {
|
||||||
|
return this._config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isEnabled(): boolean {
|
||||||
|
return this._config.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
// 清理资源
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,17 +10,20 @@ import { ComponentPoolManager } from '../../ECS/Core/ComponentPool';
|
|||||||
import { Pool } from '../../Utils/Pool';
|
import { Pool } from '../../Utils/Pool';
|
||||||
import { getComponentInstanceTypeName, getSystemInstanceTypeName } from '../../ECS/Decorators';
|
import { getComponentInstanceTypeName, getSystemInstanceTypeName } from '../../ECS/Decorators';
|
||||||
import type { IService } from '../../Core/ServiceContainer';
|
import type { IService } from '../../Core/ServiceContainer';
|
||||||
|
import type { IUpdatable } from '../../Types/IUpdatable';
|
||||||
import { SceneManager } from '../../ECS/SceneManager';
|
import { SceneManager } from '../../ECS/SceneManager';
|
||||||
import { PerformanceMonitor } from '../PerformanceMonitor';
|
import { PerformanceMonitor } from '../PerformanceMonitor';
|
||||||
|
import { Injectable, Inject, Updatable } from '../../Core/DI/Decorators';
|
||||||
|
import { DebugConfigService } from './DebugConfigService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调试管理器
|
* 调试管理器
|
||||||
*
|
*
|
||||||
* 整合所有调试数据收集器,负责收集和发送调试数据
|
* 整合所有调试数据收集器,负责收集和发送调试数据
|
||||||
*
|
|
||||||
* 通过构造函数接收SceneManager和PerformanceMonitor,避免直接依赖Core实例
|
|
||||||
*/
|
*/
|
||||||
export class DebugManager implements IService {
|
@Injectable()
|
||||||
|
@Updatable()
|
||||||
|
export class DebugManager implements IService, IUpdatable {
|
||||||
private config: IECSDebugConfig;
|
private config: IECSDebugConfig;
|
||||||
private webSocketManager: WebSocketManager;
|
private webSocketManager: WebSocketManager;
|
||||||
private entityCollector: EntityDataCollector;
|
private entityCollector: EntityDataCollector;
|
||||||
@@ -36,18 +39,12 @@ export class DebugManager implements IService {
|
|||||||
private sendInterval: number;
|
private sendInterval: number;
|
||||||
private isRunning: boolean = false;
|
private isRunning: boolean = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造调试管理器
|
|
||||||
* @param sceneManager 场景管理器
|
|
||||||
* @param performanceMonitor 性能监控器
|
|
||||||
* @param config 调试配置
|
|
||||||
*/
|
|
||||||
constructor(
|
constructor(
|
||||||
sceneManager: SceneManager,
|
@Inject(SceneManager) sceneManager: SceneManager,
|
||||||
performanceMonitor: PerformanceMonitor,
|
@Inject(PerformanceMonitor) performanceMonitor: PerformanceMonitor,
|
||||||
config: IECSDebugConfig
|
@Inject(DebugConfigService) configService: DebugConfigService
|
||||||
) {
|
) {
|
||||||
this.config = config;
|
this.config = configService.getConfig();
|
||||||
this.sceneManager = sceneManager;
|
this.sceneManager = sceneManager;
|
||||||
this.performanceMonitor = performanceMonitor;
|
this.performanceMonitor = performanceMonitor;
|
||||||
|
|
||||||
@@ -60,15 +57,15 @@ export class DebugManager implements IService {
|
|||||||
|
|
||||||
// 初始化WebSocket管理器
|
// 初始化WebSocket管理器
|
||||||
this.webSocketManager = new WebSocketManager(
|
this.webSocketManager = new WebSocketManager(
|
||||||
config.websocketUrl,
|
this.config.websocketUrl,
|
||||||
config.autoReconnect !== false
|
this.config.autoReconnect !== false
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置消息处理回调
|
// 设置消息处理回调
|
||||||
this.webSocketManager.setMessageHandler(this.handleMessage.bind(this));
|
this.webSocketManager.setMessageHandler(this.handleMessage.bind(this));
|
||||||
|
|
||||||
// 计算发送间隔(基于帧率)
|
// 计算发送间隔(基于帧率)
|
||||||
const debugFrameRate = config.debugFrameRate || 30;
|
const debugFrameRate = this.config.debugFrameRate || 30;
|
||||||
this.sendInterval = 1000 / debugFrameRate;
|
this.sendInterval = 1000 / debugFrameRate;
|
||||||
|
|
||||||
this.start();
|
this.start();
|
||||||
@@ -116,16 +113,12 @@ export class DebugManager implements IService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public update(deltaTime?: number): void {
|
||||||
* 帧更新回调
|
|
||||||
*/
|
|
||||||
public onFrameUpdate(deltaTime: number): void {
|
|
||||||
if (!this.isRunning || !this.config.enabled) return;
|
if (!this.isRunning || !this.config.enabled) return;
|
||||||
|
|
||||||
this.frameCounter++;
|
this.frameCounter++;
|
||||||
const currentTime = Date.now();
|
const currentTime = Date.now();
|
||||||
|
|
||||||
// 基于配置的帧率发送数据
|
|
||||||
if (currentTime - this.lastSendTime >= this.sendInterval) {
|
if (currentTime - this.lastSendTime >= this.sendInterval) {
|
||||||
this.sendDebugData();
|
this.sendDebugData();
|
||||||
this.lastSendTime = currentTime;
|
this.lastSendTime = currentTime;
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ export { PerformanceDataCollector } from './PerformanceDataCollector';
|
|||||||
export { ComponentDataCollector } from './ComponentDataCollector';
|
export { ComponentDataCollector } from './ComponentDataCollector';
|
||||||
export { SceneDataCollector } from './SceneDataCollector';
|
export { SceneDataCollector } from './SceneDataCollector';
|
||||||
export { WebSocketManager } from './WebSocketManager';
|
export { WebSocketManager } from './WebSocketManager';
|
||||||
export { DebugManager } from './DebugManager';
|
export { DebugManager } from './DebugManager';
|
||||||
|
export { DebugConfigService } from './DebugConfigService';
|
||||||
668
packages/core/tests/DebugManager.test.ts
Normal file
668
packages/core/tests/DebugManager.test.ts
Normal file
@@ -0,0 +1,668 @@
|
|||||||
|
import { Core } from '../src/Core';
|
||||||
|
import { Scene } from '../src/ECS/Scene';
|
||||||
|
import { DebugManager } from '../src/Utils/Debug/DebugManager';
|
||||||
|
import { DebugConfigService } from '../src/Utils/Debug/DebugConfigService';
|
||||||
|
import { IECSDebugConfig } from '../src/Types';
|
||||||
|
import { createLogger } from '../src/Utils/Logger';
|
||||||
|
|
||||||
|
const logger = createLogger('DebugManagerTest');
|
||||||
|
|
||||||
|
class TestScene extends Scene {
|
||||||
|
public initializeCalled = false;
|
||||||
|
|
||||||
|
public override initialize(): void {
|
||||||
|
this.initializeCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override begin(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
public override end(): void {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('DebugManager DI Architecture Tests', () => {
|
||||||
|
let originalConsoleWarn: typeof console.warn;
|
||||||
|
let originalConsoleError: typeof console.error;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
(Core as any)._instance = null;
|
||||||
|
originalConsoleWarn = console.warn;
|
||||||
|
originalConsoleError = console.error;
|
||||||
|
console.warn = jest.fn();
|
||||||
|
console.error = jest.fn();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
console.warn = originalConsoleWarn;
|
||||||
|
console.error = originalConsoleError;
|
||||||
|
if (Core.Instance) {
|
||||||
|
Core.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DebugConfigService - Configuration Service', () => {
|
||||||
|
test('should create with default configuration', () => {
|
||||||
|
const configService = new DebugConfigService();
|
||||||
|
const config = configService.getConfig();
|
||||||
|
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
expect(config.enabled).toBe(false);
|
||||||
|
expect(config.websocketUrl).toBe('');
|
||||||
|
expect(config.debugFrameRate).toBe(30);
|
||||||
|
expect(config.autoReconnect).toBe(true);
|
||||||
|
expect(config.channels).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should set and get configuration', () => {
|
||||||
|
const configService = new DebugConfigService();
|
||||||
|
const newConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 60,
|
||||||
|
autoReconnect: false,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
configService.setConfig(newConfig);
|
||||||
|
const retrievedConfig = configService.getConfig();
|
||||||
|
|
||||||
|
expect(retrievedConfig).toEqual(newConfig);
|
||||||
|
expect(retrievedConfig.enabled).toBe(true);
|
||||||
|
expect(retrievedConfig.websocketUrl).toBe('ws://localhost:9229');
|
||||||
|
expect(retrievedConfig.debugFrameRate).toBe(60);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct enabled status', () => {
|
||||||
|
const configService = new DebugConfigService();
|
||||||
|
expect(configService.isEnabled()).toBe(false);
|
||||||
|
|
||||||
|
configService.setConfig({
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(configService.isEnabled()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should implement dispose method', () => {
|
||||||
|
const configService = new DebugConfigService();
|
||||||
|
expect(() => configService.dispose()).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DebugManager - DI Initialization', () => {
|
||||||
|
test('should initialize DebugManager through DI when debug config is enabled', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const core = Core.create({
|
||||||
|
debug: true,
|
||||||
|
debugConfig: debugConfig
|
||||||
|
});
|
||||||
|
|
||||||
|
expect((core as any)._debugManager).toBeDefined();
|
||||||
|
expect((core as any)._debugManager).toBeInstanceOf(DebugManager);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not create DebugManager when debug config is disabled', () => {
|
||||||
|
const core = Core.create({
|
||||||
|
debug: true,
|
||||||
|
debugConfig: {
|
||||||
|
enabled: false,
|
||||||
|
websocketUrl: '',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect((core as any)._debugManager).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not create DebugManager when no debug config provided', () => {
|
||||||
|
const core = Core.create({ debug: true });
|
||||||
|
expect((core as any)._debugManager).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should register DebugConfigService in ServiceContainer', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({
|
||||||
|
debug: true,
|
||||||
|
debugConfig: debugConfig
|
||||||
|
});
|
||||||
|
|
||||||
|
const configService = Core.services.resolve(DebugConfigService);
|
||||||
|
expect(configService).toBeDefined();
|
||||||
|
expect(configService).toBeInstanceOf(DebugConfigService);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should inject all dependencies correctly', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const core = Core.create({
|
||||||
|
debug: true,
|
||||||
|
debugConfig: debugConfig
|
||||||
|
});
|
||||||
|
|
||||||
|
const debugManager = (core as any)._debugManager as DebugManager;
|
||||||
|
expect(debugManager).toBeDefined();
|
||||||
|
|
||||||
|
const sceneManager = (debugManager as any).sceneManager;
|
||||||
|
const performanceMonitor = (debugManager as any).performanceMonitor;
|
||||||
|
const config = (debugManager as any).config;
|
||||||
|
|
||||||
|
expect(sceneManager).toBeDefined();
|
||||||
|
expect(performanceMonitor).toBeDefined();
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
expect(config.enabled).toBe(true);
|
||||||
|
expect(config.websocketUrl).toBe('ws://localhost:9229');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Core.enableDebug - Runtime Activation', () => {
|
||||||
|
test('should enable debug at runtime', () => {
|
||||||
|
const core = Core.create({ debug: true });
|
||||||
|
expect(Core.isDebugEnabled).toBe(false);
|
||||||
|
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.enableDebug(debugConfig);
|
||||||
|
|
||||||
|
expect(Core.isDebugEnabled).toBe(true);
|
||||||
|
expect((core as any)._debugManager).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should create DebugConfigService when enabling debug at runtime', () => {
|
||||||
|
Core.create({ debug: true });
|
||||||
|
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.enableDebug(debugConfig);
|
||||||
|
|
||||||
|
const configService = Core.services.resolve(DebugConfigService);
|
||||||
|
expect(configService).toBeDefined();
|
||||||
|
expect(configService.getConfig()).toEqual(debugConfig);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should update existing DebugManager config when already enabled', () => {
|
||||||
|
const initialConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({ debug: true, debugConfig: initialConfig });
|
||||||
|
|
||||||
|
const updatedConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:8080',
|
||||||
|
debugFrameRate: 60,
|
||||||
|
autoReconnect: false,
|
||||||
|
channels: {
|
||||||
|
entities: false,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: false,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.enableDebug(updatedConfig);
|
||||||
|
|
||||||
|
expect(Core.isDebugEnabled).toBe(true);
|
||||||
|
const debugManager = (Core.Instance as any)._debugManager;
|
||||||
|
expect(debugManager).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should show warning when enabling debug without Core instance', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.enableDebug(debugConfig);
|
||||||
|
|
||||||
|
expect(console.warn).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining('Core实例未创建,请先调用Core.create()')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Core.disableDebug', () => {
|
||||||
|
test('should disable debug functionality', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
expect(Core.isDebugEnabled).toBe(true);
|
||||||
|
|
||||||
|
Core.disableDebug();
|
||||||
|
|
||||||
|
expect(Core.isDebugEnabled).toBe(false);
|
||||||
|
expect((Core.Instance as any)._debugManager).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle disabling when Core instance does not exist', () => {
|
||||||
|
expect(() => Core.disableDebug()).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle disabling when debug was never enabled', () => {
|
||||||
|
Core.create({ debug: true });
|
||||||
|
expect(() => Core.disableDebug()).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DebugManager - Auto Update Integration', () => {
|
||||||
|
test('should be registered as updatable service', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
|
||||||
|
const serviceContainer = (Core.Instance as any)._serviceContainer;
|
||||||
|
const updatableCount = serviceContainer.getUpdatableCount();
|
||||||
|
|
||||||
|
expect(updatableCount).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should be updated during Core.update cycle', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const core = Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
const debugManager = (core as any)._debugManager as DebugManager;
|
||||||
|
const updateSpy = jest.spyOn(debugManager, 'update');
|
||||||
|
|
||||||
|
Core.update(0.016);
|
||||||
|
|
||||||
|
expect(updateSpy).toHaveBeenCalledWith(0.016);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DebugManager - Scene Integration', () => {
|
||||||
|
test('should respond to scene changes', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const core = Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
const debugManager = (core as any)._debugManager as DebugManager;
|
||||||
|
const sceneChangeSpy = jest.spyOn(debugManager, 'onSceneChanged');
|
||||||
|
|
||||||
|
const testScene = new TestScene();
|
||||||
|
Core.setScene(testScene);
|
||||||
|
|
||||||
|
expect(sceneChangeSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should collect debug data from current scene', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
const testScene = new TestScene();
|
||||||
|
Core.setScene(testScene);
|
||||||
|
|
||||||
|
const debugData = Core.getDebugData();
|
||||||
|
|
||||||
|
expect(debugData).toBeDefined();
|
||||||
|
expect(debugData).toHaveProperty('timestamp');
|
||||||
|
expect(debugData).toHaveProperty('frameworkVersion');
|
||||||
|
expect(debugData).toHaveProperty('currentScene');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DebugManager - Configuration Management', () => {
|
||||||
|
test('should use correct debug frame rate', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 60,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const core = Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
const debugManager = (core as any)._debugManager as DebugManager;
|
||||||
|
const sendInterval = (debugManager as any).sendInterval;
|
||||||
|
|
||||||
|
expect(sendInterval).toBe(1000 / 60);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle channel configuration correctly', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: false,
|
||||||
|
performance: false,
|
||||||
|
components: true,
|
||||||
|
scenes: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
const testScene = new TestScene();
|
||||||
|
Core.setScene(testScene);
|
||||||
|
|
||||||
|
const debugData = Core.getDebugData() as any;
|
||||||
|
|
||||||
|
expect(debugData.entities).toBeDefined();
|
||||||
|
expect(debugData.components).toBeDefined();
|
||||||
|
expect(debugData.systems).toBeUndefined();
|
||||||
|
expect(debugData.performance).toBeUndefined();
|
||||||
|
expect(debugData.scenes).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DebugManager - Lifecycle', () => {
|
||||||
|
test('should start automatically on creation', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const core = Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
const debugManager = (core as any)._debugManager as DebugManager;
|
||||||
|
const isRunning = (debugManager as any).isRunning;
|
||||||
|
|
||||||
|
expect(isRunning).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should stop when disabling debug', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
const debugManager = (Core.Instance as any)._debugManager as DebugManager;
|
||||||
|
const stopSpy = jest.spyOn(debugManager, 'stop');
|
||||||
|
|
||||||
|
Core.disableDebug();
|
||||||
|
|
||||||
|
expect(stopSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should dispose properly on Core.destroy', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
const debugManager = (Core.Instance as any)._debugManager as DebugManager;
|
||||||
|
const stopSpy = jest.spyOn(debugManager, 'stop');
|
||||||
|
|
||||||
|
Core.destroy();
|
||||||
|
|
||||||
|
expect(stopSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DebugManager - Pure DI Architecture Validation', () => {
|
||||||
|
test('should resolve all dependencies through ServiceContainer', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
|
||||||
|
const debugConfigService = Core.services.resolve(DebugConfigService);
|
||||||
|
expect(debugConfigService).toBeDefined();
|
||||||
|
|
||||||
|
const config = debugConfigService.getConfig();
|
||||||
|
expect(config).toEqual(debugConfig);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not have mixed DI patterns', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const core = Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
const debugManager = (core as any)._debugManager as DebugManager;
|
||||||
|
|
||||||
|
const sceneManager = (debugManager as any).sceneManager;
|
||||||
|
const performanceMonitor = (debugManager as any).performanceMonitor;
|
||||||
|
const config = (debugManager as any).config;
|
||||||
|
|
||||||
|
expect(sceneManager).toBeDefined();
|
||||||
|
expect(performanceMonitor).toBeDefined();
|
||||||
|
expect(config).toBeDefined();
|
||||||
|
expect(config.enabled).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should use factory pattern for registration', () => {
|
||||||
|
const debugConfig: IECSDebugConfig = {
|
||||||
|
enabled: true,
|
||||||
|
websocketUrl: 'ws://localhost:9229',
|
||||||
|
debugFrameRate: 30,
|
||||||
|
autoReconnect: true,
|
||||||
|
channels: {
|
||||||
|
entities: true,
|
||||||
|
systems: true,
|
||||||
|
performance: true,
|
||||||
|
components: true,
|
||||||
|
scenes: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.create({ debug: true, debugConfig: debugConfig });
|
||||||
|
|
||||||
|
const debugManager1 = (Core.Instance as any)._debugManager;
|
||||||
|
const debugManager2 = Core.services.resolve(DebugManager);
|
||||||
|
|
||||||
|
expect(debugManager1).toBe(debugManager2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user