mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
f818702ab7
Signed-off-by: phernandez <paul@basicmachines.co> Co-authored-by: Claude <noreply@anthropic.com>
136 lines
4.9 KiB
Python
136 lines
4.9 KiB
Python
"""Tests for discussion context MCP tool."""
|
|
|
|
import pytest
|
|
|
|
from mcp.server.fastmcp.exceptions import ToolError
|
|
|
|
from basic_memory.mcp.tools import recent_activity
|
|
from basic_memory.schemas.search import SearchItemType
|
|
|
|
# Test data for different timeframe formats
|
|
valid_timeframes = [
|
|
"7d", # Standard format
|
|
"yesterday", # Natural language
|
|
"0d", # Zero duration
|
|
]
|
|
|
|
invalid_timeframes = [
|
|
"invalid", # Nonsense string
|
|
# NOTE: "tomorrow" now returns 1 day ago due to timezone safety - no longer invalid
|
|
]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_recent_activity_timeframe_formats(client, test_project, test_graph):
|
|
"""Test that recent_activity accepts various timeframe formats."""
|
|
# Test each valid timeframe with project-specific mode
|
|
for timeframe in valid_timeframes:
|
|
try:
|
|
result = await recent_activity.fn(
|
|
project=test_project.name,
|
|
type=["entity"],
|
|
timeframe=timeframe,
|
|
)
|
|
assert result is not None
|
|
assert isinstance(result, str)
|
|
assert "Recent Activity:" in result
|
|
assert timeframe in result
|
|
except Exception as e:
|
|
pytest.fail(f"Failed with valid timeframe '{timeframe}': {str(e)}")
|
|
|
|
# Test invalid timeframes should raise ValidationError
|
|
for timeframe in invalid_timeframes:
|
|
with pytest.raises(ToolError):
|
|
await recent_activity.fn(project=test_project.name, timeframe=timeframe)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_recent_activity_type_filters(client, test_project, test_graph):
|
|
"""Test that recent_activity correctly filters by types."""
|
|
|
|
# Test single string type
|
|
result = await recent_activity.fn(project=test_project.name, type=SearchItemType.ENTITY)
|
|
assert result is not None
|
|
assert isinstance(result, str)
|
|
assert "Recent Activity:" in result
|
|
assert "Recent Notes & Documents" in result
|
|
|
|
# Test single string type
|
|
result = await recent_activity.fn(project=test_project.name, type="entity")
|
|
assert result is not None
|
|
assert isinstance(result, str)
|
|
assert "Recent Activity:" in result
|
|
assert "Recent Notes & Documents" in result
|
|
|
|
# Test single type
|
|
result = await recent_activity.fn(project=test_project.name, type=["entity"])
|
|
assert result is not None
|
|
assert isinstance(result, str)
|
|
assert "Recent Activity:" in result
|
|
assert "Recent Notes & Documents" in result
|
|
|
|
# Test multiple types
|
|
result = await recent_activity.fn(project=test_project.name, type=["entity", "observation"])
|
|
assert result is not None
|
|
assert isinstance(result, str)
|
|
assert "Recent Activity:" in result
|
|
# Should contain sections for both types
|
|
assert "Recent Notes & Documents" in result or "Recent Observations" in result
|
|
|
|
# Test multiple types
|
|
result = await recent_activity.fn(
|
|
project=test_project.name, type=[SearchItemType.ENTITY, SearchItemType.OBSERVATION]
|
|
)
|
|
assert result is not None
|
|
assert isinstance(result, str)
|
|
assert "Recent Activity:" in result
|
|
# Should contain sections for both types
|
|
assert "Recent Notes & Documents" in result or "Recent Observations" in result
|
|
|
|
# Test all types
|
|
result = await recent_activity.fn(
|
|
project=test_project.name, type=["entity", "observation", "relation"]
|
|
)
|
|
assert result is not None
|
|
assert isinstance(result, str)
|
|
assert "Recent Activity:" in result
|
|
assert "Activity Summary:" in result
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_recent_activity_type_invalid(client, test_project, test_graph):
|
|
"""Test that recent_activity correctly filters by types."""
|
|
|
|
# Test single invalid string type
|
|
with pytest.raises(ValueError) as e:
|
|
await recent_activity.fn(project=test_project.name, type="note")
|
|
assert (
|
|
str(e.value) == "Invalid type: note. Valid types are: ['entity', 'observation', 'relation']"
|
|
)
|
|
|
|
# Test invalid string array type
|
|
with pytest.raises(ValueError) as e:
|
|
await recent_activity.fn(project=test_project.name, type=["note"])
|
|
assert (
|
|
str(e.value) == "Invalid type: note. Valid types are: ['entity', 'observation', 'relation']"
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_recent_activity_discovery_mode(client, test_project, test_graph):
|
|
"""Test that recent_activity discovery mode works without project parameter."""
|
|
# Test discovery mode (no project parameter)
|
|
result = await recent_activity.fn()
|
|
assert result is not None
|
|
assert isinstance(result, str)
|
|
|
|
# Check that we get a formatted summary
|
|
assert "Recent Activity Summary" in result
|
|
assert "Most Active Project:" in result or "Other Active Projects:" in result
|
|
assert "Summary:" in result
|
|
assert "active projects" in result
|
|
|
|
# Should contain project discovery guidance
|
|
assert "Suggested project:" in result or "Multiple active projects" in result
|
|
assert "Session reminder:" in result
|