# #region Test.DictionaryCRUD [C:3] [TYPE Module] [SEMANTICS test,dictionary,crud] # @BRIEF Tests for dictionary_crud.py — DictionaryCRUD. # @RELATION BINDS_TO -> [DictionaryCRUD] # @TEST_EDGE: not_found -> ValueError # @TEST_EDGE: delete_blocked_by_active_jobs -> 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, TranslationJob, TranslationJobDictionary, ) from src.plugins.translate.dictionary_crud import DictionaryCRUD from .conftest import JOB_ID class TestCreateDictionary: """DictionaryCRUD.create_dictionary.""" def test_create_basic(self, db_session): """Creates a new dictionary.""" d = DictionaryCRUD.create_dictionary(db_session, "My Dict", created_by="test") assert d.name == "My Dict" assert d.created_by == "test" assert d.is_active is True assert d.id is not None def test_create_with_description(self, db_session): """Creates with description.""" d = DictionaryCRUD.create_dictionary( db_session, "My Dict", description="Test dictionary", ) assert d.description == "Test dictionary" def test_create_inactive(self, db_session): """Creates inactive dictionary.""" d = DictionaryCRUD.create_dictionary( db_session, "My Dict", is_active=False, ) assert d.is_active is False class TestUpdateDictionary: """DictionaryCRUD.update_dictionary.""" def test_update_name(self, db_session): """Update name.""" d = DictionaryCRUD.create_dictionary(db_session, "Original") updated = DictionaryCRUD.update_dictionary(db_session, d.id, name="Updated") assert updated.name == "Updated" def test_update_description(self, db_session): """Update description.""" d = DictionaryCRUD.create_dictionary(db_session, "Test") updated = DictionaryCRUD.update_dictionary(db_session, d.id, description="New desc") assert updated.description == "New desc" def test_update_is_active(self, db_session): """Update is_active.""" d = DictionaryCRUD.create_dictionary(db_session, "Test", is_active=True) updated = DictionaryCRUD.update_dictionary(db_session, d.id, is_active=False) assert updated.is_active is False def test_update_not_found(self, db_session): """Update non-existent raises ValueError.""" with pytest.raises(ValueError, match="not found"): DictionaryCRUD.update_dictionary(db_session, "nonexistent", name="x") def test_update_partial(self, db_session): """Partial update doesn't change other fields.""" d = DictionaryCRUD.create_dictionary( db_session, "Original", description="Desc", is_active=True, ) updated = DictionaryCRUD.update_dictionary(db_session, d.id, name="New") assert updated.description == "Desc" assert updated.is_active is True class TestDeleteDictionary: """DictionaryCRUD.delete_dictionary.""" def test_delete(self, db_session): """Delete a dictionary without attached jobs.""" d = DictionaryCRUD.create_dictionary(db_session, "To Delete") dict_id = d.id # Add some entries from src.plugins.translate.dictionary_entries import DictionaryEntryCRUD DictionaryEntryCRUD.add_entry(db_session, dict_id, "hello", "bonjour") DictionaryCRUD.delete_dictionary(db_session, dict_id) assert db_session.query(TerminologyDictionary).filter(TerminologyDictionary.id == dict_id).first() is None # Entries should also be deleted entries = db_session.query(DictionaryEntry).filter(DictionaryEntry.dictionary_id == dict_id).all() assert len(entries) == 0 def test_not_found(self, db_session): """Delete non-existent raises ValueError.""" with pytest.raises(ValueError, match="not found"): DictionaryCRUD.delete_dictionary(db_session, "nonexistent") def test_delete_blocked_by_active_job(self, db_session): """Delete blocked when attached to active job.""" d = DictionaryCRUD.create_dictionary(db_session, "Blocked Dict") dict_id = d.id # Attach to the existing job from src.models.translate import TranslationJobDictionary job = db_session.query(TranslationJob).filter(TranslationJob.id == JOB_ID).first() job.status = "ACTIVE" db_session.commit() tj_dict = TranslationJobDictionary(job_id=JOB_ID, dictionary_id=dict_id) db_session.add(tj_dict) db_session.commit() with pytest.raises(ValueError, match="Cannot delete dictionary attached"): DictionaryCRUD.delete_dictionary(db_session, dict_id) def test_delete_blocked_by_scheduled_job(self, db_session): """Delete blocked when attached to SCHEDULED job.""" d = DictionaryCRUD.create_dictionary(db_session, "Scheduled Dict") dict_id = d.id job = db_session.query(TranslationJob).filter(TranslationJob.id == JOB_ID).first() job.status = "SCHEDULED" db_session.commit() tj_dict = TranslationJobDictionary(job_id=JOB_ID, dictionary_id=dict_id) db_session.add(tj_dict) db_session.commit() with pytest.raises(ValueError, match="Cannot delete dictionary attached"): DictionaryCRUD.delete_dictionary(db_session, dict_id) def test_delete_with_completed_job_ok(self, db_session): """Delete OK when attached to COMPLETED job.""" d = DictionaryCRUD.create_dictionary(db_session, "Completed Dict") dict_id = d.id job = db_session.query(TranslationJob).filter(TranslationJob.id == JOB_ID).first() job.status = "COMPLETED" db_session.commit() tj_dict = TranslationJobDictionary(job_id=JOB_ID, dictionary_id=dict_id) db_session.add(tj_dict) db_session.commit() DictionaryCRUD.delete_dictionary(db_session, dict_id) assert db_session.query(TerminologyDictionary).filter(TerminologyDictionary.id == dict_id).first() is None class TestGetDictionary: """DictionaryCRUD.get_dictionary.""" def test_get(self, db_session): """Get existing dictionary.""" d = DictionaryCRUD.create_dictionary(db_session, "Get Test") fetched = DictionaryCRUD.get_dictionary(db_session, d.id) assert fetched.id == d.id assert fetched.name == "Get Test" def test_not_found(self, db_session): """Get non-existent raises ValueError.""" with pytest.raises(ValueError, match="not found"): DictionaryCRUD.get_dictionary(db_session, "nonexistent") class TestListDictionaries: """DictionaryCRUD.list_dictionaries.""" def test_list(self, db_session): """List with pagination.""" for i in range(5): DictionaryCRUD.create_dictionary(db_session, f"Dict {i}") dicts, total = DictionaryCRUD.list_dictionaries(db_session, page=1, page_size=2) assert len(dicts) == 2 assert total == 5 def test_empty(self, db_session): """Empty list returns [] and 0.""" dicts, total = DictionaryCRUD.list_dictionaries(db_session) assert dicts == [] assert total == 0 # #endregion Test.DictionaryCRUD