Files
hermes-webui/tests/test_issue6892_sync_title_coverage.py
T
nesquena-hermesandliuguangyong93 d73cea803e docs(changelog): stamp #6892 + add direct sync_session_title coverage tests
Codex round-1 SHOULD-FIX: the PR's only test change mocked the new write to a
no-op. Add real-SessionDB tests proving generated-title persistence, manual-rename
no-overwrite, and cli/gateway source preservation on ensure_session. Additive
test-only; no behavior change to the contributor's fix.

Co-authored-by: liuguangyong93 <liuguangyong93@users.noreply.github.com>
2026-08-12 18:51:46 +00:00

96 lines
3.5 KiB
Python

"""Direct coverage for api.state_sync.sync_session_title (#6892).
Codex round-1 SHOULD-FIX: the PR's only test change mocks sync_session_title to a
no-op, so the new state.db-writing path had no direct test proving it actually
persists a generated title AND preserves a manual rename. These tests exercise
the real function against a temporary hermes-agent SessionDB.
"""
import pytest
def _make_db(tmp_path):
hermes_state = pytest.importorskip("hermes_state")
SessionDB = hermes_state.SessionDB
return SessionDB(db_path=tmp_path / "state.db")
@pytest.mark.requires_agent_modules
def test_sync_session_title_persists_generated_title(tmp_path, monkeypatch):
"""A generated title is written to state.db so `hermes sessions list` isn't blank."""
from api import state_sync
db = _make_db(tmp_path)
try:
# Route sync_session_title at the real temp DB (a fresh handle each call,
# mirroring production, but pointed at our tmp state.db).
monkeypatch.setattr(
state_sync,
"_get_state_db",
lambda profile=None: _make_db(tmp_path),
)
state_sync.sync_session_title("sess-gen", "Generated Title", profile="default")
assert db.get_session_title("sess-gen") == "Generated Title"
# Provenance is the automatic LLM source, not a user rename.
assert db.get_session_title_source("sess-gen") == db.TITLE_SOURCE_LLM
finally:
db.close()
@pytest.mark.requires_agent_modules
def test_sync_session_title_does_not_overwrite_manual_rename(tmp_path, monkeypatch):
"""A user rename (source=user) is never clobbered by a later title sync."""
from api import state_sync
db = _make_db(tmp_path)
try:
# Seed a manual rename first — this records `user` provenance.
db.ensure_session(session_id="sess-manual", source="cli")
db.set_session_title("sess-manual", "My Manual Name")
assert db.get_session_title_source("sess-manual") == db.TITLE_SOURCE_USER
monkeypatch.setattr(
state_sync,
"_get_state_db",
lambda profile=None: _make_db(tmp_path),
)
# A background generation now tries to sync an auto title — must be a no-op.
state_sync.sync_session_title("sess-manual", "Auto Generated", profile="default")
assert db.get_session_title("sess-manual") == "My Manual Name"
assert db.get_session_title_source("sess-manual") == db.TITLE_SOURCE_USER
finally:
db.close()
@pytest.mark.requires_agent_modules
def test_sync_session_title_preserves_existing_source_on_ensure(tmp_path, monkeypatch):
"""ensure_session(source='webui') must not clobber an existing cli/gateway row's source."""
from api import state_sync
db = _make_db(tmp_path)
try:
db.ensure_session(session_id="sess-cli", source="cli")
monkeypatch.setattr(
state_sync,
"_get_state_db",
lambda profile=None: _make_db(tmp_path),
)
# Sync (which calls ensure_session(source='webui')) on a pre-existing cli row.
state_sync.sync_session_title("sess-cli", "Some Title", profile="default")
# INSERT OR IGNORE semantics: the original source is preserved, the title lands.
assert db.get_session_title("sess-cli") == "Some Title"
with db._lock:
row = db._conn.execute(
"SELECT source FROM sessions WHERE id = ?", ("sess-cli",)
).fetchone()
assert row["source"] == "cli"
finally:
db.close()