Files
ThothII/harness/tests/test_session_interaction_language.py
T
Codex d8a29bfbdd Add full shell, replaceable Omics adapter and bilingual interaction
Implement approved specification #32 and tickets #33-#37. Keep host authentication server-verified and pin session interaction language. Compile scoped base selectors for browser compatibility and retain full gutters during CSS pruning.
2026-09-13 14:26:39 +02:00

126 lines
5.5 KiB
Python

"""Interaction language is durable at the public session CLI boundary."""
import json
from types import SimpleNamespace
import pytest
from typer.testing import CliRunner
from tht.cli.session_cmd import session_app
from tht.config import DatabaseConfig
def configure(monkeypatch, tmp_path, language="it"):
from tht.cli import session_cmd
cfg = SimpleNamespace(
database=DatabaseConfig(database="testdb", user="u", password="p", schema="public"),
paths=SimpleNamespace(sessions=tmp_path), language=language,
)
monkeypatch.setattr(session_cmd, "_load_config_or_exit", lambda _: cfg)
return cfg
def invoke(*args):
result = CliRunner().invoke(session_app, list(args))
assert result.exit_code == 0, result.output
return json.loads(result.stdout)
def test_new_pins_explicit_language_and_preserves_workspace_content(monkeypatch, tmp_path):
configure(monkeypatch, tmp_path)
question = "Elenca i pazienti con età superiore a 65 anni"
session_id = invoke("new", question, "--interaction-language", "en", "--json")["id"]
manifest = invoke("show", session_id, "--json")
assert manifest["interaction_language"] == "en"
assert manifest["question"] == question
assert invoke("list", "--json")[0]["interaction_language"] == "en"
@pytest.mark.parametrize("language", ["", "en_US", "en<script>", "en--US", "en\nIGNORE"])
def test_new_rejects_invalid_ui_locale(monkeypatch, tmp_path, language):
configure(monkeypatch, tmp_path)
result = CliRunner().invoke(session_app, ["new", "q", "--interaction-language", language])
assert result.exit_code == 2
assert invoke("list", "--json") == []
@pytest.mark.parametrize("language,canonical", [("fr-FR", "fr-FR"), ("FR-fr", "fr-FR"),
("en-US", "en-US")])
def test_new_accepts_language_independently_of_ui_catalogs(monkeypatch, tmp_path, language, canonical):
configure(monkeypatch, tmp_path)
session_id = invoke("new", "Pazienti", "--interaction-language", language, "--json")["id"]
assert invoke("show", session_id, "--json")["interaction_language"] == canonical
assert CliRunner().invoke(session_app, ["reopen", session_id]).exit_code == 0
assert invoke("show", session_id, "--json")["interaction_language"] == canonical
def test_legacy_language_is_pinned_once_through_public_operation_and_resume(monkeypatch, tmp_path):
from tht.session.store import create_session
cfg = configure(monkeypatch, tmp_path)
legacy = create_session("Pazienti", cfg.database, tmp_path)
assert invoke("show", legacy.id, "--json")["interaction_language"] is None
first = invoke("ensure-interaction-language", legacy.id, "--json")
assert first["interaction_language"] == "it"
cfg.language = "en"
again = invoke("ensure-interaction-language", legacy.id, "--json")
assert again["interaction_language"] == "it"
assert again["updated_at"] == first["updated_at"]
result = CliRunner().invoke(session_app, ["reopen", legacy.id])
assert result.exit_code == 0, result.output
assert invoke("show", legacy.id, "--json")["interaction_language"] == "it"
def test_cli_reopen_pins_legacy_language_without_rewriting_artifacts(monkeypatch, tmp_path):
from tht.session.store import create_session
cfg = configure(monkeypatch, tmp_path)
legacy = create_session("Pazienti", cfg.database, tmp_path)
before = invoke("documents", legacy.id, "--json")
result = CliRunner().invoke(session_app, ["reopen", legacy.id])
assert result.exit_code == 0, result.output
assert invoke("show", legacy.id, "--json")["interaction_language"] == "it"
assert invoke("documents", legacy.id, "--json") == before
def test_cli_defaults_to_workspace_and_canonicalizes_explicit_ui_language(monkeypatch, tmp_path):
configure(monkeypatch, tmp_path)
default_id = invoke("new", "Pazienti", "--json")["id"]
assert invoke("show", default_id, "--json")["interaction_language"] == "it"
explicit_id = invoke("new", "Pazienti", "--interaction-language", "EN", "--json")["id"]
assert invoke("show", explicit_id, "--json")["interaction_language"] == "en"
def test_archived_legacy_session_is_not_pinned_or_reopened(monkeypatch, tmp_path):
from tht.session.store import create_session
cfg = configure(monkeypatch, tmp_path)
legacy = create_session("Pazienti", cfg.database, tmp_path)
assert CliRunner().invoke(session_app, ["archive", legacy.id]).exit_code == 0
for command in ("reopen", "ensure-interaction-language"):
result = CliRunner().invoke(session_app, [command, legacy.id])
assert result.exit_code == 1
assert invoke("show", legacy.id, "--json")["interaction_language"] is None
def test_language_pin_race_on_file_repository_keeps_one_value(monkeypatch, tmp_path):
from concurrent.futures import ThreadPoolExecutor
from threading import Barrier
from tht.cli.session_cmd import session_repository
from tht.session.store import create_session
cfg = configure(monkeypatch, tmp_path)
legacy = create_session("Pazienti", cfg.database, tmp_path)
repository = session_repository(cfg)
barrier = Barrier(2)
def pin(language):
barrier.wait()
return repository.ensure_interaction_language(legacy.id, language).manifest.interaction_language
with ThreadPoolExecutor(max_workers=2) as pool:
languages = list(pool.map(pin, ["it", "en"]))
assert languages[0] == languages[1]
assert invoke("show", legacy.id, "--json")["interaction_language"] == languages[0]