"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
/**
 * Project Caffeine
 * 单元测试: app.ts (接入层)
 */
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
const promptsController_1 = require("../controllers/promptsController");
const toolsController_1 = require("../controllers/toolsController");
const resourceService = __importStar(require("../services/resourceService"));
// 1. 全局 Mock MCP SDK 和传输层，防止测试时真实启动服务器
jest.mock('@modelcontextprotocol/sdk/server/mcp.js');
jest.mock('@modelcontextprotocol/sdk/server/stdio.js');
jest.mock('../controllers/promptsController');
jest.mock('../controllers/toolsController');
jest.mock('../services/resourceService');
describe('app.ts 接入层逻辑测试', () => {
    let mockServerInstance;
    beforeEach(() => {
        jest.clearAllMocks();
        // 2. 模拟 McpServer 实例的行为
        mockServerInstance = {
            prompt: jest.fn(),
            tool: jest.fn(),
            resource: jest.fn(),
            connect: jest.fn().mockResolvedValue(undefined),
        };
        // 让 McpServer 构造函数返回这个 mock 实例
        mcp_js_1.McpServer.mockImplementation(() => mockServerInstance);
        // 拦截 console 输出以保持测试日志整洁
        jest.spyOn(console, 'error').mockImplementation(() => { });
        // 核心：使用 isolateModules 重新 require app.ts，确保顶层注册代码被执行
        jest.isolateModules(() => {
            require('../app');
        });
    });
    describe('Prompts 逻辑验证 (思维框架)', () => {
        it('验证参数自动补全：漏传可选参数时应当补全为 "无"', async () => {
            // 提取 scqa 注册时的回调函数 (第三个参数)
            const scqaCall = mockServerInstance.prompt.mock.calls.find((c) => c[0] === 'scqa');
            expect(scqaCall).toBeDefined();
            const handler = scqaCall[2];
            // 模拟控制器返回一个标准消息
            promptsController_1.handlePromptsGet.mockResolvedValueOnce({
                messages: [{ role: 'user', content: { text: 'test' } }]
            });
            // 触发回调：只传入必填的 situation，不传 context 和 objective
            await handler({ situation: '当前的背景' });
            // 验证：app.ts 应该调用控制器并补全了参数
            expect(promptsController_1.handlePromptsGet).toHaveBeenCalledWith('scqa', {
                situation: '当前的背景',
                context: '无', // 自动补全逻辑
                objective: '无' // 自动补全逻辑
            });
        });
        it('验证消息角色过滤：应当只保留 user 和 assistant 消息', async () => {
            const handler = mockServerInstance.prompt.mock.calls.find((c) => c[0] === 'scqa')[2];
            // 模拟控制器返回包含 system 消息的序列
            promptsController_1.handlePromptsGet.mockResolvedValueOnce({
                messages: [
                    { role: 'system', content: { type: 'text', text: '指令' } },
                    { role: 'user', content: { type: 'text', text: '问题' } },
                    { role: 'assistant', content: { type: 'text', text: '回答' } }
                ]
            });
            const result = await handler({ situation: 's' });
            // 验证：system 消息应该被 filter 过滤掉
            expect(result.messages).toHaveLength(2);
            expect(result.messages[0].role).toBe('user');
            expect(result.messages[1].role).toBe('assistant');
            // 验证元数据补全
            expect(result.messages[0].content._meta).toBeUndefined(); // 应按代码逻辑设为 undefined
        });
    });
    describe('Tools 逻辑验证 (执行工具)', () => {
        it('应当将控制器返回的结果正确映射为 type: "text" 格式', async () => {
            const toolCall = mockServerInstance.tool.mock.calls.find((c) => c[0] === 'save_note');
            const handler = toolCall[2];
            // 模拟控制器返回原始文本内容
            toolsController_1.handleToolCall.mockResolvedValueOnce({
                content: [{ text: '保存成功' }]
            });
            const result = await handler({ filename: 'a.md', content: 'c' });
            // 验证：app.ts 应该通过 .map 补全了 type: "text"
            expect(result.content[0]).toEqual({
                type: 'text',
                text: '保存成功'
            });
        });
    });
    describe('Resources 逻辑验证 (静态资源)', () => {
        it('验证资源读取：应当从 note:// URI 中解码文件名并调用服务层', async () => {
            // 寻找 resource 注册时的读取处理函数 (第三个参数)
            const readHandler = mockServerInstance.resource.mock.calls[0][2];
            const mockUri = { href: 'note://local/%E6%B5%8B%E8%AF%95.md' }; // "测试.md" 的编码
            const mockParams = { filename: '%E6%B5%8B%E8%AF%95.md' };
            resourceService.readObsidianNote.mockResolvedValueOnce('# 笔记内容');
            const result = await readHandler(mockUri, mockParams);
            // 验证：URI 是否被正确 decodeURIComponent 解码为 "测试.md"
            expect(resourceService.readObsidianNote).toHaveBeenCalledWith('测试.md');
            expect(result.contents[0].text).toBe('# 笔记内容');
        });
    });
});
//# sourceMappingURL=app.test.js.map