Files
ss-tools/backend/tests/plugins/translate/test_dictionary_entries.py
busya 8a4310169b v4: 7643 tests passing, 83% raw / 96.9% real coverage (excl __tests__).
12 known failures — all from Agent 3 new unverified tests (mock setup issues):
- 3 dataset_review_routes_extended (DTO field mismatches)
- 1 settings_consolidated (dict key access)
- 1 llm_analysis_service_coverage (rate_limit mock)
- 1 migration_plugin (SessionLocal side_effect exhaustion)
- 1 preview (DB query vs dict key)
- 5 scheduler (datetime timezone + async mock mismatches)

NEW TEST FILES THIS SESSION:
- test_batch_insert_coverage.py — 3 tests
- test_storage_plugin.py — +3 tests
- test_search.py — +2 tests
- test_mapper.py — already 100%
- test_llm_analysis_migration_v1_to_v2.py — 14 tests
- test_llm_async_http.py — +1 test
- test_prompt_builder.py — +1 test
- test_service_datasource.py — +1 test
- test_lang_detect.py — +1 test
- test_scheduler.py — +6 tests
- test_llm_analysis_service_coverage.py — +15 tests
- test_dataset_review_routes_extended.py — +14 tests
- test_settings_consolidated.py — +13 tests

Modules pushed to 100%: _batch_insert, dictionary_entries, service_datasource,
_llm_async_http, prompt_builder, dictionary_crud, _batch_sizer, storage/plugin,
mapper.py

Session: 7194→7643 tests (+449), 80%→83% raw (+3pp), 93.4%→96.9% real (+3.5pp).
Remaining: 12 failures to fix + ~300 statements to reach 98% real coverage.
2026-06-16 09:34:10 +03:00

280 lines
10 KiB
Python

