7a0da7932b
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
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
347 lines
12 KiB
Python
347 lines
12 KiB
Python
"""
|
|
Tests for web/queue/manager.py
|
|
|
|
Tests cover:
|
|
- QueueManager.add_to_queue
|
|
- QueueManager.get_queue_position
|
|
- QueueManager.remove_from_queue
|
|
- QueueManager.get_user_queue
|
|
"""
|
|
|
|
from contextlib import contextmanager
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from local_deep_research.database.session_context import DatabaseSessionError
|
|
|
|
|
|
def _mock_user_db_session(mock_session):
|
|
"""Create a mock context manager that yields the given session."""
|
|
|
|
@contextmanager
|
|
def _ctx(username=None, password=None):
|
|
yield mock_session
|
|
|
|
return _ctx
|
|
|
|
|
|
def _mock_user_db_session_error():
|
|
"""Create a mock context manager that raises DatabaseSessionError."""
|
|
|
|
@contextmanager
|
|
def _ctx(username=None, password=None):
|
|
raise DatabaseSessionError("No database connection")
|
|
yield # noqa: unreachable — needed for generator syntax
|
|
|
|
return _ctx
|
|
|
|
|
|
class TestQueueManagerAddToQueue:
|
|
"""Tests for QueueManager.add_to_queue method."""
|
|
|
|
def test_add_to_queue_success(self):
|
|
"""Test successful addition to queue."""
|
|
mock_session = MagicMock()
|
|
|
|
# Mock query chain for max position
|
|
mock_query = MagicMock()
|
|
mock_query.filter_by.return_value.scalar.return_value = 0
|
|
mock_session.query.return_value = mock_query
|
|
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session(mock_session),
|
|
):
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.queue_processor"
|
|
) as mock_processor:
|
|
from local_deep_research.web.queue.manager import (
|
|
QueueManager,
|
|
)
|
|
|
|
result = QueueManager.add_to_queue(
|
|
username="testuser",
|
|
research_id="test-id-123",
|
|
query="test query",
|
|
mode="detailed",
|
|
settings={"key": "value"},
|
|
)
|
|
|
|
assert result == 1
|
|
mock_session.add.assert_called_once()
|
|
mock_session.commit.assert_called_once()
|
|
mock_processor.notify_research_queued.assert_called_once_with(
|
|
"testuser", "test-id-123"
|
|
)
|
|
|
|
def test_add_to_queue_no_connection(self):
|
|
"""Test add_to_queue raises DatabaseSessionError when no connection."""
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session_error(),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
with pytest.raises(DatabaseSessionError):
|
|
QueueManager.add_to_queue(
|
|
username="testuser",
|
|
research_id="test-id-123",
|
|
query="test query",
|
|
mode="detailed",
|
|
settings={},
|
|
)
|
|
|
|
def test_add_to_queue_with_existing_items(self):
|
|
"""Test add_to_queue with existing items in queue."""
|
|
mock_session = MagicMock()
|
|
|
|
# Mock query chain for max position - already has 3 items
|
|
mock_query = MagicMock()
|
|
mock_query.filter_by.return_value.scalar.return_value = 3
|
|
mock_session.query.return_value = mock_query
|
|
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session(mock_session),
|
|
):
|
|
with patch("local_deep_research.web.queue.manager.queue_processor"):
|
|
from local_deep_research.web.queue.manager import (
|
|
QueueManager,
|
|
)
|
|
|
|
result = QueueManager.add_to_queue(
|
|
username="testuser",
|
|
research_id="test-id-456",
|
|
query="another query",
|
|
mode="quick",
|
|
settings={},
|
|
)
|
|
|
|
# Position should be 4 (max + 1)
|
|
assert result == 4
|
|
|
|
|
|
class TestQueueManagerGetQueuePosition:
|
|
"""Tests for QueueManager.get_queue_position method."""
|
|
|
|
def test_get_queue_position_success(self):
|
|
"""Test getting queue position successfully."""
|
|
mock_session = MagicMock()
|
|
|
|
# Mock queued research item
|
|
mock_queued = MagicMock()
|
|
mock_queued.position = 3
|
|
|
|
# Setup query chain
|
|
mock_query = MagicMock()
|
|
mock_filter = MagicMock()
|
|
mock_filter.first.return_value = mock_queued
|
|
mock_filter.count.return_value = 2 # 2 items ahead
|
|
mock_query.filter_by.return_value = mock_filter
|
|
mock_query.filter.return_value = mock_filter
|
|
mock_session.query.return_value = mock_query
|
|
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session(mock_session),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
result = QueueManager.get_queue_position(
|
|
username="testuser", research_id="test-id-123"
|
|
)
|
|
|
|
# Position should be ahead_count + 1
|
|
assert result == 3
|
|
|
|
def test_get_queue_position_not_found(self):
|
|
"""Test get_queue_position when research not in queue."""
|
|
mock_session = MagicMock()
|
|
|
|
mock_query = MagicMock()
|
|
mock_query.filter_by.return_value.first.return_value = None
|
|
mock_session.query.return_value = mock_query
|
|
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session(mock_session),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
result = QueueManager.get_queue_position(
|
|
username="testuser", research_id="nonexistent"
|
|
)
|
|
|
|
assert result is None
|
|
|
|
def test_get_queue_position_no_connection(self):
|
|
"""Test get_queue_position raises DatabaseSessionError when no connection."""
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session_error(),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
with pytest.raises(DatabaseSessionError):
|
|
QueueManager.get_queue_position(
|
|
username="testuser", research_id="test-id-123"
|
|
)
|
|
|
|
|
|
class TestQueueManagerRemoveFromQueue:
|
|
"""Tests for QueueManager.remove_from_queue method."""
|
|
|
|
def test_remove_from_queue_success(self):
|
|
"""Test successful removal from queue."""
|
|
mock_session = MagicMock()
|
|
|
|
# Mock queued research item
|
|
mock_queued = MagicMock()
|
|
mock_queued.position = 2
|
|
|
|
mock_query = MagicMock()
|
|
mock_query.filter_by.return_value.first.return_value = mock_queued
|
|
mock_query.filter.return_value.update.return_value = None
|
|
mock_session.query.return_value = mock_query
|
|
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session(mock_session),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
result = QueueManager.remove_from_queue(
|
|
username="testuser", research_id="test-id-123"
|
|
)
|
|
|
|
assert result is True
|
|
mock_session.delete.assert_called_once_with(mock_queued)
|
|
mock_session.commit.assert_called_once()
|
|
|
|
def test_remove_from_queue_not_found(self):
|
|
"""Test remove_from_queue when research not in queue."""
|
|
mock_session = MagicMock()
|
|
|
|
mock_query = MagicMock()
|
|
mock_query.filter_by.return_value.first.return_value = None
|
|
mock_session.query.return_value = mock_query
|
|
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session(mock_session),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
result = QueueManager.remove_from_queue(
|
|
username="testuser", research_id="nonexistent"
|
|
)
|
|
|
|
assert result is False
|
|
|
|
def test_remove_from_queue_no_connection(self):
|
|
"""Test remove_from_queue raises DatabaseSessionError when no connection."""
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session_error(),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
with pytest.raises(DatabaseSessionError):
|
|
QueueManager.remove_from_queue(
|
|
username="testuser", research_id="test-id-123"
|
|
)
|
|
|
|
|
|
class TestQueueManagerGetUserQueue:
|
|
"""Tests for QueueManager.get_user_queue method."""
|
|
|
|
def test_get_user_queue_success(self):
|
|
"""Test getting user queue successfully."""
|
|
mock_session = MagicMock()
|
|
|
|
# Mock queued items
|
|
from datetime import datetime
|
|
|
|
mock_item1 = MagicMock()
|
|
mock_item1.research_id = "id-1"
|
|
mock_item1.query = "query 1"
|
|
mock_item1.mode = "detailed"
|
|
mock_item1.position = 1
|
|
mock_item1.created_at = datetime(2025, 1, 1, 12, 0, 0)
|
|
mock_item1.is_processing = False
|
|
|
|
mock_item2 = MagicMock()
|
|
mock_item2.research_id = "id-2"
|
|
mock_item2.query = "query 2"
|
|
mock_item2.mode = "quick"
|
|
mock_item2.position = 2
|
|
mock_item2.created_at = None
|
|
mock_item2.is_processing = True
|
|
|
|
mock_research1 = MagicMock()
|
|
mock_research2 = MagicMock()
|
|
|
|
def query_side_effect(model):
|
|
q = MagicMock()
|
|
if "QueuedResearch" in str(model):
|
|
q.filter_by.return_value.order_by.return_value.all.return_value = [
|
|
mock_item1,
|
|
mock_item2,
|
|
]
|
|
else: # ResearchHistory
|
|
# Return research on first call, then second
|
|
q.filter_by.return_value.first.side_effect = [
|
|
mock_research1,
|
|
mock_research2,
|
|
]
|
|
return q
|
|
|
|
mock_session.query.side_effect = query_side_effect
|
|
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session(mock_session),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
result = QueueManager.get_user_queue(username="testuser")
|
|
|
|
assert len(result) == 2
|
|
assert result[0]["research_id"] == "id-1"
|
|
assert result[0]["query"] == "query 1"
|
|
assert result[0]["mode"] == "detailed"
|
|
assert result[0]["position"] == 1
|
|
assert result[0]["is_processing"] is False
|
|
assert result[1]["research_id"] == "id-2"
|
|
assert result[1]["created_at"] is None
|
|
|
|
def test_get_user_queue_empty(self):
|
|
"""Test get_user_queue when queue is empty."""
|
|
mock_session = MagicMock()
|
|
|
|
mock_query = MagicMock()
|
|
mock_query.filter_by.return_value.order_by.return_value.all.return_value = []
|
|
mock_session.query.return_value = mock_query
|
|
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session(mock_session),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
result = QueueManager.get_user_queue(username="testuser")
|
|
|
|
assert result == []
|
|
|
|
def test_get_user_queue_no_connection(self):
|
|
"""Test get_user_queue raises DatabaseSessionError when no connection."""
|
|
with patch(
|
|
"local_deep_research.web.queue.manager.get_user_db_session",
|
|
_mock_user_db_session_error(),
|
|
):
|
|
from local_deep_research.web.queue.manager import QueueManager
|
|
|
|
with pytest.raises(DatabaseSessionError):
|
|
QueueManager.get_user_queue(username="testuser")
|