# #region Test.Core.Database [C:3] [TYPE Module] [SEMANTICS test,database,core]
# @BRIEF Verify DatabaseModule — engine creation, session lifecycle, additive migrations, init_db.
# @RELATION BINDS_TO -> [DatabaseModule]
# @TEST_EDGE: table_not_exists -> migration returns early
# @TEST_EDGE: columns_present -> no ALTER executed
# @TEST_EDGE: migration_failure -> exception handled per function contract
import sys
from pathlib import Path
from unittest.mock import MagicMock, patch
import contextlib
import pytest

sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent / "src"))
from src.core.database import (
    BASE_DIR, _build_engine, init_db, get_db, get_tasks_db, get_auth_db,
    _ensure_user_dashboard_preferences_columns,
    _ensure_user_dashboard_preferences_health_columns,
    _ensure_llm_validation_results_columns,
    _ensure_git_server_configs_columns,
    _ensure_auth_users_columns,
    _ensure_roles_is_admin_column,
    _ensure_filter_source_enum_values,
    _ensure_translation_jobs_columns,
    _ensure_dataset_review_session_columns,
    _ensure_translation_schedules_columns,
    _ensure_dictionary_entries_columns,
)

class _FakeCM:
    def __init__(self, conn): self._conn = conn
    def __enter__(self): return self._conn
    def __exit__(self, *a): return False

_NOOP = contextlib.contextmanager(lambda id, msg="": (yield))
_P = "src.core.database"

def _insp(tables=None, cols=None):
    m = MagicMock()
    m.get_table_names.return_value = tables or []
    m.get_columns.return_value = [{"name": c} for c in (cols or [])]
    return m

def _eng():
    e, c = MagicMock(), MagicMock()
    e.begin.return_value = _FakeCM(c)
    e.connect.return_value = _FakeCM(c)
    return e, c

# ═══════════════════════════════════════════════════════════════════════════
# Engine creation & constants
# ═══════════════════════════════════════════════════════════════════════════

# #region test_build_engine [C:2] [TYPE Function]
# @BRIEF SQLite gets check_same_thread; Postgres gets pool_pre_ping.
@patch(f"{_P}.create_engine")
def test_build_engine(mock_ce):
    with patch(f"{_P}.belief_scope", _NOOP):
        _build_engine("sqlite:///t.db")
        _build_engine("postgresql://u:p@h/d")
    assert mock_ce.call_args_list[0].kwargs == {"connect_args": {"check_same_thread": False}}
    assert mock_ce.call_args_list[1].kwargs == {"pool_pre_ping": True}
# #endregion test_build_engine

# #region test_base_dir [C:2] [TYPE Function]
# @BRIEF BASE_DIR resolves to backend root.
def test_base_dir():
    assert BASE_DIR == Path(__file__).resolve().parent.parent.parent
# #endregion test_base_dir

# ═══════════════════════════════════════════════════════════════════════════
# Parametrized migration tests
# ═══════════════════════════════════════════════════════════════════════════

# #region test_migration_table_missing [C:2] [TYPE Function]
# @BRIEF All migration functions return early when table absent.
@pytest.mark.parametrize("fn,table", [
    (_ensure_user_dashboard_preferences_columns, "user_dashboard_preferences"),
    (_ensure_user_dashboard_preferences_health_columns, "user_dashboard_preferences"),
    (_ensure_llm_validation_results_columns, "llm_validation_results"),
    (_ensure_git_server_configs_columns, "git_server_configs"),
    (_ensure_auth_users_columns, "users"),
    (_ensure_roles_is_admin_column, "roles"),
    (_ensure_translation_jobs_columns, "translation_jobs"),
    (_ensure_translation_schedules_columns, "translation_schedules"),
    (_ensure_dictionary_entries_columns, "dictionary_entries"),
])
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_migration_table_missing(mock_inspect, fn, table):
    mock_inspect.return_value = _insp(tables=[])
    eng = MagicMock()
    fn(eng)
    eng.begin.assert_not_called()
# #endregion test_migration_table_missing

# #region test_pref_columns_add [C:2] [TYPE Function]
# @BRIEF Adds 6 missing columns to user_dashboard_preferences.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_pref_columns_add(mock_inspect, _):
    mock_inspect.return_value = _insp(["user_dashboard_preferences"], ["git_username"])
    eng, conn = _eng()
    _ensure_user_dashboard_preferences_columns(eng)
    assert conn.execute.call_count == 6
