mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
add knowledge_sync_service tests
This commit is contained in:
+11
-5
@@ -11,6 +11,7 @@ from basic_memory import db
|
||||
from basic_memory.config import ProjectConfig
|
||||
from basic_memory.db import DatabaseType
|
||||
from basic_memory.markdown.knowledge_writer import KnowledgeWriter
|
||||
from basic_memory.markdown.knowledge_parser import KnowledgeParser
|
||||
from basic_memory.models import Base
|
||||
from basic_memory.models.knowledge import Entity
|
||||
from basic_memory.repository.document_repository import DocumentRepository
|
||||
@@ -22,10 +23,10 @@ from basic_memory.services import (
|
||||
ObservationService,
|
||||
RelationService,
|
||||
DocumentService,
|
||||
KnowledgeService,
|
||||
FileChangeScanner,
|
||||
FileService
|
||||
)
|
||||
from basic_memory.services.file_service import FileService
|
||||
from basic_memory.services import KnowledgeService
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
@@ -67,7 +68,6 @@ async def session_maker(engine_factory) -> async_sessionmaker[AsyncSession]:
|
||||
return session_maker
|
||||
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(scope="function")
|
||||
async def document_repository(
|
||||
session_maker: async_sessionmaker[AsyncSession],
|
||||
@@ -140,8 +140,14 @@ def knowledge_writer():
|
||||
return KnowledgeWriter()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def knowledge_parser():
|
||||
"""Create parser instance."""
|
||||
return KnowledgeParser()
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
def file_change_scanner(document_repository, entity_repository) -> FileChangeScanner:
|
||||
def file_sync_service(document_repository, entity_repository) -> FileChangeScanner:
|
||||
"""Create FileChangeScanner instance."""
|
||||
return FileChangeScanner(document_repository, entity_repository)
|
||||
|
||||
@@ -176,4 +182,4 @@ async def sample_entity(entity_repository: EntityRepository) -> Entity:
|
||||
"path_id": "test/test_entity",
|
||||
"file_path": "test/test_entity.md",
|
||||
}
|
||||
return await entity_repository.create(entity_data)
|
||||
return await entity_repository.create(entity_data)
|
||||
@@ -0,0 +1,184 @@
|
||||
"""Tests for knowledge sync service."""
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
from pathlib import Path
|
||||
from typing import AsyncGenerator
|
||||
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from basic_memory.services.sync.knowledge_sync_service import KnowledgeSyncService
|
||||
from basic_memory.services import KnowledgeService, FileChangeScanner
|
||||
from basic_memory.markdown import KnowledgeParser
|
||||
from basic_memory.utils.file_utils import compute_checksum
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def knowledge_sync_service(
|
||||
file_sync_service: FileChangeScanner, # from conftest
|
||||
knowledge_service: KnowledgeService, # from conftest
|
||||
knowledge_parser: KnowledgeParser # need to add to conftest
|
||||
) -> KnowledgeSyncService:
|
||||
"""Create knowledge sync service for testing."""
|
||||
return KnowledgeSyncService(file_sync_service, knowledge_service, knowledge_parser)
|
||||
|
||||
|
||||
async def create_test_entity_file(
|
||||
path: Path,
|
||||
entity_type: str = "test",
|
||||
name: str = "Test Entity",
|
||||
content: str = "test content"
|
||||
) -> None:
|
||||
"""Create a test entity file with frontmatter."""
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Create basic entity markdown
|
||||
file_content = f"""---
|
||||
type: {entity_type}
|
||||
id: {entity_type}/{name.lower().replace(' ', '_')}
|
||||
created: 2024-12-27T10:00:00Z
|
||||
modified: 2024-12-27T10:00:00Z
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
# {name}
|
||||
|
||||
{content}
|
||||
|
||||
## Observations
|
||||
- [test] First observation #test
|
||||
- [test] Second observation #test
|
||||
|
||||
## Relations
|
||||
- relates_to [[Other_Entity]]
|
||||
"""
|
||||
path.write_text(file_content)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_new_entity(
|
||||
knowledge_sync_service: KnowledgeSyncService,
|
||||
test_config,
|
||||
):
|
||||
"""Test syncing a new entity file."""
|
||||
knowledge_dir = test_config.knowledge_dir
|
||||
test_file = knowledge_dir / "test" / "test_entity.md"
|
||||
|
||||
# Create test file
|
||||
await create_test_entity_file(test_file)
|
||||
|
||||
# Run sync
|
||||
changes = await knowledge_sync_service.sync(knowledge_dir)
|
||||
|
||||
# Verify changes
|
||||
assert len(changes.new) == 1
|
||||
assert "test/test_entity.md" in changes.new
|
||||
|
||||
# Verify entity in DB
|
||||
entity = await knowledge_sync_service.knowledge_service.get_entity_by_path_id("test/test_entity")
|
||||
assert entity.name == "Test Entity"
|
||||
assert entity.entity_type == "test"
|
||||
assert len(entity.observations) == 2
|
||||
assert len(entity.outbound_relations) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_modified_entity(
|
||||
knowledge_sync_service: KnowledgeSyncService,
|
||||
test_config,
|
||||
entity_repository,
|
||||
):
|
||||
"""Test syncing a modified entity file."""
|
||||
knowledge_dir = test_config.knowledge_dir
|
||||
test_file = knowledge_dir / "test" / "test_entity.md"
|
||||
|
||||
# Create initial file and sync
|
||||
await create_test_entity_file(test_file)
|
||||
await knowledge_sync_service.sync(knowledge_dir)
|
||||
|
||||
# Modify file
|
||||
await create_test_entity_file(
|
||||
test_file,
|
||||
content="modified content",
|
||||
name="Test Entity" # Keep same name/path
|
||||
)
|
||||
|
||||
# Run sync again
|
||||
changes = await knowledge_sync_service.sync(knowledge_dir)
|
||||
|
||||
# Verify changes
|
||||
assert len(changes.modified) == 1
|
||||
assert "test/test_entity.md" in changes.modified
|
||||
|
||||
# Verify entity updated
|
||||
entity = await knowledge_sync_service.knowledge_service.get_entity_by_path_id("test/test_entity")
|
||||
assert "modified content" in entity.description
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_moved_entity(
|
||||
knowledge_sync_service: KnowledgeSyncService,
|
||||
test_config,
|
||||
entity_repository
|
||||
):
|
||||
"""Test syncing a moved entity file."""
|
||||
knowledge_dir = test_config.knowledge_dir
|
||||
original_file = knowledge_dir / "test" / "original.md"
|
||||
new_file = knowledge_dir / "test" / "moved.md"
|
||||
|
||||
# Create initial file and sync
|
||||
await create_test_entity_file(original_file, name="Original")
|
||||
await knowledge_sync_service.sync(knowledge_dir)
|
||||
|
||||
# Create new file with same content
|
||||
new_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
await create_test_entity_file(new_file, name="Moved")
|
||||
original_file.unlink()
|
||||
|
||||
# Run sync
|
||||
changes = await knowledge_sync_service.sync(knowledge_dir)
|
||||
|
||||
# Verify changes
|
||||
assert len(changes.moved) == 1
|
||||
assert "test/moved.md" in changes.moved
|
||||
assert changes.moved["test/moved.md"].moved_from == "test/original.md"
|
||||
|
||||
# Verify entity updated
|
||||
with pytest.raises(Exception):
|
||||
# Original should be gone
|
||||
await knowledge_sync_service.knowledge_service.get_entity_by_path_id("test/original")
|
||||
|
||||
# New entity should exist
|
||||
entity = await knowledge_sync_service.knowledge_service.get_entity_by_path_id("test/moved")
|
||||
assert entity.name == "Moved"
|
||||
assert len(entity.observations) == 2
|
||||
assert len(entity.outbound_relations) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_deleted_entity(
|
||||
knowledge_sync_service: KnowledgeSyncService,
|
||||
test_config,
|
||||
entity_repository
|
||||
):
|
||||
"""Test syncing a deleted entity file."""
|
||||
knowledge_dir = test_config.knowledge_dir
|
||||
test_file = knowledge_dir / "test" / "to_delete.md"
|
||||
|
||||
# Create initial file and sync
|
||||
await create_test_entity_file(test_file)
|
||||
await knowledge_sync_service.sync(knowledge_dir)
|
||||
|
||||
# Delete file
|
||||
test_file.unlink()
|
||||
|
||||
# Run sync
|
||||
changes = await knowledge_sync_service.sync(knowledge_dir)
|
||||
|
||||
# Verify changes
|
||||
assert len(changes.deleted) == 1
|
||||
assert "test/to_delete.md" in changes.deleted
|
||||
|
||||
# Verify entity deleted
|
||||
with pytest.raises(Exception):
|
||||
await knowledge_sync_service.knowledge_service.get_entity_by_path_id("test/to_delete")
|
||||
Reference in New Issue
Block a user