server/tests/test_session_reader.py
Rama main · réplica de lectura del repositorio original.
import json
from hashlib import sha256
from pathlib import Path
import pytest
from bumblehive_server.session_reader import SessionNotFoundError, SessionReader
@pytest.mark.asyncio
async def test_session_reader_lists_and_loads_json_sessions(tmp_path) -> None:
reader = SessionReader(tmp_path)
session_id = await reader.create("/tmp/demo")
path = tmp_path / f"{sha256(session_id.encode()).hexdigest()}.json"
path.write_text(
json.dumps(
{
"session_id": session_id,
"messages": [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi"},
],
}
),
encoding="utf-8",
)
sessions = await reader.list()
detail = await reader.get(session_id)
assert sessions[0].title == "Hello"
assert sessions[0].last_message == "Hi"
assert sessions[0].workspace == str(Path("/tmp/demo").resolve())
assert sessions[0].parent_session_id is None
assert sessions[0].created_at <= sessions[0].updated_at
assert detail.workspace == str(Path("/tmp/demo").resolve())
assert detail.created_at == sessions[0].created_at
assert detail.messages[-1]["content"] == "Hi"
@pytest.mark.asyncio
async def test_session_reader_prefers_persisted_display_title(tmp_path) -> None:
reader = SessionReader(tmp_path)
session_id = await reader.create_child(
"/tmp/demo",
title=" Inspect concurrency ",
parent_session_id="parent-session",
)
path = tmp_path / f"{sha256(session_id.encode()).hexdigest()}.json"
path.write_text(
json.dumps(
{
"session_id": session_id,
"messages": [
{
"role": "user",
"content": "A much longer self-contained task",
}
],
}
),
encoding="utf-8",
)
sessions = await reader.list()
assert sessions[0].title == "Inspect concurrency"
assert sessions[0].parent_session_id == "parent-session"
metadata_path = (
tmp_path
/ ".metadata"
/ f"{sha256(session_id.encode()).hexdigest()}.json"
)
metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
assert metadata["title"] == "Inspect concurrency"
assert metadata["parent_session_id"] == "parent-session"
@pytest.mark.asyncio
async def test_session_reader_finds_all_descendants(tmp_path) -> None:
reader = SessionReader(tmp_path)
parent_id = await reader.create("/tmp/demo")
child_id = await reader.create_child(
"/tmp/demo",
title="Child",
parent_session_id=parent_id,
)
grandchild_id = await reader.create_child(
"/tmp/demo",
title="Grandchild",
parent_session_id=child_id,
)
unrelated_id = await reader.create("/tmp/demo")
assert await reader.descendant_ids(parent_id) == [child_id, grandchild_id]
assert await reader.descendant_ids(child_id) == [grandchild_id]
assert await reader.descendant_ids(unrelated_id) == []
@pytest.mark.asyncio
async def test_session_reader_raises_for_missing_session(tmp_path) -> None:
reader = SessionReader(tmp_path)
with pytest.raises(SessionNotFoundError):
await reader.get("missing")
@pytest.mark.asyncio
async def test_session_reader_creates_and_migrates_workspace_documents(
tmp_path,
) -> None:
reader = SessionReader(tmp_path)
created_id = await reader.create(tmp_path / "created-workspace")
created_path = tmp_path / f"{sha256(created_id.encode()).hexdigest()}.json"
assert json.loads(created_path.read_text(encoding="utf-8")) == {
"session_id": created_id,
"messages": [],
}
created = await reader.get(created_id)
assert created.workspace == str((tmp_path / "created-workspace").resolve())
assert created.messages == []
assert created.created_at <= created.updated_at
legacy_id = "legacy-session"
legacy_path = tmp_path / f"{sha256(legacy_id.encode()).hexdigest()}.json"
legacy_path.write_text(
json.dumps({"session_id": legacy_id, "messages": []}),
encoding="utf-8",
)
original_document = legacy_path.read_text(encoding="utf-8")
original_mtime = legacy_path.stat().st_mtime_ns
migrated = await reader.migrate_missing_workspace(tmp_path / "legacy-workspace")
assert migrated == 1
assert (await reader.get(legacy_id)).workspace == str(
(tmp_path / "legacy-workspace").resolve()
)
assert legacy_path.stat().st_mtime_ns == original_mtime
assert legacy_path.read_text(encoding="utf-8") == original_document
assert await reader.delete_metadata(legacy_id) is True
assert await reader.delete_metadata(legacy_id) is False