test_write.py•8.32 kB
"""Tests for mcp_write tool."""
import pytest
from unittest.mock import AsyncMock, patch
class TestMcpWriteModes:
"""Test different write modes."""
@pytest.mark.asyncio
async def test_write_invalid_mode(self):
"""Test invalid mode returns error."""
from mcp_copyq.tools.write import mcp_write
result = await mcp_write(mode="invalid_mode")
assert "error" in result
assert "INVALID_MODE" in result
class TestMcpWriteAdd:
"""Test add mode functionality."""
@pytest.mark.asyncio
async def test_add_missing_tab(self):
"""Test add without tab returns error."""
from mcp_copyq.tools.write import mcp_write
result = await mcp_write(mode="add", text="test")
assert "error" in result
assert "MISSING_PARAM" in result
assert "tab" in result
@pytest.mark.asyncio
async def test_add_missing_text(self):
"""Test add without text returns error."""
from mcp_copyq.tools.write import mcp_write
result = await mcp_write(mode="add", tab="info")
assert "error" in result
assert "MISSING_PARAM" in result
assert "text" in result
@pytest.mark.asyncio
async def test_add_success(self):
"""Test successful add."""
from mcp_copyq.tools.write import mcp_write
with patch("mcp_copyq.tools.write.client") as mock:
mock.tab_exists = AsyncMock(return_value=True)
mock.add_item = AsyncMock(return_value=0)
result = await mcp_write(
mode="add",
tab="info",
text="New item text",
tags=["tag1", "tag2"]
)
assert "ok" in result
assert "mode:add" in result
assert "tab:info" in result
assert "index:0" in result
@pytest.mark.asyncio
async def test_add_preview(self):
"""Test add with preview intent."""
from mcp_copyq.tools.write import mcp_write
with patch("mcp_copyq.tools.write.client") as mock:
mock.tab_exists = AsyncMock(return_value=True)
result = await mcp_write(
mode="add",
tab="info",
text="New item",
intent="preview"
)
assert "preview" in result
assert "will_add" in result
# add_item should NOT be called
mock.add_item.assert_not_called()
class TestMcpWriteUpdate:
"""Test update mode functionality."""
@pytest.mark.asyncio
async def test_update_missing_params(self):
"""Test update without required params."""
from mcp_copyq.tools.write import mcp_write
# Missing tab
result = await mcp_write(mode="update", index=0, field="text", text="new")
assert "MISSING_PARAM" in result and "tab" in result
# Missing index
result = await mcp_write(mode="update", tab="info", field="text", text="new")
assert "MISSING_PARAM" in result and "index" in result
# Missing field
result = await mcp_write(mode="update", tab="info", index=0, text="new")
assert "MISSING_PARAM" in result and "field" in result
@pytest.mark.asyncio
async def test_update_text_replace(self):
"""Test text replacement."""
from mcp_copyq.tools.write import mcp_write
with patch("mcp_copyq.tools.write.client") as mock:
mock.tab_exists = AsyncMock(return_value=True)
mock.read_item_full = AsyncMock(return_value={
"index": 0, "text": "Old text", "tags": [], "note": ""
})
mock.update_text = AsyncMock()
result = await mcp_write(
mode="update",
tab="info",
index=0,
field="text",
edit_mode="replace",
text="New text"
)
assert "ok" in result
mock.update_text.assert_called_once()
@pytest.mark.asyncio
async def test_update_tags_append(self):
"""Test tags append."""
from mcp_copyq.tools.write import mcp_write
with patch("mcp_copyq.tools.write.client") as mock:
mock.tab_exists = AsyncMock(return_value=True)
mock.read_item_full = AsyncMock(return_value={
"index": 0, "text": "Text", "tags": ["old"], "note": ""
})
mock.update_tags = AsyncMock()
result = await mcp_write(
mode="update",
tab="info",
index=0,
field="tags",
edit_mode="append",
tags=["new"]
)
assert "ok" in result
mock.update_tags.assert_called_once()
class TestMcpWriteDelete:
"""Test delete mode functionality."""
@pytest.mark.asyncio
async def test_delete_success(self):
"""Test successful delete."""
from mcp_copyq.tools.write import mcp_write
with patch("mcp_copyq.tools.write.client") as mock:
mock.tab_exists = AsyncMock(return_value=True)
mock.read_item_full = AsyncMock(return_value={
"index": 0, "text": "To delete", "tags": [], "note": ""
})
mock.remove_item = AsyncMock()
result = await mcp_write(mode="delete", tab="info", index=0)
assert "ok" in result
assert "mode:delete" in result
mock.remove_item.assert_called_once()
@pytest.mark.asyncio
async def test_delete_preview(self):
"""Test delete preview."""
from mcp_copyq.tools.write import mcp_write
with patch("mcp_copyq.tools.write.client") as mock:
mock.tab_exists = AsyncMock(return_value=True)
mock.read_item_full = AsyncMock(return_value={
"index": 0, "text": "Will be deleted", "tags": ["tag"], "note": "note"
})
result = await mcp_write(
mode="delete",
tab="info",
index=0,
intent="preview"
)
assert "preview" in result
assert "will_delete" in result
mock.remove_item.assert_not_called()
class TestMcpWriteMove:
"""Test move mode functionality."""
@pytest.mark.asyncio
async def test_move_success(self):
"""Test successful move."""
from mcp_copyq.tools.write import mcp_write
with patch("mcp_copyq.tools.write.client") as mock:
mock.tab_exists = AsyncMock(return_value=True)
mock.read_item_full = AsyncMock(return_value={
"index": 0, "text": "Moving item", "tags": [], "note": ""
})
mock.move_item = AsyncMock(return_value=0)
result = await mcp_write(
mode="move",
tab="info",
index=0,
to_tab="workspace/archive"
)
assert "ok" in result
assert "mode:move" in result
mock.move_item.assert_called_once()
class TestMcpWriteTabOperations:
"""Test tab create/delete operations."""
@pytest.mark.asyncio
async def test_tab_create_permission_denied(self):
"""Test tab_create outside workspace."""
from mcp_copyq.tools.write import mcp_write
result = await mcp_write(mode="tab_create", path="info/subtab")
assert "error" in result
assert "PERMISSION_DENIED" in result
@pytest.mark.asyncio
async def test_tab_create_success(self):
"""Test successful tab create."""
from mcp_copyq.tools.write import mcp_write
with patch("mcp_copyq.tools.write.client") as mock:
mock.tab_exists = AsyncMock(return_value=False)
mock.create_tab = AsyncMock()
result = await mcp_write(
mode="tab_create",
path="workspace/new_project"
)
assert "ok" in result
mock.create_tab.assert_called_once()
@pytest.mark.asyncio
async def test_tab_delete_permission_denied(self):
"""Test tab_delete outside workspace."""
from mcp_copyq.tools.write import mcp_write
result = await mcp_write(mode="tab_delete", path="info")
assert "error" in result
assert "PERMISSION_DENIED" in result