"use strict";
/**
 * Tests for the Native AI Plugin System
 */
Object.defineProperty(exports, "__esModule", { value: true });
const plugin_system_1 = require("../plugin-system");
const anthropic_provider_plugin_1 = require("../../../examples/plugins/anthropic-provider-plugin");
const openai_provider_plugin_1 = require("../../../examples/plugins/openai-provider-plugin");
// Mock console to avoid logs during tests
const originalConsole = global.console;
beforeAll(() => {
    global.console = {
        ...originalConsole,
        log: jest.fn(),
        info: jest.fn(),
        warn: jest.fn(),
        error: jest.fn(),
    };
});
afterAll(() => {
    global.console = originalConsole;
});
describe('BFUIPluginManager', () => {
    let pluginManager;
    beforeEach(() => {
        // Reset singleton for each test
        // @ts-ignore - accessing private static field for testing
        plugin_system_1.BFUIPluginManager._instance = undefined;
        // Create a new instance
        const config = {
            apiUrl: 'http://test-api.example.com',
            apiKey: 'test-api-key',
            defaultProvider: 'anthropic-provider',
            monitoring: {
                enabled: true,
                serviceName: 'test-service',
            },
            plugins: {
                'anthropic-provider': {
                    apiKey: 'test-anthropic-key'
                },
                'openai-provider': {
                    apiKey: 'test-openai-key'
                }
            }
        };
        pluginManager = plugin_system_1.BFUIPluginManager.getInstance(config);
    });
    afterEach(async () => {
        // Clean up after each test
        if (pluginManager.isInitialized()) {
            await pluginManager.shutdown();
        }
    });
    test('getInstance returns the same instance', () => {
        const instance1 = plugin_system_1.BFUIPluginManager.getInstance();
        const instance2 = plugin_system_1.BFUIPluginManager.getInstance();
        expect(instance1).toBe(instance2);
    });
    test('getInstance with config updates the config', () => {
        const newConfig = {
            apiUrl: 'http://new-api.example.com',
            apiKey: 'new-api-key',
        };
        const updatedInstance = plugin_system_1.BFUIPluginManager.getInstance(newConfig);
        // @ts-ignore - accessing private field for testing
        expect(updatedInstance.config.apiUrl).toBe('http://new-api.example.com');
        // @ts-ignore - accessing private field for testing
        expect(updatedInstance.config.apiKey).toBe('new-api-key');
    });
    test('registerPlugin adds a plugin to the registry', () => {
        const plugin = new anthropic_provider_plugin_1.AnthropicProviderPlugin();
        pluginManager.registerPlugin(plugin);
        const retrievedPlugin = pluginManager.getPlugin(plugin.id);
        expect(retrievedPlugin).toBe(plugin);
    });
    test('getPluginsByType returns plugins of the specified type', () => {
        const anthropicPlugin = new anthropic_provider_plugin_1.AnthropicProviderPlugin();
        const openaiPlugin = new openai_provider_plugin_1.OpenAIProviderPlugin();
        pluginManager.registerPlugin(anthropicPlugin);
        pluginManager.registerPlugin(openaiPlugin);
        const providerPlugins = pluginManager.getPluginsByType('provider');
        expect(providerPlugins).toHaveLength(2);
        expect(providerPlugins).toContain(anthropicPlugin);
        expect(providerPlugins).toContain(openaiPlugin);
    });
    test('getProviderPlugins returns only provider plugins', () => {
        const anthropicPlugin = new anthropic_provider_plugin_1.AnthropicProviderPlugin();
        const openaiPlugin = new openai_provider_plugin_1.OpenAIProviderPlugin();
        // Create a non-provider plugin
        const nonProviderPlugin = {
            id: 'test-plugin',
            name: 'Test Plugin',
            version: '1.0.0',
            type: 'tool',
            capabilities: ['test'],
            metadata: {},
            initialize: jest.fn(),
            isInitialized: jest.fn().mockReturnValue(true),
            shutdown: jest.fn(),
        };
        pluginManager.registerPlugin(anthropicPlugin);
        pluginManager.registerPlugin(openaiPlugin);
        pluginManager.registerPlugin(nonProviderPlugin);
        const providerPlugins = pluginManager.getProviderPlugins();
        expect(providerPlugins).toHaveLength(2);
        expect(providerPlugins).toContain(anthropicPlugin);
        expect(providerPlugins).toContain(openaiPlugin);
        expect(providerPlugins).not.toContain(nonProviderPlugin);
    });
    test('initialize initializes all registered plugins', async () => {
        const anthropicPlugin = new anthropic_provider_plugin_1.AnthropicProviderPlugin();
        const openaiPlugin = new openai_provider_plugin_1.OpenAIProviderPlugin();
        // Spy on initialize methods
        const anthropicInitSpy = jest.spyOn(anthropicPlugin, 'initialize');
        const openaiInitSpy = jest.spyOn(openaiPlugin, 'initialize');
        pluginManager.registerPlugin(anthropicPlugin);
        pluginManager.registerPlugin(openaiPlugin);
        await pluginManager.initialize();
        expect(anthropicInitSpy).toHaveBeenCalled();
        expect(openaiInitSpy).toHaveBeenCalled();
        expect(pluginManager.isInitialized()).toBe(true);
    });
    test('shutdown shuts down all registered plugins', async () => {
        const anthropicPlugin = new anthropic_provider_plugin_1.AnthropicProviderPlugin();
        const openaiPlugin = new openai_provider_plugin_1.OpenAIProviderPlugin();
        // Spy on shutdown methods
        const anthropicShutdownSpy = jest.spyOn(anthropicPlugin, 'shutdown');
        const openaiShutdownSpy = jest.spyOn(openaiPlugin, 'shutdown');
        pluginManager.registerPlugin(anthropicPlugin);
        pluginManager.registerPlugin(openaiPlugin);
        await pluginManager.initialize();
        await pluginManager.shutdown();
        expect(anthropicShutdownSpy).toHaveBeenCalled();
        expect(openaiShutdownSpy).toHaveBeenCalled();
        expect(pluginManager.isInitialized()).toBe(false);
    });
    test('unregisterPlugin removes a plugin from the registry', async () => {
        const plugin = new anthropic_provider_plugin_1.AnthropicProviderPlugin();
        pluginManager.registerPlugin(plugin);
        await pluginManager.initialize();
        expect(pluginManager.getPlugin(plugin.id)).toBe(plugin);
        pluginManager.unregisterPlugin(plugin.id);
        expect(pluginManager.getPlugin(plugin.id)).toBeUndefined();
    });
    test('getDefaultProvider returns the configured default provider', async () => {
        const anthropicPlugin = new anthropic_provider_plugin_1.AnthropicProviderPlugin();
        pluginManager.registerPlugin(anthropicPlugin);
        await pluginManager.initialize();
        const defaultProvider = pluginManager.getDefaultProvider();
        expect(defaultProvider).toBe(anthropicPlugin);
    });
});
describe('ProviderAdapter', () => {
    let pluginManager;
    let anthropicPlugin;
    beforeEach(async () => {
        // Reset singleton for each test
        // @ts-ignore - accessing private static field for testing
        plugin_system_1.BFUIPluginManager._instance = undefined;
        // Create a new instance
        const config = {
            apiUrl: 'http://test-api.example.com',
            apiKey: 'test-api-key',
            defaultProvider: 'anthropic-provider',
            plugins: {
                'anthropic-provider': {
                    apiKey: 'test-anthropic-key'
                }
            }
        };
        pluginManager = plugin_system_1.BFUIPluginManager.getInstance(config);
        anthropicPlugin = new anthropic_provider_plugin_1.AnthropicProviderPlugin();
        // Mock plugin methods
        jest.spyOn(anthropicPlugin, 'execute').mockImplementation(async (request) => {
            return {
                id: 'test-response',
                model: request.model || 'claude-3-sonnet',
                content: 'Test response',
                usage: {
                    prompt_tokens: 10,
                    completion_tokens: 20,
                    total_tokens: 30
                }
            };
        });
        jest.spyOn(anthropicPlugin, 'executeStreaming').mockImplementation(async (request, handler) => {
            handler.onChunk({
                content: 'Test chunk',
                done: true
            });
            handler.onComplete({
                id: 'test-response',
                model: request.model || 'claude-3-sonnet',
                content: 'Test response',
                usage: {
                    prompt_tokens: 10,
                    completion_tokens: 20,
                    total_tokens: 30
                }
            });
        });
        pluginManager.registerPlugin(anthropicPlugin);
        await pluginManager.initialize();
    });
    test('constructor accepts a provider plugin', () => {
        const adapter = new plugin_system_1.ProviderAdapter(anthropicPlugin);
        expect(adapter).toBeDefined();
        expect(adapter.getId()).toBe('anthropic-provider');
    });
    test('constructor accepts a provider ID', () => {
        const adapter = new plugin_system_1.ProviderAdapter('anthropic-provider');
        expect(adapter).toBeDefined();
        expect(adapter.getId()).toBe('anthropic-provider');
    });
    test('chat executes a chat request', async () => {
        const adapter = new plugin_system_1.ProviderAdapter(anthropicPlugin);
        const chatRequest = {
            model: 'claude-3-sonnet',
            messages: [
                {
                    role: 'user',
                    content: 'Hello, Claude!'
                }
            ]
        };
        const response = await adapter.chat(chatRequest);
        expect(response).toBeDefined();
        expect(response.model).toBe('claude-3-sonnet');
        expect(response.choices[0].message.content).toBe('Test response');
    });
    test('chat with streaming executes a streaming request', async () => {
        const adapter = new plugin_system_1.ProviderAdapter(anthropicPlugin);
        const chatRequest = {
            model: 'claude-3-sonnet',
            messages: [
                {
                    role: 'user',
                    content: 'Hello, Claude!'
                }
            ],
            stream: true
        };
        const onStreamMock = jest.fn();
        const response = await adapter.chat(chatRequest, {
            onStream: onStreamMock
        });
        expect(response).toBeDefined();
        expect(onStreamMock).toHaveBeenCalled();
    });
    test('getCapabilities returns provider capabilities', () => {
        const adapter = new plugin_system_1.ProviderAdapter(anthropicPlugin);
        const capabilities = adapter.getCapabilities();
        expect(capabilities).toBeDefined();
        expect(capabilities.streaming).toBe(true);
    });
    test('getModels returns provider models', () => {
        const adapter = new plugin_system_1.ProviderAdapter(anthropicPlugin);
        const models = adapter.getModels();
        expect(models).toBeDefined();
        expect(models.length).toBeGreaterThan(0);
    });
});
//# sourceMappingURL=plugin-system.test.js.map