# #endregion test_pref_columns_add

# #region test_pref_columns_all_present [C:2] [TYPE Function]
# @BRIEF No ALTER when all 7 pref columns exist.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_pref_columns_all_present(mock_inspect):
    cols = ["git_username","git_email","git_personal_access_token_encrypted",
            "start_page","auto_open_task_drawer","dashboards_table_density","show_only_slug_dashboards"]
    mock_inspect.return_value = _insp(["user_dashboard_preferences"], cols)
    eng = MagicMock()
    _ensure_user_dashboard_preferences_columns(eng)
    eng.begin.assert_not_called()
# #endregion test_pref_columns_all_present

# #region test_pref_failure_swallowed [C:2] [TYPE Function]
# @BRIEF Exception during pref migration is logged, not re-raised.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("boom"))
@patch(f"{_P}.inspect")
def test_pref_failure_swallowed(mock_inspect, _):
    mock_inspect.return_value = _insp(["user_dashboard_preferences"], [])
    eng, _ = _eng()
    _ensure_user_dashboard_preferences_columns(eng)  # must not raise
# #endregion test_pref_failure_swallowed

# #region test_health_columns [C:2] [TYPE Function]
# @BRIEF Health columns: add 3 when missing, skip when present, swallow errors.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_health_columns(mock_inspect, _):
    mock_inspect.return_value = _insp(["user_dashboard_preferences"], [])
    eng, conn = _eng()
    _ensure_user_dashboard_preferences_health_columns(eng)
    assert conn.execute.call_count == 3
# #endregion test_health_columns

# #region test_health_all_present [C:2] [TYPE Function]
# @BRIEF No ALTER when all health columns exist.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_health_all_present(mock_inspect):
    mock_inspect.return_value = _insp(["user_dashboard_preferences"],
        ["telegram_id","email_address","notify_on_fail"])
    eng = MagicMock()
    _ensure_user_dashboard_preferences_health_columns(eng)
    eng.begin.assert_not_called()
# #endregion test_health_all_present

# #region test_health_failure_swallowed [C:2] [TYPE Function]
# @BRIEF Health migration exception is logged, not re-raised.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("boom"))
@patch(f"{_P}.inspect")
def test_health_failure_swallowed(mock_inspect, _):
    mock_inspect.return_value = _insp(["user_dashboard_preferences"], [])
    eng, _ = _eng()
    _ensure_user_dashboard_preferences_health_columns(eng)
# #endregion test_health_failure_swallowed

# #region test_llm_columns [C:2] [TYPE Function]
# @BRIEF LLM validation: add 2 columns, skip when present, swallow errors.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_llm_columns(mock_inspect, _):
    mock_inspect.return_value = _insp(["llm_validation_results"], [])
    eng, conn = _eng()
    _ensure_llm_validation_results_columns(eng)
    assert conn.execute.call_count == 2
# #endregion test_llm_columns

# #region test_llm_all_present [C:2] [TYPE Function]
# @BRIEF No ALTER when task_id and environment_id exist.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_llm_all_present(mock_inspect):
    mock_inspect.return_value = _insp(["llm_validation_results"], ["task_id","environment_id"])
    eng = MagicMock()
    _ensure_llm_validation_results_columns(eng)
    eng.begin.assert_not_called()
# #endregion test_llm_all_present

# #region test_llm_failure_swallowed [C:2] [TYPE Function]
# @BRIEF LLM migration exception is logged, not re-raised.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("boom"))
@patch(f"{_P}.inspect")
def test_llm_failure_swallowed(mock_inspect, _):
    mock_inspect.return_value = _insp(["llm_validation_results"], [])
    eng, _ = _eng()
    _ensure_llm_validation_results_columns(eng)
# #endregion test_llm_failure_swallowed

# #region test_git_columns [C:2] [TYPE Function]
# @BRIEF Git configs: add default_branch, skip when present, swallow errors.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_git_columns(mock_inspect, _):
    mock_inspect.return_value = _insp(["git_server_configs"], [])
    eng, conn = _eng()
    _ensure_git_server_configs_columns(eng)
    assert conn.execute.call_count == 1
# #endregion test_git_columns

# #region test_git_all_present [C:2] [TYPE Function]
# @BRIEF No ALTER when default_branch exists.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_git_all_present(mock_inspect):
    mock_inspect.return_value = _insp(["git_server_configs"], ["default_branch"])
    eng = MagicMock()
    _ensure_git_server_configs_columns(eng)
    eng.begin.assert_not_called()