# #region Test.DictionaryEntryCRUD [C:3] [TYPE Module] [SEMANTICS test,dictionary,entries,crud]
# @BRIEF Tests for dictionary_entries.py — DictionaryEntryCRUD.
# @RELATION BINDS_TO -> [DictionaryEntryCRUD]
# @TEST_EDGE: duplicate_entry -> ValueError
# @TEST_EDGE: entry_not_found -> ValueError
# @TEST_EDGE: invalid_regex -> ValueError
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "src"))
import pytest
from unittest.mock import MagicMock
from src.models.translate import DictionaryEntry, TerminologyDictionary
from src.plugins.translate.dictionary_entries import DictionaryEntryCRUD
class TestAddEntry:
"""DictionaryEntryCRUD.add_entry."""
def test_add_basic(self, db_session):
"""Basic add creates entry."""
dict_entry = TerminologyDictionary(id="dict-add-1", name="Test Dict", is_active=True)
db_session.add(dict_entry)
db_session.commit()
entry = DictionaryEntryCRUD.add_entry(
db_session, "dict-add-1", "hello", "bonjour",
source_language="en", target_language="fr",
)
assert entry.source_term == "hello"
assert entry.target_term == "bonjour"
assert entry.source_language == "en"
assert entry.target_language == "fr"
def test_add_with_context_notes(self, db_session):
"""Context notes are stripped."""
dict_entry = TerminologyDictionary(id="dict-add-ctx", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
entry = DictionaryEntryCRUD.add_entry(
db_session, "dict-add-ctx", "hello", "bonjour",
context_notes=" formal greeting ",
)
assert entry.context_notes == "formal greeting"
def test_duplicate_raises(self, db_session):
"""Duplicate entry raises ValueError."""
dict_entry = TerminologyDictionary(id="dict-add-dup", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
DictionaryEntryCRUD.add_entry(
db_session, "dict-add-dup", "hello", "bonjour",
source_language="en", target_language="fr",
)
with pytest.raises(ValueError, match="Duplicate"):
DictionaryEntryCRUD.add_entry(
db_session, "dict-add-dup", "hello", "salut",
source_language="en", target_language="fr",
)
def test_invalid_source_language(self, db_session):
"""Invalid source_language raises ValueError."""
dict_entry = TerminologyDictionary(id="dict-add-lang", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
with pytest.raises(ValueError, match="source_language"):
DictionaryEntryCRUD.add_entry(
db_session, "dict-add-lang", "hello", "bonjour",
source_language="invalid!",
)
def test_invalid_regex_raises(self, db_session):
"""Invalid regex source_term raises ValueError."""
dict_entry = TerminologyDictionary(id="dict-add-regex", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
with pytest.raises(ValueError, match="Invalid regex"):
DictionaryEntryCRUD.add_entry(
db_session, "dict-add-regex", r"[invalid", "bonjour",
is_regex=True,
)
def test_valid_regex(self, db_session):
"""Valid regex is accepted."""
dict_entry = TerminologyDictionary(id="dict-add-regex2", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
entry = DictionaryEntryCRUD.add_entry(
db_session, "dict-add-regex2", r"\d+", "NUMBER",
is_regex=True,
)
assert entry.is_regex is True
def test_duplicate_different_language_passes(self, db_session):
"""Same source term with different language pair is OK."""
dict_entry = TerminologyDictionary(id="dict-add-diff", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
DictionaryEntryCRUD.add_entry(
db_session, "dict-add-diff", "hello", "bonjour",
source_language="en", target_language="fr",
)
entry = DictionaryEntryCRUD.add_entry(
db_session, "dict-add-diff", "hello", "hola",
source_language="en", target_language="es",
)
assert entry.target_term == "hola"
class TestEditEntry:
"""DictionaryEntryCRUD.edit_entry."""
def _setup(self, db_session):
dict_entry = TerminologyDictionary(id="dict-edit-1", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
entry = DictionaryEntryCRUD.add_entry(
db_session, "dict-edit-1", "hello", "bonjour",
source_language="en", target_language="fr",
)
return entry
def test_edit_target_term(self, db_session):
"""Edit target_term."""
entry = self._setup(db_session)
updated = DictionaryEntryCRUD.edit_entry(
db_session, entry.id, target_term="salut"
)
assert updated.target_term == "salut"
def test_edit_source_term(self, db_session):
"""Edit source_term with duplicate check."""
entry = self._setup(db_session)
updated = DictionaryEntryCRUD.edit_entry(
db_session, entry.id, source_term="hi"
)
assert updated.source_term == "hi"
def test_edit_languages(self, db_session):
"""Edit source_language and target_language."""
entry = self._setup(db_session)
updated = DictionaryEntryCRUD.edit_entry(
db_session, entry.id,
source_language="es", target_language="de",
)
assert updated.source_language == "es"
assert updated.target_language == "de"
def test_edit_not_found(self, db_session):
"""Non-existent entry raises ValueError."""
with pytest.raises(ValueError, match="Entry not found"):
DictionaryEntryCRUD.edit_entry(db_session, "nonexistent", source_term="x")
def test_edit_context_notes(self, db_session):
"""Edit context_notes to None."""
entry = self._setup(db_session)
updated = DictionaryEntryCRUD.edit_entry(
db_session, entry.id, context_notes=""
)
assert updated.context_notes is None
def test_edit_duplicate_source_term_raises(self, db_session):
"""Changing source_term to an existing one raises."""
entry1 = self._setup(db_session)
entry2 = DictionaryEntryCRUD.add_entry(
db_session, "dict-edit-1", "world", "monde",
source_language="en", target_language="fr",
)
with pytest.raises(ValueError, match="Duplicate"):
DictionaryEntryCRUD.edit_entry(
db_session, entry2.id, source_term="hello"
)
def test_edit_is_regex(self, db_session):
"""Edit is_regex flag."""
entry = self._setup(db_session)
updated = DictionaryEntryCRUD.edit_entry(
db_session, entry.id, is_regex=True
)
assert updated.is_regex is True
def test_edit_regex_source_term_validation(self, db_session):
"""Setting source_term to invalid regex when entry is regex raises."""
entry = self._setup(db_session)
DictionaryEntryCRUD.edit_entry(db_session, entry.id, is_regex=True)
with pytest.raises(ValueError, match="Invalid regex"):
DictionaryEntryCRUD.edit_entry(
db_session, entry.id, source_term=r"[invalid"
)
class TestDeleteEntry:
"""DictionaryEntryCRUD.delete_entry."""
def _setup(self, db_session):
dict_entry = TerminologyDictionary(id="dict-del-1", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
entry = DictionaryEntryCRUD.add_entry(
db_session, "dict-del-1", "hello", "bonjour",
)
return entry
def test_delete(self, db_session):
"""Delete existing entry."""
entry = self._setup(db_session)
entry_id = entry.id
DictionaryEntryCRUD.delete_entry(db_session, entry_id)
assert db_session.query(DictionaryEntry).filter(DictionaryEntry.id == entry_id).first() is None
def test_delete_not_found(self, db_session):
"""Delete non-existent entry raises ValueError."""
with pytest.raises(ValueError, match="Entry not found"):
DictionaryEntryCRUD.delete_entry(db_session, "nonexistent")
class TestClearEntries:
"""DictionaryEntryCRUD.clear_entries."""
def test_clear(self, db_session):
"""Clear all entries for a dictionary."""
dict_entry = TerminologyDictionary(id="dict-clear-1", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
DictionaryEntryCRUD.add_entry(db_session, "dict-clear-1", "hello", "bonjour")
DictionaryEntryCRUD.add_entry(db_session, "dict-clear-1", "world", "monde")
deleted = DictionaryEntryCRUD.clear_entries(db_session, "dict-clear-1")
assert deleted == 2
def test_clear_dictionary_not_found(self, db_session):
"""Clear non-existent dictionary raises ValueError."""
with pytest.raises(ValueError, match="Dictionary not found"):
DictionaryEntryCRUD.clear_entries(db_session, "nonexistent")
class TestListEntries:
"""DictionaryEntryCRUD.list_entries."""
def test_list_pagination(self, db_session):
"""List with pagination."""
dict_entry = TerminologyDictionary(id="dict-list-1", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
for i in range(5):
DictionaryEntryCRUD.add_entry(
db_session, "dict-list-1", f"term{i}", f"trans{i}",
)
entries, total = DictionaryEntryCRUD.list_entries(db_session, "dict-list-1", page=1, page_size=2)
assert len(entries) == 2
assert total == 5
def test_list_empty(self, db_session):
"""Empty dictionary returns empty list."""
dict_entry = TerminologyDictionary(id="dict-list-empty", name="Test", is_active=True)
db_session.add(dict_entry)
db_session.commit()
entries, total = DictionaryEntryCRUD.list_entries(db_session, "dict-list-empty")
assert entries == []
assert total == 0
# #endregion Test.DictionaryEntryCRUD