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
443 lines
16 KiB
Python
443 lines
16 KiB
Python
"""
|
|
Extended tests for model consolidation - Comprehensive model architecture validation.
|
|
|
|
Tests cover:
|
|
- All model imports from consolidated location
|
|
- Model relationships and foreign keys
|
|
- Column definitions and types
|
|
- Model constraints and indexes
|
|
- Enum definitions
|
|
- Cross-model consistency
|
|
"""
|
|
|
|
from sqlalchemy import inspect
|
|
|
|
|
|
class TestModelImports:
|
|
"""Tests for model imports from consolidated location."""
|
|
|
|
def test_benchmark_models_importable(self):
|
|
"""Benchmark models should be importable."""
|
|
from local_deep_research.database.models import (
|
|
BenchmarkRun,
|
|
BenchmarkResult,
|
|
BenchmarkProgress,
|
|
)
|
|
|
|
assert BenchmarkRun is not None
|
|
assert BenchmarkResult is not None
|
|
assert BenchmarkProgress is not None
|
|
|
|
def test_library_models_importable(self):
|
|
"""Library models should be importable."""
|
|
from local_deep_research.database.models import (
|
|
Document,
|
|
Collection,
|
|
DocumentChunk,
|
|
)
|
|
|
|
assert Document is not None
|
|
assert Collection is not None
|
|
assert DocumentChunk is not None
|
|
|
|
|
|
class TestModelRelationships:
|
|
"""Tests for model relationships."""
|
|
|
|
def test_benchmark_run_has_results_relationship(self):
|
|
"""BenchmarkRun should have results relationship."""
|
|
from local_deep_research.database.models import BenchmarkRun
|
|
|
|
assert hasattr(BenchmarkRun, "results")
|
|
|
|
def test_benchmark_run_has_progress_relationship(self):
|
|
"""BenchmarkRun should have progress_updates relationship."""
|
|
from local_deep_research.database.models import BenchmarkRun
|
|
|
|
assert hasattr(BenchmarkRun, "progress_updates")
|
|
|
|
def test_benchmark_result_has_run_relationship(self):
|
|
"""BenchmarkResult should have benchmark_run relationship."""
|
|
from local_deep_research.database.models import BenchmarkResult
|
|
|
|
assert hasattr(BenchmarkResult, "benchmark_run")
|
|
|
|
def test_document_has_collections_relationship(self):
|
|
"""Document should have collections relationship."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
assert hasattr(Document, "collections")
|
|
|
|
def test_collection_has_documents_relationship(self):
|
|
"""Collection should have document_links relationship."""
|
|
from local_deep_research.database.models import Collection
|
|
|
|
assert hasattr(Collection, "document_links")
|
|
|
|
|
|
class TestColumnDefinitions:
|
|
"""Tests for model column definitions."""
|
|
|
|
def test_research_history_has_query_column(self):
|
|
"""ResearchHistory should have query column."""
|
|
from local_deep_research.database.models import ResearchHistory
|
|
|
|
assert hasattr(ResearchHistory, "query")
|
|
|
|
def test_research_history_has_status_column(self):
|
|
"""ResearchHistory should have status column."""
|
|
from local_deep_research.database.models import ResearchHistory
|
|
|
|
assert hasattr(ResearchHistory, "status")
|
|
|
|
def test_research_history_has_research_meta_column(self):
|
|
"""ResearchHistory should have research_meta (renamed from metadata)."""
|
|
from local_deep_research.database.models import ResearchHistory
|
|
|
|
assert hasattr(ResearchHistory, "research_meta")
|
|
|
|
def test_research_resource_has_title_column(self):
|
|
"""ResearchResource should have title column."""
|
|
from local_deep_research.database.models import ResearchResource
|
|
|
|
assert hasattr(ResearchResource, "title")
|
|
|
|
def test_research_resource_has_url_column(self):
|
|
"""ResearchResource should have url column."""
|
|
from local_deep_research.database.models import ResearchResource
|
|
|
|
assert hasattr(ResearchResource, "url")
|
|
|
|
def test_research_resource_has_resource_metadata_column(self):
|
|
"""ResearchResource should have resource_metadata (renamed from metadata)."""
|
|
from local_deep_research.database.models import ResearchResource
|
|
|
|
assert hasattr(ResearchResource, "resource_metadata")
|
|
|
|
def test_document_has_required_columns(self):
|
|
"""Document should have all required columns."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
required_columns = [
|
|
"id",
|
|
"document_hash",
|
|
"file_size",
|
|
"file_type",
|
|
"status",
|
|
"created_at",
|
|
]
|
|
for col in required_columns:
|
|
assert hasattr(Document, col), f"Document missing column: {col}"
|
|
|
|
def test_collection_has_required_columns(self):
|
|
"""Collection should have all required columns."""
|
|
from local_deep_research.database.models import Collection
|
|
|
|
required_columns = ["id", "name", "is_default", "created_at"]
|
|
for col in required_columns:
|
|
assert hasattr(Collection, col), f"Collection missing column: {col}"
|
|
|
|
|
|
class TestEnumDefinitions:
|
|
"""Tests for enum definitions."""
|
|
|
|
def test_document_status_has_expected_values(self):
|
|
"""DocumentStatus should have expected values."""
|
|
from local_deep_research.database.models.library import DocumentStatus
|
|
|
|
assert DocumentStatus.PENDING.value == "pending"
|
|
assert DocumentStatus.PROCESSING.value == "processing"
|
|
assert DocumentStatus.COMPLETED.value == "completed"
|
|
assert DocumentStatus.FAILED.value == "failed"
|
|
|
|
def test_embedding_provider_enum_exists(self):
|
|
"""EmbeddingProvider enum should exist."""
|
|
from local_deep_research.database.models.library import (
|
|
EmbeddingProvider,
|
|
)
|
|
|
|
assert EmbeddingProvider is not None
|
|
assert (
|
|
EmbeddingProvider.SENTENCE_TRANSFORMERS.value
|
|
== "sentence_transformers"
|
|
)
|
|
assert EmbeddingProvider.OLLAMA.value == "ollama"
|
|
# Issue #3883 — OPENAI covers the cloud API and any
|
|
# OpenAI-compatible endpoint (LM Studio, vLLM, llama.cpp).
|
|
assert EmbeddingProvider.OPENAI.value == "openai"
|
|
|
|
def test_embedding_provider_openai_constructible_from_string(self):
|
|
"""EmbeddingProvider("openai") should resolve to the OPENAI member.
|
|
|
|
The library RAG service stores the provider as a string and
|
|
later persists it via ``EmbeddingProvider(value)``; the
|
|
round-trip is the column-write path that issue #3883's
|
|
acceptance criteria #1 calls out.
|
|
"""
|
|
from local_deep_research.database.models.library import (
|
|
EmbeddingProvider,
|
|
)
|
|
|
|
assert EmbeddingProvider("openai") is EmbeddingProvider.OPENAI
|
|
|
|
|
|
class TestTableNames:
|
|
"""Tests for correct table names."""
|
|
|
|
def test_document_table_name(self):
|
|
"""Document should have correct table name."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
assert Document.__tablename__ == "documents"
|
|
|
|
def test_collection_table_name(self):
|
|
"""Collection should have correct table name."""
|
|
from local_deep_research.database.models import Collection
|
|
|
|
assert Collection.__tablename__ == "collections"
|
|
|
|
def test_document_chunk_table_name(self):
|
|
"""DocumentChunk should have correct table name."""
|
|
from local_deep_research.database.models import DocumentChunk
|
|
|
|
assert DocumentChunk.__tablename__ == "document_chunks"
|
|
|
|
def test_rag_index_table_name(self):
|
|
"""RAGIndex should have correct table name."""
|
|
from local_deep_research.database.models import RAGIndex
|
|
|
|
assert RAGIndex.__tablename__ == "rag_indices"
|
|
|
|
|
|
class TestModelConstraints:
|
|
"""Tests for model constraints."""
|
|
|
|
def test_document_has_unique_hash_constraint(self):
|
|
"""Document should have unique document_hash constraint."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
mapper = inspect(Document)
|
|
columns = {c.name: c for c in mapper.columns}
|
|
assert columns["document_hash"].unique is True
|
|
|
|
def test_collection_document_has_unique_constraint(self):
|
|
"""DocumentCollection should have unique document-collection pair."""
|
|
from local_deep_research.database.models import DocumentCollection
|
|
|
|
# Check table args for unique constraint
|
|
table_args = DocumentCollection.__table_args__
|
|
has_unique = any(
|
|
hasattr(arg, "name") and "uix_document_collection" in str(arg.name)
|
|
for arg in table_args
|
|
if hasattr(arg, "name")
|
|
)
|
|
assert has_unique
|
|
|
|
|
|
class TestIndexDefinitions:
|
|
"""Tests for index definitions."""
|
|
|
|
def test_document_has_source_type_index(self):
|
|
"""Document should have source_type index."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
table_args = Document.__table_args__
|
|
has_index = any(
|
|
hasattr(arg, "name") and "idx_source_type" in str(arg.name)
|
|
for arg in table_args
|
|
if hasattr(arg, "name")
|
|
)
|
|
assert has_index
|
|
|
|
def test_document_chunk_has_collection_index(self):
|
|
"""DocumentChunk should have collection index."""
|
|
from local_deep_research.database.models import DocumentChunk
|
|
|
|
table_args = DocumentChunk.__table_args__
|
|
has_index = any(
|
|
hasattr(arg, "name") and "idx_chunk_collection" in str(arg.name)
|
|
for arg in table_args
|
|
if hasattr(arg, "name")
|
|
)
|
|
assert has_index
|
|
|
|
|
|
class TestCrossModelConsistency:
|
|
"""Tests for cross-model consistency."""
|
|
|
|
def test_document_references_source_type(self):
|
|
"""Document.source_type_id should reference source_types."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
mapper = inspect(Document)
|
|
columns = {c.name: c for c in mapper.columns}
|
|
fk = list(columns["source_type_id"].foreign_keys)[0]
|
|
assert "source_types" in str(fk.target_fullname)
|
|
|
|
def test_document_collection_references_both(self):
|
|
"""DocumentCollection should reference both Document and Collection."""
|
|
from local_deep_research.database.models import DocumentCollection
|
|
|
|
mapper = inspect(DocumentCollection)
|
|
columns = {c.name: c for c in mapper.columns}
|
|
|
|
doc_fk = list(columns["document_id"].foreign_keys)[0]
|
|
coll_fk = list(columns["collection_id"].foreign_keys)[0]
|
|
|
|
assert "documents" in str(doc_fk.target_fullname)
|
|
assert "collections" in str(coll_fk.target_fullname)
|
|
|
|
|
|
class TestModelRepr:
|
|
"""Tests for model __repr__ methods."""
|
|
|
|
def test_document_repr_not_error(self):
|
|
"""Document __repr__ should not raise errors."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
doc = Document()
|
|
doc.id = "test-id"
|
|
doc.title = "Test Document"
|
|
doc.file_type = "pdf"
|
|
doc.file_size = 1024
|
|
|
|
# Should not raise
|
|
repr_str = repr(doc)
|
|
assert "Document" in repr_str
|
|
|
|
def test_collection_repr_not_error(self):
|
|
"""Collection __repr__ should not raise errors."""
|
|
from local_deep_research.database.models import Collection
|
|
|
|
coll = Collection()
|
|
coll.id = "test-id"
|
|
coll.name = "Test Collection"
|
|
coll.collection_type = "user_collection"
|
|
|
|
repr_str = repr(coll)
|
|
assert "Collection" in repr_str
|
|
|
|
|
|
class TestModelDefaults:
|
|
"""Tests for model default values."""
|
|
|
|
def test_document_status_default(self):
|
|
"""Document status should default to COMPLETED."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
mapper = inspect(Document)
|
|
columns = {c.name: c for c in mapper.columns}
|
|
default = columns["status"].default
|
|
|
|
assert default is not None
|
|
|
|
def test_collection_is_default_defaults_to_false(self):
|
|
"""Collection.is_default should default to False."""
|
|
from local_deep_research.database.models import Collection
|
|
|
|
mapper = inspect(Collection)
|
|
columns = {c.name: c for c in mapper.columns}
|
|
default = columns["is_default"].default
|
|
|
|
assert default is not None
|
|
assert default.arg is False
|
|
|
|
|
|
class TestNullableColumns:
|
|
"""Tests for nullable column settings."""
|
|
|
|
def test_document_id_not_nullable(self):
|
|
"""Document.id should not be nullable."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
mapper = inspect(Document)
|
|
columns = {c.name: c for c in mapper.columns}
|
|
assert columns["id"].nullable is False
|
|
|
|
def test_document_hash_not_nullable(self):
|
|
"""Document.document_hash should not be nullable."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
mapper = inspect(Document)
|
|
columns = {c.name: c for c in mapper.columns}
|
|
assert columns["document_hash"].nullable is False
|
|
|
|
def test_document_original_url_nullable(self):
|
|
"""Document.original_url should be nullable (for uploads)."""
|
|
from local_deep_research.database.models import Document
|
|
|
|
mapper = inspect(Document)
|
|
columns = {c.name: c for c in mapper.columns}
|
|
assert columns["original_url"].nullable is True
|
|
|
|
|
|
class TestExtractionEnums:
|
|
"""Tests for extraction-related enums."""
|
|
|
|
def test_extraction_method_enum(self):
|
|
"""ExtractionMethod enum should have expected values."""
|
|
from local_deep_research.database.models.library import ExtractionMethod
|
|
|
|
assert ExtractionMethod.PDF_EXTRACTION.value == "pdf_extraction"
|
|
assert ExtractionMethod.NATIVE_API.value == "native_api"
|
|
assert ExtractionMethod.UNKNOWN.value == "unknown"
|
|
|
|
def test_extraction_source_enum(self):
|
|
"""ExtractionSource enum should have expected values."""
|
|
from local_deep_research.database.models.library import ExtractionSource
|
|
|
|
assert ExtractionSource.ARXIV_API.value == "arxiv_api"
|
|
assert ExtractionSource.PUBMED_API.value == "pubmed_api"
|
|
assert ExtractionSource.PDFPLUMBER.value == "pdfplumber"
|
|
|
|
def test_extraction_quality_enum(self):
|
|
"""ExtractionQuality enum should have expected values."""
|
|
from local_deep_research.database.models.library import (
|
|
ExtractionQuality,
|
|
)
|
|
|
|
assert ExtractionQuality.HIGH.value == "high"
|
|
assert ExtractionQuality.MEDIUM.value == "medium"
|
|
assert ExtractionQuality.LOW.value == "low"
|
|
|
|
|
|
class TestRAGEnums:
|
|
"""Tests for RAG-related enums."""
|
|
|
|
def test_distance_metric_enum(self):
|
|
"""DistanceMetric enum should have expected values."""
|
|
from local_deep_research.database.models.library import DistanceMetric
|
|
|
|
assert DistanceMetric.COSINE.value == "cosine"
|
|
assert DistanceMetric.L2.value == "l2"
|
|
assert DistanceMetric.DOT_PRODUCT.value == "dot_product"
|
|
|
|
def test_index_type_enum(self):
|
|
"""IndexType enum should have expected values."""
|
|
from local_deep_research.database.models.library import IndexType
|
|
|
|
assert IndexType.FLAT.value == "flat"
|
|
assert IndexType.HNSW.value == "hnsw"
|
|
assert IndexType.IVF.value == "ivf"
|
|
|
|
def test_splitter_type_enum(self):
|
|
"""SplitterType enum should have expected values."""
|
|
from local_deep_research.database.models.library import SplitterType
|
|
|
|
assert SplitterType.RECURSIVE.value == "recursive"
|
|
assert SplitterType.SEMANTIC.value == "semantic"
|
|
assert SplitterType.TOKEN.value == "token"
|
|
assert SplitterType.SENTENCE.value == "sentence"
|
|
|
|
|
|
class TestPDFStorageMode:
|
|
"""Tests for PDF storage mode enum."""
|
|
|
|
def test_pdf_storage_mode_enum(self):
|
|
"""PDFStorageMode enum should have expected values."""
|
|
from local_deep_research.database.models.library import PDFStorageMode
|
|
|
|
assert PDFStorageMode.NONE.value == "none"
|
|
assert PDFStorageMode.FILESYSTEM.value == "filesystem"
|
|
assert PDFStorageMode.DATABASE.value == "database"
|