# #endregion test_git_all_present

# #region test_git_failure_swallowed [C:2] [TYPE Function]
# @BRIEF Git migration exception is logged, not re-raised.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("boom"))
@patch(f"{_P}.inspect")
def test_git_failure_swallowed(mock_inspect, _):
    mock_inspect.return_value = _insp(["git_server_configs"], [])
    eng, _ = _eng()
    _ensure_git_server_configs_columns(eng)
# #endregion test_git_failure_swallowed

# #region test_auth_users [C:2] [TYPE Function]
# @BRIEF Auth users: add 2 columns, skip when present, re-raise errors.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_auth_users(mock_inspect, _):
    mock_inspect.return_value = _insp(["users"], [])
    eng, conn = _eng()
    _ensure_auth_users_columns(eng)
    assert conn.execute.call_count == 2
# #endregion test_auth_users

# #region test_auth_users_all_present [C:2] [TYPE Function]
# @BRIEF No ALTER when full_name and is_ad_user exist.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_auth_users_all_present(mock_inspect):
    mock_inspect.return_value = _insp(["users"], ["full_name","is_ad_user"])
    eng = MagicMock()
    _ensure_auth_users_columns(eng)
    eng.begin.assert_not_called()
# #endregion test_auth_users_all_present

# #region test_auth_users_failure_reraises [C:2] [TYPE Function]
# @BRIEF Auth users migration exception is re-raised.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("db error"))
@patch(f"{_P}.inspect")
def test_auth_users_failure_reraises(mock_inspect, _):
    mock_inspect.return_value = _insp(["users"], [])
    eng, _ = _eng()
    with pytest.raises(RuntimeError, match="db error"):
        _ensure_auth_users_columns(eng)
# #endregion test_auth_users_failure_reraises

# #region test_roles [C:2] [TYPE Function]
# @BRIEF Roles: add is_admin + update Admin, skip when present, re-raise errors.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_roles(mock_inspect, _):
    mock_inspect.return_value = _insp(["roles"], [])
    eng, conn = _eng()
    _ensure_roles_is_admin_column(eng)
    assert conn.execute.call_count == 2  # ALTER + UPDATE
# #endregion test_roles

# #region test_roles_already_exists [C:2] [TYPE Function]
# @BRIEF No ALTER when is_admin present.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_roles_already_exists(mock_inspect):
    mock_inspect.return_value = _insp(["roles"], ["is_admin"])
    eng = MagicMock()
    _ensure_roles_is_admin_column(eng)
    eng.begin.assert_not_called()
# #endregion test_roles_already_exists

# #region test_roles_failure_reraises [C:2] [TYPE Function]
# @BRIEF Roles migration exception is re-raised.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("fail"))
@patch(f"{_P}.inspect")
def test_roles_failure_reraises(mock_inspect, _):
    mock_inspect.return_value = _insp(["roles"], [])
    eng, _ = _eng()
    with pytest.raises(RuntimeError, match="fail"):
        _ensure_roles_is_admin_column(eng)
# #endregion test_roles_failure_reraises

# #region test_filter_enum [C:2] [TYPE Function]
# @BRIEF FilterSource enum: skip if type missing, add missing values, swallow errors.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
def test_filter_enum(_):
    eng, conn = _eng()
    conn.execute.return_value = MagicMock(fetchone=MagicMock(return_value=None))
    _ensure_filter_source_enum_values(eng)  # type missing → skip
# #endregion test_filter_enum

# #region test_filter_enum_adds [C:2] [TYPE Function]
# @BRIEF Adds missing enum values when type exists.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
def test_filter_enum_adds(_):
    eng, conn = _eng()
    type_res = MagicMock(); type_res.fetchone.return_value = ("filtersource",)
    enum_res = MagicMock(); enum_res.fetchall.return_value = [("SUPERSET_PERMALINK",)]
    conn.execute.side_effect = [type_res, enum_res, MagicMock()]
    _ensure_filter_source_enum_values(eng)
    conn.commit.assert_called_once()
# #endregion test_filter_enum_adds

