"""Tests for MCP process tools — patches the service layer.""" from unittest.mock import AsyncMock, MagicMock, patch import pytest from scribe.mcp._context import _user_id_ctx @pytest.fixture(autouse=True) def _bind_user(): token = _user_id_ctx.set(7) yield _user_id_ctx.reset(token) def _fake_note(id=1, title="Drift Audit", note_type="process"): n = MagicMock() n.id = id n.title = title n.note_type = note_type n.to_dict.return_value = {"id": id, "title": title, "note_type": note_type} return n @pytest.mark.asyncio async def test_create_process_requires_title_and_body(): from scribe.mcp.tools.processes import create_process with pytest.raises(ValueError): await create_process(title="", body="something") with pytest.raises(ValueError): await create_process(title="X", body=" ") @pytest.mark.asyncio async def test_create_process_sets_note_type(): created = _fake_note() with patch("scribe.services.notes.create_note", AsyncMock(return_value=created)) as mock_create: from scribe.mcp.tools.processes import create_process out = await create_process(title="Drift Audit", body="the prompt", tags=["audit"]) assert out["note_type"] == "process" # the service was asked to create a process assert mock_create.await_args.kwargs["note_type"] == "process" assert mock_create.await_args.kwargs["title"] == "Drift Audit" @pytest.mark.asyncio async def test_get_process_returns_body_and_candidates(): note = _fake_note(id=7) with patch("scribe.services.notes.resolve_process", AsyncMock(return_value=(note, [{"id": 9, "title": "Drift Audit Notes"}]))): from scribe.mcp.tools.processes import get_process out = await get_process("drift") assert out["id"] == 7 assert out["other_matches"] == [{"id": 9, "title": "Drift Audit Notes"}] @pytest.mark.asyncio async def test_get_process_not_found_raises(): with patch("scribe.services.notes.resolve_process", AsyncMock(return_value=(None, []))): from scribe.mcp.tools.processes import get_process with pytest.raises(ValueError): await get_process("missing") @pytest.mark.asyncio async def test_update_process_rejects_non_process_note(): plain = _fake_note(id=3, note_type="note") with patch("scribe.services.notes.get_note", AsyncMock(return_value=plain)): from scribe.mcp.tools.processes import update_process with pytest.raises(ValueError): await update_process(process_id=3, title="x") def test_register_attaches_four_tools(): from scribe.mcp.tools import processes names: list[str] = [] class FakeMcp: def tool(self, name): names.append(name) def deco(fn): return fn return deco processes.register(FakeMcp()) assert set(names) == { "list_processes", "create_process", "get_process", "update_process", }