""" Tests for Database Schema Migrations Phase 21: Database & Encryption - Schema Migration Tests Tests database schema creation, versioning, and migrations. """ import pytest class TestSchemaMigrations: """Tests for schema migration functionality""" def test_initial_schema_creation(self): """Test initial schema is created correctly""" from local_deep_research.database.models import Base # Verify Base.metadata has tables defined assert len(Base.metadata.tables) > 0 def test_migration_models_importable(self): """Test all model modules can be imported""" # Import each model module to ensure no syntax errors from local_deep_research.database.models import auth from local_deep_research.database.models import research from local_deep_research.database.models import settings from local_deep_research.database.models import metrics from local_deep_research.database.models import queue assert auth is not None assert research is not None assert settings is not None assert metrics is not None assert queue is not None def test_base_model_columns(self): """Test base model has expected columns""" from local_deep_research.database.models.base import Base # Base should be a declarative base assert hasattr(Base, "metadata") def test_auth_model_schema(self): """Test auth model schema""" from local_deep_research.database.models.auth import User # Check expected columns exist columns = User.__table__.columns.keys() assert "id" in columns assert "username" in columns # Note: passwords are NOT stored in this model - they decrypt user databases def test_research_model_schema(self): """Test research model schema""" from local_deep_research.database.models.research import ResearchHistory columns = ResearchHistory.__table__.columns.keys() assert "id" in columns assert "query" in columns assert "status" in columns def test_settings_model_schema(self): """Test settings model schema""" from local_deep_research.database.models.settings import Setting columns = Setting.__table__.columns.keys() assert "id" in columns assert "key" in columns assert "value" in columns def test_metrics_model_schema(self): """Test metrics model schema""" from local_deep_research.database.models.metrics import TokenUsage columns = TokenUsage.__table__.columns.keys() assert "id" in columns def test_sorted_tables_order(self): """Test tables are sorted correctly for creation""" from local_deep_research.database.models import Base tables = Base.metadata.sorted_tables # Should have multiple tables assert len(tables) > 0 # Tables should be sorted by dependency order table_names = [t.name for t in tables] assert len(table_names) == len(set(table_names)) # No duplicates class TestModelRelationships: """Tests for model relationships""" def test_research_source_relationship(self): """Test research model has expected columns""" from local_deep_research.database.models.research import ResearchHistory # Check research history model exists and has expected columns columns = ResearchHistory.__table__.columns.keys() assert "id" in columns assert "query" in columns def test_queued_research_relationship(self): """Test queued research model""" from local_deep_research.database.models.queued_research import ( QueuedResearch, ) columns = QueuedResearch.__table__.columns.keys() assert "id" in columns assert "query" in columns class TestDatabaseInitialization: """Tests for database initialization""" def test_initialize_database_function_exists(self): """Test initialize_database function exists""" from local_deep_research.database.initialize import initialize_database assert callable(initialize_database) def test_initialize_module_importable(self): """Test initialize module can be imported""" from local_deep_research.database import initialize assert hasattr(initialize, "initialize_database") class TestConstraints: """Tests for database constraints""" def test_unique_username_constraint(self): """Test unique username constraint on User model""" from local_deep_research.database.models.auth import User # Check for unique constraint on username username_col = User.__table__.columns["username"] assert username_col.unique is True def test_setting_key_uniqueness(self): """Test setting key uniqueness""" from local_deep_research.database.models.settings import Setting # Key should be unique within user context _key_col = Setting.__table__.columns["key"] # noqa: F841 # May have unique constraint or unique together with user_id class TestColumnTypes: """Tests for column type definitions""" def test_datetime_columns_have_timezone(self): """Test datetime columns use timezone-aware type""" from local_deep_research.database.models.research import ResearchHistory # Check created_at column exists if "created_at" in ResearchHistory.__table__.columns: created_col = ResearchHistory.__table__.columns["created_at"] # Column should exist (type checking varies by dialect) assert created_col is not None def test_text_columns_for_long_content(self): """Test long content uses Text type""" from local_deep_research.database.models.research import ResearchHistory # Check report column uses Text if "report" in ResearchHistory.__table__.columns: report_col = ResearchHistory.__table__.columns["report"] assert report_col is not None def test_json_columns(self): """Test JSON column support""" from local_deep_research.database.models.settings import Setting # Settings may store JSON values value_col = Setting.__table__.columns["value"] assert value_col is not None class TestIndexes: """Tests for database indexes""" def test_primary_key_indexes(self): """Test primary key columns are indexed""" from local_deep_research.database.models.auth import User # Primary key should be indexed by default id_col = User.__table__.columns["id"] assert id_col.primary_key is True class TestTableNames: """Tests for table naming conventions""" def test_table_names_lowercase(self): """Test table names are lowercase""" from local_deep_research.database.models import Base for table in Base.metadata.tables.values(): assert table.name == table.name.lower() def test_no_reserved_keywords(self): """Test no reserved SQL keywords used as table names""" reserved = {"user", "order", "group", "select", "table", "index"} from local_deep_research.database.models import Base for table in Base.metadata.tables.values(): # 'users' is fine, 'user' is reserved if table.name in reserved: pytest.fail( f"Reserved keyword used as table name: {table.name}" )