# #region test_filter_enum_complete [C:2] [TYPE Function]
# @BRIEF No ALTER TYPE when all enum values already present.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
def test_filter_enum_complete(_):
    eng, conn = _eng()
    type_res = MagicMock(); type_res.fetchone.return_value = ("filtersource",)
    enum_res = MagicMock(); enum_res.fetchall.return_value = [
        ("SUPERSET_PERMALINK",), ("SUPERSET_NATIVE_FILTERS_KEY",)]
    conn.execute.side_effect = [type_res, enum_res]
    _ensure_filter_source_enum_values(eng)
    conn.commit.assert_not_called()
# #endregion test_filter_enum_complete

# #region test_filter_enum_failure [C:2] [TYPE Function]
# @BRIEF Enum migration exception is swallowed.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("pg error"))
def test_filter_enum_failure(_):
    eng, _ = _eng()
    _ensure_filter_source_enum_values(eng)
# #endregion test_filter_enum_failure

# #region test_translation_jobs [C:2] [TYPE Function]
# @BRIEF Translation jobs: add 6 columns, skip when present, env_id re-raises.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_translation_jobs(mock_inspect, _):
    mock_inspect.return_value = _insp(["translation_jobs"], [])
    eng, conn = _eng()
    _ensure_translation_jobs_columns(eng)
    assert conn.execute.call_count == 6
# #endregion test_translation_jobs

# #region test_tj_all_present [C:2] [TYPE Function]
# @BRIEF No ALTER when all 6 translation_jobs columns exist.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_tj_all_present(mock_inspect):
    cols = ["environment_id","target_database_id","target_language_column",
            "target_source_column","target_source_language_column","disable_reasoning"]
    mock_inspect.return_value = _insp(["translation_jobs"], cols)
    eng = MagicMock()
    _ensure_translation_jobs_columns(eng)
    eng.begin.assert_not_called()
# #endregion test_tj_all_present

# #region test_tj_env_failure_reraises [C:2] [TYPE Function]
# @BRIEF environment_id failure re-raises.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_tj_env_failure_reraises(mock_inspect):
    mock_inspect.return_value = _insp(["translation_jobs"], [])
    eng = MagicMock()
    eng.begin.side_effect = RuntimeError("conn fail")
    with pytest.raises(RuntimeError, match="conn fail"):
        _ensure_translation_jobs_columns(eng)
# #endregion test_tj_env_failure_reraises

# #region test_tj_partial [C:2] [TYPE Function]
# @BRIEF Only adds missing columns (4 of 6).
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_tj_partial(mock_inspect, _):
    mock_inspect.return_value = _insp(["translation_jobs"],
        ["environment_id","target_database_id"])
    eng, conn = _eng()
    _ensure_translation_jobs_columns(eng)
    assert conn.execute.call_count == 4
# #endregion test_tj_partial

# #region test_tj_col_failure_swallowed [C:2] [TYPE Function]
# @BRIEF Non-env column failures are swallowed.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_tj_col_failure_swallowed(mock_inspect, _):
    mock_inspect.return_value = _insp(["translation_jobs"], ["environment_id"])
    eng, _ = _eng()
    eng.begin.side_effect = RuntimeError("fail")
    _ensure_translation_jobs_columns(eng)  # must not raise
# #endregion test_tj_col_failure_swallowed

# #region test_dataset_review [C:2] [TYPE Function]
# @BRIEF Dataset review: add 2 columns across 2 tables, re-raise errors.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_dataset_review(mock_inspect, _):
    mock_inspect.return_value = _insp(
        ["dataset_review_sessions","imported_filters"], [])
    eng, conn = _eng()
    _ensure_dataset_review_session_columns(eng)
    assert conn.execute.call_count == 2
# #endregion test_dataset_review

# #region test_dr_partial_tables [C:2] [TYPE Function]
# @BRIEF Skips missing tables, migrates existing ones.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_dr_partial_tables(mock_inspect, _):
    # Only dataset_review_sessions exists, imported_filters does not
    mock_inspect.return_value = _insp(["dataset_review_sessions"], [])
    eng, conn = _eng()
    _ensure_dataset_review_session_columns(eng)
    assert conn.execute.call_count == 1  # only version column for sessions
# #endregion test_dr_partial_tables

# #region test_dr_all_present [C:2] [TYPE Function]
# @BRIEF No ALTER when version and raw_value_masked exist.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_dr_all_present(mock_inspect):
    mock_inspect.return_value = _insp(
        ["dataset_review_sessions","imported_filters"], ["version","raw_value_masked"])
    eng = MagicMock()
    _ensure_dataset_review_session_columns(eng)
    eng.begin.assert_not_called()
# #endregion test_dr_all_present

