"""Teste migrare defensiva coloane users (is_admin, email_verified). TDD: RED -> implementare in _migrate -> GREEN. """ from __future__ import annotations import sqlite3 import tempfile from pathlib import Path import pytest from app.db import _migrate, init_db, get_connection from app.config import get_settings # --------------------------------------------------------------------------- # Test 1: _migrate adauga is_admin si email_verified pe o tabela users minima # --------------------------------------------------------------------------- def test_migrate_adauga_is_admin_pe_users_veche() -> None: """Pe un DB cu tabela users creata fara is_admin/email_verified, _migrate trebuie sa adauge ambele coloane.""" with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f: db_path = Path(f.name) conn = sqlite3.connect(str(db_path), isolation_level=None) conn.row_factory = sqlite3.Row conn.execute("PRAGMA journal_mode = WAL") conn.execute("PRAGMA foreign_keys = OFF") # evitam FK checks pe schema minima # Tabela accounts minima (necesara pentru FK la users). # Trebuie sa aiba cui + rar_creds_enc + active ca _migrate sa nu crape # pe ALTER/CREATE INDEX care le refera inainte de blocul users. conn.execute(""" CREATE TABLE accounts ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, cui TEXT, active INTEGER NOT NULL DEFAULT 1, rar_creds_enc TEXT ) """) conn.execute("INSERT INTO accounts (id, name) VALUES (1, 'default')") # Tabela submissions minima (necesara pentru _migrate -- coloane submissions) conn.execute(""" CREATE TABLE submissions ( id INTEGER PRIMARY KEY AUTOINCREMENT, idempotency_key TEXT NOT NULL UNIQUE, account_id INTEGER, status TEXT NOT NULL DEFAULT 'queued', payload_json TEXT NOT NULL, rar_creds_enc TEXT, rar_status_code INTEGER, rar_error TEXT, id_prezentare INTEGER, retry_count INTEGER NOT NULL DEFAULT 0, next_attempt_at TEXT, sending_since TEXT, purge_after TEXT, batch_id INTEGER, row_index INTEGER, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')) ) """) # Tabela users MINIMA: fara is_admin, fara email_verified conn.execute(""" CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, email TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, salt TEXT NOT NULL, scrypt_params TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')) ) """) try: # Rulam migrarea _migrate(conn) # Verificam ca ambele coloane au fost adaugate cols = {r["name"] for r in conn.execute("PRAGMA table_info(users)").fetchall()} assert "is_admin" in cols, f"is_admin lipseste dupa migrare; coloane prezente: {cols}" assert "email_verified" in cols, f"email_verified lipseste dupa migrare; coloane prezente: {cols}" finally: conn.close() db_path.unlink(missing_ok=True) # --------------------------------------------------------------------------- # Test 2: _migrate este idempotent pe un DB initializat normal cu init_db() # --------------------------------------------------------------------------- def test_migrate_idempotent_pe_users_curenta(tmp_path: pytest.TempPathFactory, monkeypatch: pytest.MonkeyPatch) -> None: """Pe un DB initializat normal, re-apelarea _migrate nu ridica exceptie si coloanele is_admin/email_verified raman prezente.""" db_file = tmp_path / "test_idem.db" monkeypatch.setenv("AUTOPASS_DB_PATH", str(db_file)) # Resetam settings-ul cached ca sa preia noul AUTOPASS_DB_PATH get_settings.cache_clear() # type: ignore[attr-defined] try: # Initializare normala init_db() # Re-apelam _migrate direct (idempotenta) conn = get_connection() try: _migrate(conn) # nu trebuie sa ridice cols = {r["name"] for r in conn.execute("PRAGMA table_info(users)").fetchall()} assert "is_admin" in cols assert "email_verified" in cols finally: conn.close() finally: get_settings.cache_clear() # type: ignore[attr-defined]