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
259 lines
8.7 KiB
Python
259 lines
8.7 KiB
Python
"""
|
|
Tests for notifications/templates.py
|
|
|
|
Tests cover:
|
|
- EventType enum
|
|
- NotificationTemplate.format()
|
|
- NotificationTemplate.get_required_context()
|
|
- NotificationTemplate._get_fallback_template()
|
|
"""
|
|
|
|
|
|
class TestEventType:
|
|
"""Tests for EventType enum."""
|
|
|
|
def test_research_completed_event(self):
|
|
"""Test RESEARCH_COMPLETED event type."""
|
|
from local_deep_research.notifications.templates import EventType
|
|
|
|
assert EventType.RESEARCH_COMPLETED.value == "research_completed"
|
|
|
|
def test_research_failed_event(self):
|
|
"""Test RESEARCH_FAILED event type."""
|
|
from local_deep_research.notifications.templates import EventType
|
|
|
|
assert EventType.RESEARCH_FAILED.value == "research_failed"
|
|
|
|
def test_research_queued_event(self):
|
|
"""Test RESEARCH_QUEUED event type."""
|
|
from local_deep_research.notifications.templates import EventType
|
|
|
|
assert EventType.RESEARCH_QUEUED.value == "research_queued"
|
|
|
|
def test_subscription_update_event(self):
|
|
"""Test SUBSCRIPTION_UPDATE event type."""
|
|
from local_deep_research.notifications.templates import EventType
|
|
|
|
assert EventType.SUBSCRIPTION_UPDATE.value == "subscription_update"
|
|
|
|
def test_subscription_error_event(self):
|
|
"""Test SUBSCRIPTION_ERROR event type."""
|
|
from local_deep_research.notifications.templates import EventType
|
|
|
|
assert EventType.SUBSCRIPTION_ERROR.value == "subscription_error"
|
|
|
|
def test_test_event(self):
|
|
"""Test TEST event type."""
|
|
from local_deep_research.notifications.templates import EventType
|
|
|
|
assert EventType.TEST.value == "test"
|
|
|
|
def test_all_event_types_are_strings(self):
|
|
"""Test that all event type values are strings."""
|
|
from local_deep_research.notifications.templates import EventType
|
|
|
|
for event in EventType:
|
|
assert isinstance(event.value, str)
|
|
|
|
|
|
class TestNotificationTemplateFormat:
|
|
"""Tests for NotificationTemplate.format method."""
|
|
|
|
def test_format_with_custom_template(self):
|
|
"""Test formatting with custom template."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
EventType,
|
|
)
|
|
|
|
custom_template = {
|
|
"title": "Custom: {topic}",
|
|
"body": "Message about {topic} for {user}",
|
|
}
|
|
context = {"topic": "Research", "user": "John"}
|
|
|
|
result = NotificationTemplate.format(
|
|
EventType.TEST, context, custom_template=custom_template
|
|
)
|
|
|
|
assert result["title"] == "Custom: Research"
|
|
assert result["body"] == "Message about Research for John"
|
|
|
|
def test_format_custom_template_missing_var(self):
|
|
"""Test formatting custom template with missing variable."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
EventType,
|
|
)
|
|
|
|
custom_template = {"title": "Title: {missing}", "body": "Body text"}
|
|
context = {"existing": "value"}
|
|
|
|
result = NotificationTemplate.format(
|
|
EventType.TEST, context, custom_template=custom_template
|
|
)
|
|
|
|
assert "Template error" in result["body"] or "missing" in result["body"]
|
|
|
|
def test_format_returns_dict_with_title_and_body(self):
|
|
"""Test that format returns dict with title and body keys."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
EventType,
|
|
)
|
|
|
|
result = NotificationTemplate.format(EventType.TEST, {})
|
|
|
|
assert "title" in result
|
|
assert "body" in result
|
|
assert isinstance(result["title"], str)
|
|
assert isinstance(result["body"], str)
|
|
|
|
def test_format_unknown_event_type_fallback(self):
|
|
"""Test formatting with unknown event type falls back gracefully."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
EventType,
|
|
)
|
|
|
|
# Remove TEMPLATE_FILES entry temporarily to simulate unknown event
|
|
original_templates = NotificationTemplate.TEMPLATE_FILES.copy()
|
|
NotificationTemplate.TEMPLATE_FILES = {}
|
|
|
|
try:
|
|
result = NotificationTemplate.format(
|
|
EventType.TEST, {"key": "value"}
|
|
)
|
|
|
|
assert "title" in result
|
|
assert "body" in result
|
|
finally:
|
|
NotificationTemplate.TEMPLATE_FILES = original_templates
|
|
|
|
|
|
class TestNotificationTemplateFallback:
|
|
"""Tests for NotificationTemplate._get_fallback_template method."""
|
|
|
|
def test_fallback_template_format(self):
|
|
"""Test fallback template format."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
EventType,
|
|
)
|
|
|
|
result = NotificationTemplate._get_fallback_template(
|
|
EventType.RESEARCH_COMPLETED, {"query": "test query"}
|
|
)
|
|
|
|
assert "title" in result
|
|
assert "body" in result
|
|
assert "Research Completed" in result["title"]
|
|
|
|
def test_fallback_template_includes_context(self):
|
|
"""Test fallback template includes context in body."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
EventType,
|
|
)
|
|
|
|
context = {"key": "value", "another": "data"}
|
|
|
|
result = NotificationTemplate._get_fallback_template(
|
|
EventType.TEST, context
|
|
)
|
|
|
|
# Body should include some representation of the context
|
|
assert "Details" in result["body"] or "value" in result["body"]
|
|
|
|
def test_fallback_template_replaces_underscores(self):
|
|
"""Test fallback template replaces underscores in event name."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
EventType,
|
|
)
|
|
|
|
result = NotificationTemplate._get_fallback_template(
|
|
EventType.API_QUOTA_WARNING, {}
|
|
)
|
|
|
|
assert "_" not in result["title"].lower()
|
|
|
|
|
|
class TestNotificationTemplateGetRequiredContext:
|
|
"""Tests for NotificationTemplate.get_required_context method."""
|
|
|
|
def test_get_required_context_returns_list(self):
|
|
"""Test that get_required_context returns a list."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
EventType,
|
|
)
|
|
|
|
result = NotificationTemplate.get_required_context(EventType.TEST)
|
|
|
|
assert isinstance(result, list)
|
|
|
|
def test_get_required_context_unknown_event(self):
|
|
"""Test get_required_context with unknown event type."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
EventType,
|
|
)
|
|
|
|
# Remove from TEMPLATE_FILES to simulate unknown
|
|
original_templates = NotificationTemplate.TEMPLATE_FILES.copy()
|
|
NotificationTemplate.TEMPLATE_FILES = {}
|
|
|
|
try:
|
|
result = NotificationTemplate.get_required_context(EventType.TEST)
|
|
|
|
assert result == []
|
|
finally:
|
|
NotificationTemplate.TEMPLATE_FILES = original_templates
|
|
|
|
|
|
class TestNotificationTemplateJinjaEnv:
|
|
"""Tests for NotificationTemplate Jinja2 environment."""
|
|
|
|
def test_jinja_env_singleton(self):
|
|
"""Test that Jinja environment is a singleton."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
)
|
|
|
|
# Reset the env to test
|
|
NotificationTemplate._jinja_env = None
|
|
|
|
env1 = NotificationTemplate._get_jinja_env()
|
|
env2 = NotificationTemplate._get_jinja_env()
|
|
|
|
# Both should be the same object (or both None if templates don't exist)
|
|
assert env1 is env2
|
|
|
|
|
|
class TestNotificationTemplateClass:
|
|
"""Tests for NotificationTemplate class structure."""
|
|
|
|
def test_template_files_mapping_exists(self):
|
|
"""Test that TEMPLATE_FILES mapping exists."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
)
|
|
|
|
assert hasattr(NotificationTemplate, "TEMPLATE_FILES")
|
|
assert isinstance(NotificationTemplate.TEMPLATE_FILES, dict)
|
|
|
|
def test_class_methods_exist(self):
|
|
"""Test that required class methods exist."""
|
|
from local_deep_research.notifications.templates import (
|
|
NotificationTemplate,
|
|
)
|
|
|
|
assert hasattr(NotificationTemplate, "format")
|
|
assert hasattr(NotificationTemplate, "get_required_context")
|
|
assert hasattr(NotificationTemplate, "_get_fallback_template")
|
|
assert hasattr(NotificationTemplate, "_get_jinja_env")
|
|
|
|
assert callable(NotificationTemplate.format)
|
|
assert callable(NotificationTemplate.get_required_context)
|