diff --git a/harness/tests/test_session_mutations.py b/harness/tests/test_session_mutations.py index 4d34e7d7..d1bbc66b 100644 --- a/harness/tests/test_session_mutations.py +++ b/harness/tests/test_session_mutations.py @@ -67,3 +67,63 @@ def test_delete_session(tmp_path): def test_delete_missing_raises(tmp_path): with pytest.raises(SessionError): delete_session("nope", tmp_path) + + +import json +from typer.testing import CliRunner + +from tht.cli.session_cmd import session_app + + +def _patch_cfg(monkeypatch, 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()) + + +def test_cli_set_name(tmp_path, monkeypatch): + m = create_session("q", _db(), tmp_path) + _patch_cfg(monkeypatch, tmp_path) + res = CliRunner().invoke(session_app, ["set-name", m.id, "--name", "Mio nome"]) + assert res.exit_code == 0, res.output + assert load_session(m.id, tmp_path).name == "Mio nome" + + +def test_cli_set_group(tmp_path, monkeypatch): + m = create_session("q", _db(), tmp_path) + _patch_cfg(monkeypatch, tmp_path) + res = CliRunner().invoke(session_app, ["set-group", m.id, "--group", "G1"]) + assert res.exit_code == 0, res.output + assert load_session(m.id, tmp_path).group == "G1" + + +def test_cli_archive_unarchive(tmp_path, monkeypatch): + m = create_session("q", _db(), tmp_path) + _patch_cfg(monkeypatch, tmp_path) + assert CliRunner().invoke(session_app, ["archive", m.id]).exit_code == 0 + assert load_session(m.id, tmp_path).archived is True + assert CliRunner().invoke(session_app, ["unarchive", m.id]).exit_code == 0 + assert load_session(m.id, tmp_path).archived is False + + +def test_cli_delete(tmp_path, monkeypatch): + m = create_session("q", _db(), tmp_path) + _patch_cfg(monkeypatch, tmp_path) + res = CliRunner().invoke(session_app, ["delete", m.id]) + assert res.exit_code == 0, res.output + assert not (tmp_path / m.id).exists() + + +def test_cli_list_includes_new_fields(tmp_path, monkeypatch): + from tht.cli.session_cmd import _list_sessions + + create_session("q", _db(), tmp_path) + rows = _list_sessions(tmp_path) + assert {"name", "group", "archived"}.issubset(rows[0].keys()) diff --git a/harness/tht/cli/session_cmd.py b/harness/tht/cli/session_cmd.py index a5372372..067a8b75 100644 --- a/harness/tht/cli/session_cmd.py +++ b/harness/tht/cli/session_cmd.py @@ -155,6 +155,69 @@ def close_cmd(session_id: str = typer.Argument(...), config: Path = CONFIG_OPT) typer.secho(f"OK: sessione {session_id} chiusa.", fg=typer.colors.GREEN) +@session_app.command("set-name") +def set_name_cmd( + session_id: str = typer.Argument(...), + name: str = typer.Option(..., "--name", help="Nome descrittivo (vuoto = azzera)."), + config: Path = CONFIG_OPT, +) -> None: + """Imposta il nome descrittivo della sessione.""" + from tht.session.store import set_name + + cfg = _load_config_or_exit(config) + load_session_or_exit(cfg, session_id) + set_name(session_id, name, cfg.paths.sessions) + typer.secho(f"OK: nome aggiornato per {session_id}.", fg=typer.colors.GREEN) + + +@session_app.command("set-group") +def set_group_cmd( + session_id: str = typer.Argument(...), + group: str = typer.Option(..., "--group", help="Nome del gruppo (vuoto = nessun gruppo)."), + config: Path = CONFIG_OPT, +) -> None: + """Sposta la sessione in un gruppo (o la toglie da ogni gruppo).""" + from tht.session.store import set_group + + cfg = _load_config_or_exit(config) + load_session_or_exit(cfg, session_id) + set_group(session_id, group, cfg.paths.sessions) + typer.secho(f"OK: gruppo aggiornato per {session_id}.", fg=typer.colors.GREEN) + + +@session_app.command("archive") +def archive_cmd(session_id: str = typer.Argument(...), config: Path = CONFIG_OPT) -> None: + """Archivia la sessione (la toglie dalla lista attiva, sola lettura).""" + from tht.session.store import set_archived + + cfg = _load_config_or_exit(config) + load_session_or_exit(cfg, session_id) + set_archived(session_id, True, cfg.paths.sessions) + typer.secho(f"OK: sessione {session_id} archiviata.", fg=typer.colors.GREEN) + + +@session_app.command("unarchive") +def unarchive_cmd(session_id: str = typer.Argument(...), config: Path = CONFIG_OPT) -> None: + """Ripristina la sessione dall'archivio (non ne cambia la ripristinabilità).""" + from tht.session.store import set_archived + + cfg = _load_config_or_exit(config) + load_session_or_exit(cfg, session_id) + set_archived(session_id, False, cfg.paths.sessions) + typer.secho(f"OK: sessione {session_id} ripristinata.", fg=typer.colors.GREEN) + + +@session_app.command("delete") +def delete_cmd(session_id: str = typer.Argument(...), config: Path = CONFIG_OPT) -> None: + """Elimina definitivamente la cartella di sessione.""" + from tht.session.store import delete_session + + cfg = _load_config_or_exit(config) + load_session_or_exit(cfg, session_id) + delete_session(session_id, cfg.paths.sessions) + typer.secho(f"OK: sessione {session_id} eliminata.", fg=typer.colors.GREEN) + + def session_problems(cfg, session_id: str) -> list[str]: """Problemi del Blocco 3 (decisioni + schema_linking). Riusato da check e finalize.""" import json