Skip to content

Commit 4068933

Browse files
test: improve PluginManager coverage (#50)
1 parent 6bf83a6 commit 4068933

File tree

1 file changed

+55
-1
lines changed

1 file changed

+55
-1
lines changed

test/plugins/plugin-manager.spec.ts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,19 @@ describe('PluginManager', () => {
135135
metadata: { name: 'test', version: '1.0.0' },
136136
install: jest.fn()
137137
} as any;
138-
138+
139139
await expect(pluginManager.installPlugin(plugin))
140140
.rejects.toThrow('Plugin must implement uninstall method');
141141
});
142+
143+
it('should fail when required dependencies are missing', async () => {
144+
const plugin = createMockPlugin('dep-plugin');
145+
plugin.metadata.dependencies = { 'non-existent-package': '1.0.0' };
146+
147+
await expect(pluginManager.installPlugin(plugin))
148+
.rejects.toThrow('Dependency [email protected] not found');
149+
expect(plugin.install).not.toHaveBeenCalled();
150+
});
142151
});
143152

144153
describe('Plugin Uninstallation', () => {
@@ -159,6 +168,15 @@ describe('PluginManager', () => {
159168
await expect(pluginManager.uninstallPlugin('inexistent-plugin'))
160169
.rejects.toThrow('Plugin inexistent-plugin not found');
161170
});
171+
172+
it('should handle errors during plugin uninstallation', async () => {
173+
const plugin = createMockPlugin('test-plugin');
174+
plugin.uninstall = jest.fn().mockRejectedValue(new Error('Uninstall error'));
175+
await pluginManager.installPlugin(plugin);
176+
177+
await expect(pluginManager.uninstallPlugin('test-plugin'))
178+
.rejects.toThrow('Uninstall error');
179+
});
162180
});
163181

164182
describe('Plugin Enable/Disable', () => {
@@ -301,6 +319,23 @@ describe('PluginManager', () => {
301319
expect(results[1].success).toBe(true);
302320
expect(successHook).toHaveBeenCalled();
303321
});
322+
323+
it('should remove hooks when plugin is uninstalled', async () => {
324+
const hook = jest.fn().mockResolvedValue({});
325+
const plugin = createMockPlugin('test-plugin');
326+
plugin.getHooks = jest.fn().mockReturnValue({
327+
beforePermissionCheck: hook
328+
});
329+
330+
await pluginManager.installPlugin(plugin);
331+
await pluginManager.uninstallPlugin('test-plugin');
332+
333+
const data: HookData = { role: 'user', operation: 'read', params: {} };
334+
const results = await pluginManager.executeHooks('beforePermissionCheck', data);
335+
336+
expect(results).toHaveLength(0);
337+
expect(hook).not.toHaveBeenCalled();
338+
});
304339
});
305340

306341
describe('Plugin Configuration', () => {
@@ -360,6 +395,18 @@ describe('PluginManager', () => {
360395
});
361396
});
362397

398+
describe('Internal Utilities', () => {
399+
it('should return null when handler has no associated plugin', () => {
400+
const result = (pluginManager as any).findPluginByHandler(() => {});
401+
expect(result).toBeNull();
402+
});
403+
404+
it('should attempt to load plugins from directory', async () => {
405+
await expect(pluginManager.loadPluginsFromDirectory('/tmp'))
406+
.resolves.not.toThrow();
407+
});
408+
});
409+
363410
describe('Events', () => {
364411
it('should emit installation event', async () => {
365412
const eventSpy = jest.fn();
@@ -446,6 +493,13 @@ describe('PluginManager', () => {
446493
})
447494
}));
448495
});
496+
497+
it('should log plugin system errors', () => {
498+
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
499+
(pluginManager as any).registry.events.emit('error', 'boom');
500+
expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('boom'));
501+
errorSpy.mockRestore();
502+
});
449503
});
450504

451505
describe('Strict Mode', () => {

0 commit comments

Comments
 (0)