"""Contact model ownership tests - Paket 6 (#357). Beweist: Contact/ContactPerson leben physisch im ContactsPlugin (models.py), app/models/contact.py ist nur noch eine Re-Export-Bruecke (Kompatibilitaet fuer Alembic env.py, Core-Services, Tests) und die contacts/contactpersons-Tabellen bleiben Alembic-owned (kein Plugin-Schema-Sync-Dual-Ownership). """ from __future__ import annotations class TestContactModelOwnership: """Contact/ContactPerson sind physisch im ContactsPlugin beheimatet.""" def test_contact_class_owned_by_contacts_plugin(self): """Contact.__module__ zeigt auf das Plugin, nicht auf app.models.""" from app.models.contact import Contact assert Contact.__module__ == "app.plugins.builtins.contacts.models" def test_contact_person_class_owned_by_contacts_plugin(self): """ContactPerson.__module__ zeigt auf das Plugin.""" from app.models.contact import ContactPerson assert ContactPerson.__module__ == "app.plugins.builtins.contacts.models" def test_plugin_models_module_importable_directly(self): """Das Plugin-Modul ist direkt importierbar (Vorbild: mail.models).""" from app.plugins.builtins.contacts.models import Contact, ContactPerson assert Contact.__tablename__ == "contacts" assert ContactPerson.__tablename__ == "contactpersons" def test_shim_identity_same_class_objects(self): """Shim-Import und Plugin-Import liefern dieselbe Klasse (kein Duplikat).""" from app.models.contact import Contact as ViaShim from app.plugins.builtins.contacts.models import Contact as ViaPlugin assert ViaShim is ViaPlugin class TestAlembicMetadataIntegrity: """Base.metadata bleibt nach dem Move vollstaendig (Alembic-Sicherheit).""" def test_contacts_table_in_base_metadata(self): """contacts/contactpersons sind in Base.metadata registriert. env.py laedt from app.models import * - ohne funktionierenden Re-Export wuerde Alembic-Autogenerate die Tabellen als entfernt betrachten (DROP). """ from app.core.db import Base assert "contacts" in Base.metadata.tables assert "contactpersons" in Base.metadata.tables def test_models_package_export_unchanged(self): """from app.models import Contact funktioniert weiter (env.py-Signal).""" import app.models assert app.models.Contact is not None assert app.models.ContactPerson is not None class TestSyncPluginSchemaExclude: """contacts/contactpersons bleiben Alembic-owned, kein Plugin-Sync.""" def test_alembic_owned_tables_constant_declares_contacts(self): """sync_plugin_schema deklariert contacts/contactpersons als Alembic-owned. Der __module__-Filter des Scripts wuerde nach dem Move sonst die Alembic-verwalteten Tabellen in den Plugin-Schema-Sync-Kanal ziehen (Dual-Ownership -> Schema-Drift gegen 142 Migrationen). """ from scripts.sync_plugin_schema import ALEMBIC_OWNED_TABLES assert "contacts" in ALEMBIC_OWNED_TABLES assert "contactpersons" in ALEMBIC_OWNED_TABLES class TestCoreImportCompatibility: """Bestehende Core-Import-Stellen funktionieren ueber den Shim weiter.""" def test_core_worker_imports_contact(self): """app.core.worker (dokumentierter P16-Fall) importiert Contact weiter.""" from app.models.contact import Contact # noqa: F401 def test_contact_merge_fk_resolves(self): """FK-Kette contact_merge_history -> contacts loest sich weiter auf.""" from app.core.db import Base merge = Base.metadata.tables["contact_merge_history"] fk_targets = {fk.target_fullname for fk in merge.foreign_keys} assert "contacts.id" in fk_targets