7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
221 lines
7.4 KiB
Python
221 lines
7.4 KiB
Python
"""
|
|
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}"
|
|
)
|