Files
ss-tools/backend/tests/plugins/translate/test_preview_session_ops.py
busya f75c15dbc6 test: massive coverage expansion — 15 new test modules + assistant tool fixes + orthogonal testing
- 10 translate plugin test files (100% coverage on 12 modules)
- assistant/handler tools: 85+ tests covering dispatch, registry, resolvers, routes, llm_planner, 13 tool handlers
- clean release: artifact_catalog_loader, mappers, approval, publication tests
- API routes: translate_helpers, validation_service extensions, datasets to 100%
- notifications: providers/service tests
- services: profile_preference_service
- docs/orthogonal-test-report.md — full speckit.tests audit
- Fixes: 3 git_base async mock failures, 4 assistant handler permission-check patches
- .gitignore: coverage artifacts
2026-06-15 15:38:59 +03:00

163 lines
6.8 KiB
Python

# #region Test.PreviewSessionOps [C:3] [TYPE Module] [SEMANTICS test, translate, preview, session, query]
# @BRIEF Tests for preview_session_ops.py — get_preview_session.
# @RELATION BINDS_TO -> [preview_session_ops]
# @TEST_CONTRACT: get_preview_session -> dict | returns latest session with records
# @TEST_EDGE: no_session_found -> raises ValueError
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "src"))
import os
os.environ.setdefault("SECRET_KEY", "test-secret-key-for-testing")
os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:")
os.environ.setdefault("AUTH_DATABASE_URL", "sqlite:///:memory:")
from datetime import datetime, timezone
from unittest.mock import MagicMock, patch
import pytest
from src.plugins.translate.preview_session_ops import get_preview_session
class TestGetPreviewSession:
"""get_preview_session — fetch latest preview session for a job."""
def _make_session(self, overrides: dict | None = None) -> MagicMock:
"""Create a mock preview session."""
session = MagicMock()
session.id = "session-1"
session.job_id = "job-1"
session.status = "APPLIED"
session.created_by = "user-1"
session.created_at = datetime(2026, 1, 15, 12, 0, 0, tzinfo=timezone.utc)
session.expires_at = datetime(2026, 2, 15, 12, 0, 0, tzinfo=timezone.utc)
if overrides:
for k, v in overrides.items():
setattr(session, k, v)
return session
def _make_record(self) -> MagicMock:
"""Create a mock preview record."""
r = MagicMock()
r.id = "rec-1"
r.source_sql = "SELECT * FROM foo"
r.target_sql = "SELECT * FROM bar"
r.source_object_type = "table"
r.source_object_id = "obj-1"
r.source_object_name = "foo"
r.status = "done"
r.feedback = None
r.languages = []
return r
def _make_job(self, target_languages=None, target_dialect=None) -> MagicMock:
"""Create a mock translation job."""
job = MagicMock()
job.id = "job-1"
job.target_languages = target_languages if target_languages is not None else ["ru", "de"]
job.target_dialect = target_dialect if target_dialect else "clickhouse"
return job
def _setup_db_mock(self, session, records, job):
"""Configure db mock chain for the three queries in get_preview_session."""
db = MagicMock()
# Query 1: TranslationPreviewSession (filter + order_by + first)
db.query.return_value.filter.return_value.order_by.return_value.first.return_value = session
# Query 2: TranslationPreviewRecord (filter + all)
db.query.return_value.filter.return_value.all.return_value = records
# Query 3: TranslationJob (filter + first — no order_by)
db.query.return_value.filter.return_value.first.return_value = job
return db
def test_returns_session_with_records(self):
"""Returns session dict with serialized records."""
session = self._make_session()
record = self._make_record()
job = self._make_job()
db = self._setup_db_mock(session, [record], job)
with patch("src.plugins.translate.preview_session_ops._serialize_preview_record") as mock_ser:
mock_ser.return_value = {"id": "rec-1", "source_sql": "SELECT * FROM foo"}
result = get_preview_session(db, "job-1")
assert result["id"] == "session-1"
assert result["job_id"] == "job-1"
assert result["status"] == "APPLIED"
assert result["created_by"] == "user-1"
assert "created_at" in result
assert "expires_at" in result
assert result["target_languages"] == ["ru", "de"]
assert len(result["records"]) == 1
assert result["records"][0]["id"] == "rec-1"
def test_no_session_found_raises(self):
"""No session found raises ValueError."""
db = MagicMock()
db.query.return_value.filter.return_value.order_by.return_value.first.return_value = None
with pytest.raises(ValueError, match="No preview session found for job 'job-1'"):
get_preview_session(db, "job-1")
def test_job_not_found_defaults_to_en(self):
"""Job not found falls back to ['en'] (last fallback)."""
session = self._make_session()
db = MagicMock()
db.query.return_value.filter.return_value.order_by.return_value.first.return_value = session
db.query.return_value.filter.return_value.all.return_value = []
# No job found -> first (no order_by) returns None
db.query.return_value.filter.return_value.first.return_value = None
with patch("src.plugins.translate.preview_session_ops._serialize_preview_record") as mock_ser:
result = get_preview_session(db, "job-1")
# When job is None -> the fallback is ["en"]
assert result["target_languages"] == ["en"]
def test_job_no_target_languages_uses_dialect(self):
"""Job with None target_languages uses target_dialect."""
session = self._make_session()
job = self._make_job(target_dialect="postgresql")
job.target_languages = None # explicitly override to None
db = self._setup_db_mock(session, [], job)
with patch("src.plugins.translate.preview_session_ops._serialize_preview_record") as mock_ser:
result = get_preview_session(db, "job-1")
assert result["target_languages"] == ["postgresql"]
def test_target_languages_not_list_normalized(self):
"""target_languages that is not a list gets wrapped in list."""
session = self._make_session()
job = self._make_job(target_languages="ru") # string instead of list
db = self._setup_db_mock(session, [], job)
with patch("src.plugins.translate.preview_session_ops._serialize_preview_record") as mock_ser:
result = get_preview_session(db, "job-1")
assert result["target_languages"] == ["ru"]
def test_session_expires_at_none(self):
"""Session without expires_at returns None for that field."""
session = self._make_session({"expires_at": None})
job = self._make_job()
db = self._setup_db_mock(session, [], job)
with patch("src.plugins.translate.preview_session_ops._serialize_preview_record") as mock_ser:
result = get_preview_session(db, "job-1")
assert result["expires_at"] is None
def test_empty_records(self):
"""No records returns empty records list."""
session = self._make_session()
job = self._make_job()
db = self._setup_db_mock(session, [], job)
with patch("src.plugins.translate.preview_session_ops._serialize_preview_record"):
result = get_preview_session(db, "job-1")
assert result["records"] == []
# #endregion Test.PreviewSessionOps