# #region test_dr_failure_reraises [C:2] [TYPE Function]
# @BRIEF Dataset review migration exception is re-raised.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("fail"))
@patch(f"{_P}.inspect")
def test_dr_failure_reraises(mock_inspect, _):
    mock_inspect.return_value = _insp(
        ["dataset_review_sessions","imported_filters"], [])
    eng, _ = _eng()
    with pytest.raises(RuntimeError, match="fail"):
        _ensure_dataset_review_session_columns(eng)
# #endregion test_dr_failure_reraises

# #region test_schedules [C:2] [TYPE Function]
# @BRIEF Translation schedules: add execution_mode, skip when present, swallow errors.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_schedules(mock_inspect, _):
    mock_inspect.return_value = _insp(["translation_schedules"], [])
    eng, conn = _eng()
    _ensure_translation_schedules_columns(eng)
    assert conn.execute.call_count == 1
# #endregion test_schedules

# #region test_schedules_all_present [C:2] [TYPE Function]
# @BRIEF No ALTER when execution_mode exists.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_schedules_all_present(mock_inspect):
    mock_inspect.return_value = _insp(["translation_schedules"], ["execution_mode"])
    eng = MagicMock()
    _ensure_translation_schedules_columns(eng)
    eng.begin.assert_not_called()
# #endregion test_schedules_all_present

# #region test_schedules_failure [C:2] [TYPE Function]
# @BRIEF Schedules migration exception is swallowed.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("err"))
@patch(f"{_P}.inspect")
def test_schedules_failure(mock_inspect, _):
    mock_inspect.return_value = _insp(["translation_schedules"], [])
    eng, _ = _eng()
    _ensure_translation_schedules_columns(eng)
# #endregion test_schedules_failure

# #region test_dictionary [C:2] [TYPE Function]
# @BRIEF Dictionary entries: add 3 columns, skip when present, swallow errors.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=lambda s: s)
@patch(f"{_P}.inspect")
def test_dictionary(mock_inspect, _):
    mock_inspect.return_value = _insp(["dictionary_entries"], [])
    eng, conn = _eng()
    _ensure_dictionary_entries_columns(eng)
    assert conn.execute.call_count == 3
# #endregion test_dictionary

# #region test_dict_all_present [C:2] [TYPE Function]
# @BRIEF No ALTER when all 3 origin columns exist.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.inspect")
def test_dict_all_present(mock_inspect):
    mock_inspect.return_value = _insp(["dictionary_entries"],
        ["origin_run_id","origin_row_key","origin_user_id"])
    eng = MagicMock()
    _ensure_dictionary_entries_columns(eng)
    eng.begin.assert_not_called()
# #endregion test_dict_all_present

# #region test_dict_failure [C:2] [TYPE Function]
# @BRIEF Dictionary migration exception is swallowed.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.text", side_effect=RuntimeError("err"))
@patch(f"{_P}.inspect")
def test_dict_failure(mock_inspect, _):
    mock_inspect.return_value = _insp(["dictionary_entries"], [])
    eng, _ = _eng()
    _ensure_dictionary_entries_columns(eng)
# #endregion test_dict_failure

# ═══════════════════════════════════════════════════════════════════════════
# init_db & session generators
# ═══════════════════════════════════════════════════════════════════════════

# #region test_init_db [C:2] [TYPE Function]
# @BRIEF Calls create_all on all three engines.
@patch(f"{_P}.belief_scope", _NOOP)
@patch(f"{_P}.Base")
def test_init_db(mock_base):
    mock_meta = MagicMock()
    mock_base.metadata = mock_meta
    init_db()
    assert mock_meta.create_all.call_count == 3
# #endregion test_init_db

# #region test_session_generators [C:2] [TYPE Function]
# @BRIEF All session generators yield session and close on exit.
@pytest.mark.parametrize("gen_fn,factory_name", [
    (get_db, "SessionLocal"), (get_tasks_db, "TasksSessionLocal"), (get_auth_db, "AuthSessionLocal"),
])
@patch(f"{_P}.belief_scope", _NOOP)
def test_session_generators(gen_fn, factory_name):
    mock_sess = MagicMock()
    with patch(f"{_P}.{factory_name}", return_value=mock_sess):
        gen = gen_fn()
        assert next(gen) is mock_sess
        try: gen.send(None)
        except StopIteration: pass
    mock_sess.close.assert_called_once()
# #endregion test_session_generators
# #endregion Test.Core.Database
