Files
ThothII/harness/tests/test_session_list_json.py
T
marcopanandClaude Sonnet 4.6 5e0e1cee03 test(harness): pin session list/show json keys + schema alias
- test_list_sessions_required_keys: assert full spec key set
  (adds summary/updated_at/author) so dropping any goes caught.
- test_cli_show_json_valid: assert "schema" in / "db_schema" not in
  data to pin by_alias=True on the alias-sensitive field.

Production code unchanged. 8 passed; full suite 230 passed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:27:18 +02:00

166 lines
4.8 KiB
Python

"""Tests for `tht session list --json` and `tht session show --json` (Task 7)."""
import json
import pytest
from typer.testing import CliRunner
from tht.cli.session_cmd import _list_sessions, session_app
from tht.session.store import create_session
def _make_db():
from tht.config import DatabaseConfig
return DatabaseConfig(
database="testdb",
user="testuser",
password="testpass", # noqa: S106
**{"schema": "public"},
)
# ---------------------------------------------------------------------------
# Unit: _list_sessions helper
# ---------------------------------------------------------------------------
def test_list_sessions_returns_all_created(tmp_path):
db = _make_db()
m1 = create_session("prima domanda", db, tmp_path)
m2 = create_session("seconda domanda", db, tmp_path)
rows = _list_sessions(tmp_path)
ids = [r["id"] for r in rows]
assert m1.id in ids
assert m2.id in ids
def test_list_sessions_required_keys(tmp_path):
db = _make_db()
create_session("qualsiasi domanda", db, tmp_path)
rows = _list_sessions(tmp_path)
assert len(rows) >= 1
required = {"id", "status", "question", "summary", "created_at", "updated_at", "author"}
assert required.issubset(rows[0].keys())
def test_list_sessions_sorted_desc(tmp_path):
db = _make_db()
create_session("prima", db, tmp_path)
create_session("seconda", db, tmp_path)
rows = _list_sessions(tmp_path)
dates = [r["created_at"] for r in rows]
assert dates == sorted(dates, reverse=True)
def test_list_sessions_empty_dir(tmp_path):
rows = _list_sessions(tmp_path)
assert rows == []
# ---------------------------------------------------------------------------
# CLI: tht session list --json
# ---------------------------------------------------------------------------
def test_cli_list_json_valid(tmp_path, monkeypatch):
db = _make_db()
m = create_session("test question", db, tmp_path)
# Patch _load_config_or_exit so we don't need a real config file
from tht.cli import session_cmd
class FakePaths:
sessions = tmp_path
class FakeCfg:
paths = FakePaths()
monkeypatch.setattr(session_cmd, "_load_config_or_exit", lambda _: FakeCfg())
runner = CliRunner()
result = runner.invoke(session_app, ["list", "--json"])
assert result.exit_code == 0, result.output
rows = json.loads(result.output)
assert isinstance(rows, list)
ids = [r["id"] for r in rows]
assert m.id in ids
def test_cli_list_human_no_json_noise(tmp_path, monkeypatch):
"""Human mode must not emit JSON."""
db = _make_db()
create_session("human question", db, tmp_path)
from tht.cli import session_cmd
class FakePaths:
sessions = tmp_path
class FakeCfg:
paths = FakePaths()
monkeypatch.setattr(session_cmd, "_load_config_or_exit", lambda _: FakeCfg())
runner = CliRunner()
result = runner.invoke(session_app, ["list"])
assert result.exit_code == 0
# Must not be parseable as JSON array
with pytest.raises(json.JSONDecodeError):
json.loads(result.output)
# ---------------------------------------------------------------------------
# CLI: tht session show --json
# ---------------------------------------------------------------------------
def test_cli_show_json_valid(tmp_path, monkeypatch):
db = _make_db()
m = create_session("domanda show json", db, tmp_path)
from tht.cli import session_cmd
class FakePaths:
sessions = tmp_path
class FakeCfg:
paths = FakePaths()
database = db
monkeypatch.setattr(session_cmd, "_load_config_or_exit", lambda _: FakeCfg())
runner = CliRunner()
result = runner.invoke(session_app, ["show", m.id, "--json"])
assert result.exit_code == 0, result.output
data = json.loads(result.output)
assert data["id"] == m.id
assert "phase" in data
assert "has_schema_linking" in data
# Pin by_alias=True: the alias-sensitive field must serialize as "schema", not "db_schema".
assert "schema" in data
assert "db_schema" not in data
def test_cli_show_json_stdout_pristine(tmp_path, monkeypatch):
"""--json must produce only valid JSON on stdout (no ANSI color codes or extra lines)."""
db = _make_db()
m = create_session("pristine stdout test", db, tmp_path)
from tht.cli import session_cmd
class FakePaths:
sessions = tmp_path
class FakeCfg:
paths = FakePaths()
database = db
monkeypatch.setattr(session_cmd, "_load_config_or_exit", lambda _: FakeCfg())
runner = CliRunner()
result = runner.invoke(session_app, ["show", m.id, "--json"])
assert result.exit_code == 0, result.output
# stdout must parse cleanly as JSON
data = json.loads(result.output)
assert isinstance(data, dict)