Skip to main content
Glama
test_sync_features.py10.3 kB
"""Unit tests for the sync and timestamp features.""" from datetime import datetime, timezone from unittest.mock import Mock, patch import pytest from mcp_kanka.tools import handle_check_entity_updates, handle_find_entities class TestTimestampSupport: """Test timestamp support in entity responses.""" @patch("mcp_kanka.operations.get_service") async def test_find_entities_includes_timestamps(self, mock_get_service): """Test that find_entities includes created_at and updated_at timestamps.""" # Mock service mock_service = Mock() mock_get_service.return_value = mock_service # Mock entities with timestamps mock_entities = [ Mock( id=1, entity_id=101, name="Alice", type="NPC", created_at=datetime(2023, 1, 1, 10, 0, 0, tzinfo=timezone.utc), updated_at=datetime(2023, 6, 15, 14, 30, 0, tzinfo=timezone.utc), ), Mock( id=2, entity_id=102, name="Bob", type="Player", created_at=datetime(2023, 2, 1, 12, 0, 0, tzinfo=timezone.utc), updated_at=datetime(2023, 8, 20, 16, 45, 0, tzinfo=timezone.utc), ), ] mock_service.list_entities.return_value = mock_entities # Mock _entity_to_dict to include timestamps mock_service._entity_to_dict.side_effect = [ { "id": 1, "entity_id": 101, "name": "Alice", "entity_type": "character", "type": "NPC", "entry": "Test character", "tags": [], "is_hidden": False, "created_at": "2023-01-01T10:00:00+00:00", "updated_at": "2023-06-15T14:30:00+00:00", }, { "id": 2, "entity_id": 102, "name": "Bob", "entity_type": "character", "type": "Player", "entry": "Another character", "tags": [], "is_hidden": False, "created_at": "2023-02-01T12:00:00+00:00", "updated_at": "2023-08-20T16:45:00+00:00", }, ] # Test with full details result = await handle_find_entities( entity_type="character", include_full=True, ) # Check response structure assert "entities" in result assert "sync_info" in result entities = result["entities"] assert len(entities) == 2 # Check timestamps are included assert entities[0]["created_at"] == "2023-01-01T10:00:00+00:00" assert entities[0]["updated_at"] == "2023-06-15T14:30:00+00:00" assert entities[1]["created_at"] == "2023-02-01T12:00:00+00:00" assert entities[1]["updated_at"] == "2023-08-20T16:45:00+00:00" @patch("mcp_kanka.operations.get_service") async def test_sync_info_metadata(self, mock_get_service): """Test that sync_info metadata is correctly calculated.""" # Mock service mock_service = Mock() mock_get_service.return_value = mock_service # Mock entities with timestamps mock_entities = [ Mock(id=1, entity_id=101, name="Alice"), Mock(id=2, entity_id=102, name="Bob"), Mock(id=3, entity_id=103, name="Charlie"), ] mock_service.list_entities.return_value = mock_entities # Mock _entity_to_dict mock_service._entity_to_dict.side_effect = [ { "id": 1, "entity_id": 101, "name": "Alice", "entity_type": "character", "updated_at": "2023-06-15T14:30:00+00:00", }, { "id": 2, "entity_id": 102, "name": "Bob", "entity_type": "character", "updated_at": "2023-08-20T16:45:00+00:00", # Newest }, { "id": 3, "entity_id": 103, "name": "Charlie", "entity_type": "character", "updated_at": "2023-07-10T10:00:00+00:00", }, ] # Test result = await handle_find_entities( entity_type="character", limit=2, # Paginate to return only 2 ) sync_info = result["sync_info"] # Check sync_info fields assert "request_timestamp" in sync_info assert ( sync_info["newest_updated_at"] == "2023-08-20T16:45:00+00:00" ) # Bob's timestamp assert sync_info["total_count"] == 3 assert sync_info["returned_count"] == 2 @patch("mcp_kanka.operations.get_service") async def test_last_synced_parameter(self, mock_get_service): """Test that last_synced parameter is passed to the service.""" # Mock service mock_service = Mock() mock_get_service.return_value = mock_service mock_service.list_entities.return_value = [] # Test with last_synced last_sync_time = "2023-06-01T00:00:00Z" await handle_find_entities( entity_type="character", last_synced=last_sync_time, ) # Verify service was called with last_sync mock_service.list_entities.assert_called_with( "character", page=1, limit=0, last_sync=last_sync_time, related=True ) class TestCheckEntityUpdates: """Test the check_entity_updates functionality.""" @patch("mcp_kanka.operations.get_service") async def test_check_entity_updates_basic(self, mock_get_service): """Test basic check_entity_updates functionality.""" # Mock service mock_service = Mock() mock_client = Mock() mock_service.client = mock_client mock_get_service.return_value = mock_service # Mock entities response mock_client.entities.return_value = [ {"id": 101, "updated_at": "2023-06-15T14:30:00Z"}, {"id": 102, "updated_at": "2023-08-20T16:45:00Z"}, {"id": 103, "updated_at": "2023-05-01T10:00:00Z"}, # 104 is not in response (deleted) ] # Test result = await handle_check_entity_updates( entity_ids=[101, 102, 103, 104], last_synced="2023-06-01T00:00:00Z" ) # Check results assert set(result["modified_entity_ids"]) == {101, 102} # Updated after June 1 assert result["deleted_entity_ids"] == [104] # Not found assert "check_timestamp" in result @patch("mcp_kanka.operations.get_service") async def test_check_entity_updates_no_modifications(self, mock_get_service): """Test check_entity_updates when no entities are modified.""" # Mock service mock_service = Mock() mock_client = Mock() mock_service.client = mock_client mock_get_service.return_value = mock_service # Mock entities response - all updated before last_synced mock_client.entities.return_value = [ {"id": 101, "updated_at": "2023-01-15T14:30:00Z"}, {"id": 102, "updated_at": "2023-02-20T16:45:00Z"}, ] # Test result = await handle_check_entity_updates( entity_ids=[101, 102], last_synced="2023-06-01T00:00:00Z" ) # Check results assert result["modified_entity_ids"] == [] assert result["deleted_entity_ids"] == [] assert "check_timestamp" in result @patch("mcp_kanka.operations.get_service") async def test_check_entity_updates_pagination(self, mock_get_service): """Test that check_entity_updates handles pagination correctly.""" # Mock service mock_service = Mock() mock_client = Mock() mock_service.client = mock_client mock_get_service.return_value = mock_service # Mock paginated responses def mock_entities(page=1, limit=100): if page == 1: return [ {"id": i, "updated_at": "2023-07-01T00:00:00Z"} for i in range(1, 101) ] elif page == 2: return [ {"id": i, "updated_at": "2023-07-01T00:00:00Z"} for i in range(101, 151) ] else: return [] mock_client.entities.side_effect = mock_entities # Test with entity ID from second page result = await handle_check_entity_updates( entity_ids=[50, 125, 200], # 200 doesn't exist last_synced="2023-06-01T00:00:00Z", ) # Check results assert set(result["modified_entity_ids"]) == {50, 125} assert result["deleted_entity_ids"] == [200] @patch("mcp_kanka.operations.get_service") async def test_check_entity_updates_missing_last_synced(self, mock_get_service): """Test that check_entity_updates requires last_synced parameter.""" # Mock service (not actually used in this test) mock_service = Mock() mock_get_service.return_value = mock_service with pytest.raises(ValueError, match="last_synced parameter is required"): await handle_check_entity_updates( entity_ids=[101, 102], # last_synced missing ) @patch("mcp_kanka.operations.get_service") async def test_check_entity_updates_empty_list(self, mock_get_service): """Test check_entity_updates with empty entity list.""" # Mock service mock_service = Mock() mock_client = Mock() mock_service.client = mock_client mock_get_service.return_value = mock_service mock_client.entities.return_value = [] # Test result = await handle_check_entity_updates( entity_ids=[], last_synced="2023-06-01T00:00:00Z" ) # Check results assert result["modified_entity_ids"] == [] assert result["deleted_entity_ids"] == [] assert "check_timestamp" in result

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ervwalter/mcp-kanka'

If you have feedback or need assistance with the MCP directory API, please join our Discord server