Files
esengine/packages/editor-core/tests/EditorPluginManager.test.ts
2025-10-14 22:33:55 +08:00

269 lines
8.5 KiB
TypeScript

import { Core } from '@esengine/ecs-framework';
import {
EditorPluginManager,
UIRegistry,
MessageHub,
SerializerRegistry,
EditorPluginCategory,
PanelPosition
} from '../src';
import type { IEditorPlugin, ISerializer } from '../src';
class TestSerializer implements ISerializer<string> {
serialize(data: string): Uint8Array {
const encoder = new TextEncoder();
return encoder.encode(data);
}
deserialize(data: Uint8Array): string {
const decoder = new TextDecoder();
return decoder.decode(data);
}
getSupportedType(): string {
return 'string';
}
}
class TestEditorPlugin implements IEditorPlugin {
readonly name = 'test-editor-plugin';
readonly version = '1.0.0';
readonly displayName = 'Test Editor Plugin';
readonly category = EditorPluginCategory.Tool;
readonly description = 'A test plugin for editor';
async install(): Promise<void> {
// 测试安装
}
async uninstall(): Promise<void> {
// 测试卸载
}
registerMenuItems() {
return [
{
id: 'test-menu',
label: 'Test Menu',
onClick: () => {}
}
];
}
registerToolbar() {
return [
{
id: 'test-toolbar',
label: 'Test Toolbar',
groupId: 'test-group',
onClick: () => {}
}
];
}
registerPanels() {
return [
{
id: 'test-panel',
title: 'Test Panel',
position: PanelPosition.Left
}
];
}
getSerializers() {
return [new TestSerializer()];
}
}
describe('EditorPluginManager', () => {
let core: Core;
let pluginManager: EditorPluginManager;
let uiRegistry: UIRegistry;
let messageHub: MessageHub;
let serializerRegistry: SerializerRegistry;
beforeEach(() => {
core = Core.create({ debug: false });
uiRegistry = new UIRegistry();
messageHub = new MessageHub();
serializerRegistry = new SerializerRegistry();
Core.services.registerInstance(UIRegistry, uiRegistry);
Core.services.registerInstance(MessageHub, messageHub);
Core.services.registerInstance(SerializerRegistry, serializerRegistry);
pluginManager = new EditorPluginManager();
pluginManager.initialize(core, Core.services);
});
afterEach(() => {
pluginManager.dispose();
Core.destroy();
});
describe('基本功能', () => {
it('应该能够安装编辑器插件', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
expect(pluginManager.isInstalled(plugin.name)).toBe(true);
expect(pluginManager.getEditorPlugin(plugin.name)).toBe(plugin);
});
it('应该能够卸载编辑器插件', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
await pluginManager.uninstallEditor(plugin.name);
expect(pluginManager.isInstalled(plugin.name)).toBe(false);
expect(pluginManager.getEditorPlugin(plugin.name)).toBeUndefined();
});
it('应该能够获取插件元数据', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
const metadata = pluginManager.getPluginMetadata(plugin.name);
expect(metadata).toBeDefined();
expect(metadata?.name).toBe(plugin.name);
expect(metadata?.displayName).toBe(plugin.displayName);
expect(metadata?.category).toBe(plugin.category);
expect(metadata?.enabled).toBe(true);
});
});
describe('UI 注册', () => {
it('应该注册菜单项', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
const menu = uiRegistry.getMenu('test-menu');
expect(menu).toBeDefined();
expect(menu?.label).toBe('Test Menu');
});
it('应该注册工具栏项', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
const toolbar = uiRegistry.getToolbarItem('test-toolbar');
expect(toolbar).toBeDefined();
expect(toolbar?.label).toBe('Test Toolbar');
});
it('应该注册面板', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
const panel = uiRegistry.getPanel('test-panel');
expect(panel).toBeDefined();
expect(panel?.title).toBe('Test Panel');
});
it('卸载插件时应该注销 UI 元素', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
await pluginManager.uninstallEditor(plugin.name);
expect(uiRegistry.getMenu('test-menu')).toBeUndefined();
expect(uiRegistry.getToolbarItem('test-toolbar')).toBeUndefined();
expect(uiRegistry.getPanel('test-panel')).toBeUndefined();
});
});
describe('序列化器注册', () => {
it('应该注册序列化器', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
expect(serializerRegistry.has(plugin.name, 'string')).toBe(true);
});
it('应该能够使用序列化器', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
const testData = 'Hello World';
const serialized = serializerRegistry.serialize(plugin.name, 'string', testData);
const deserialized = serializerRegistry.deserialize(plugin.name, 'string', serialized);
expect(deserialized).toBe(testData);
});
it('卸载插件时应该注销序列化器', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
await pluginManager.uninstallEditor(plugin.name);
expect(serializerRegistry.has(plugin.name, 'string')).toBe(false);
});
});
describe('事件通知', () => {
it('应该发送插件安装事件', async () => {
let eventReceived = false;
messageHub.subscribe('plugin:installed', (data: any) => {
eventReceived = true;
expect(data.name).toBe('test-editor-plugin');
});
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
expect(eventReceived).toBe(true);
});
it('应该发送项目打开事件', async () => {
let eventReceived = false;
messageHub.subscribe('project:opened', (data: any) => {
eventReceived = true;
expect(data.path).toBe('/test/project');
});
await pluginManager.notifyProjectOpen('/test/project');
expect(eventReceived).toBe(true);
});
it('应该发送项目关闭事件', async () => {
let eventReceived = false;
messageHub.subscribe('project:closed', () => {
eventReceived = true;
});
await pluginManager.notifyProjectClose();
expect(eventReceived).toBe(true);
});
});
describe('插件管理', () => {
it('应该能够按类别获取插件', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
const plugins = pluginManager.getPluginsByCategory(EditorPluginCategory.Tool);
expect(plugins.length).toBe(1);
expect(plugins[0]).toBe(plugin);
});
it('应该能够启用/禁用插件', async () => {
const plugin = new TestEditorPlugin();
await pluginManager.installEditor(plugin);
await pluginManager.disablePlugin(plugin.name);
let metadata = pluginManager.getPluginMetadata(plugin.name);
expect(metadata?.enabled).toBe(false);
await pluginManager.enablePlugin(plugin.name);
metadata = pluginManager.getPluginMetadata(plugin.name);
expect(metadata?.enabled).toBe(true);
});
});
});