"""Tests for SQLAlchemy model definitions. These tests verify model structure without needing a database connection. """ from sqlalchemy import inspect from src.models import ( Base, ConsentRecord, Cookie, CookieAllowListEntry, CookieCategory, KnownCookie, Organisation, ScanJob, ScanResult, Site, SiteConfig, Translation, User, ) def test_all_models_registered_in_metadata(): """All expected tables should be present in Base.metadata.""" table_names = set(Base.metadata.tables.keys()) expected = { "organisations", "users", "sites", "site_configs", "cookie_categories", "cookies", "cookie_allow_list", "known_cookies", "consent_records", "scan_jobs", "scan_results", "translations", } assert expected.issubset(table_names), f"Missing tables: {expected - table_names}" def test_organisation_columns(): mapper = inspect(Organisation) column_names = {c.key for c in mapper.columns} assert "id" in column_names assert "name" in column_names assert "slug" in column_names assert "contact_email" in column_names assert "billing_plan" in column_names assert "created_at" in column_names assert "updated_at" in column_names assert "deleted_at" in column_names def test_user_columns_and_fk(): mapper = inspect(User) column_names = {c.key for c in mapper.columns} assert "organisation_id" in column_names assert "email" in column_names assert "password_hash" in column_names assert "role" in column_names def test_site_unique_constraint(): table = Site.__table__ constraint_names = {c.name for c in table.constraints if hasattr(c, "name") and c.name} assert "uq_sites_org_domain" in constraint_names def test_site_config_jsonb_fields(): mapper = inspect(SiteConfig) column_names = {c.key for c in mapper.columns} for field in ["regional_modes", "gcm_default", "banner_config"]: assert field in column_names, f"Missing JSONB field: {field}" def test_cookie_category_columns(): mapper = inspect(CookieCategory) column_names = {c.key for c in mapper.columns} assert "tcf_purpose_ids" in column_names assert "gcm_consent_types" in column_names assert "is_essential" in column_names def test_cookie_unique_constraint(): table = Cookie.__table__ constraint_names = {c.name for c in table.constraints if hasattr(c, "name") and c.name} assert "uq_cookies_site_name_domain_type" in constraint_names def test_cookie_allow_list_unique_constraint(): table = CookieAllowListEntry.__table__ constraint_names = {c.name for c in table.constraints if hasattr(c, "name") and c.name} assert "uq_allow_list_site_name_domain" in constraint_names def test_known_cookie_unique_constraint(): table = KnownCookie.__table__ constraint_names = {c.name for c in table.constraints if hasattr(c, "name") and c.name} assert "uq_known_cookies_name_domain" in constraint_names def test_consent_record_columns(): mapper = inspect(ConsentRecord) column_names = {c.key for c in mapper.columns} for field in [ "visitor_id", "action", "categories_accepted", "tc_string", "gcm_state", "country_code", "consented_at", ]: assert field in column_names, f"Missing field: {field}" def test_scan_job_columns(): mapper = inspect(ScanJob) column_names = {c.key for c in mapper.columns} assert "status" in column_names assert "pages_scanned" in column_names assert "cookies_found" in column_names def test_scan_result_columns(): mapper = inspect(ScanResult) column_names = {c.key for c in mapper.columns} assert "page_url" in column_names assert "cookie_name" in column_names assert "script_source" in column_names assert "auto_category" in column_names def test_translation_unique_constraint(): table = Translation.__table__ constraint_names = {c.name for c in table.constraints if hasattr(c, "name") and c.name} assert "uq_translations_site_locale" in constraint_names def test_uuid_primary_keys(): """All models should use UUID primary keys.""" models = [ Organisation, User, Site, SiteConfig, CookieCategory, Cookie, CookieAllowListEntry, KnownCookie, ConsentRecord, ScanJob, ScanResult, Translation, ] for model in models: mapper = inspect(model) pk_cols = mapper.primary_key assert len(pk_cols) == 1, f"{model.__name__} should have exactly one PK column" assert str(pk_cols[0].type) == "UUID", ( f"{model.__name__} PK should be UUID, got {pk_cols[0].type}" )