Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

300 lines
8.9 KiB
Python

"""
Tests for news/core/base_card.py
Tests cover:
- CardSource dataclass
- CardVersion dataclass
- BaseCard abstract class
- Card initialization and field generation
"""
import pytest
from unittest.mock import Mock
from dataclasses import is_dataclass
from abc import ABC
class TestCardSourceDataclass:
"""Tests for CardSource dataclass."""
def test_card_source_is_dataclass(self):
"""CardSource is a dataclass."""
from local_deep_research.news.core.base_card import CardSource
assert is_dataclass(CardSource)
def test_card_source_required_type_field(self):
"""CardSource requires type field."""
from local_deep_research.news.core.base_card import CardSource
source = CardSource(type="news_item")
assert source.type == "news_item"
def test_card_source_optional_fields_defaults(self):
"""CardSource has optional fields with defaults."""
from local_deep_research.news.core.base_card import CardSource
source = CardSource(type="test")
assert source.source_id is None
assert source.created_from == ""
assert source.metadata == {}
def test_card_source_custom_metadata(self):
"""CardSource accepts custom metadata."""
from local_deep_research.news.core.base_card import CardSource
source = CardSource(
type="test",
metadata={"query": "test query", "timestamp": "2024-01-01"},
)
assert source.metadata["query"] == "test query"
assert source.metadata["timestamp"] == "2024-01-01"
class TestCardVersionDataclass:
"""Tests for CardVersion dataclass."""
def test_card_version_is_dataclass(self):
"""CardVersion is a dataclass."""
from local_deep_research.news.core.base_card import CardVersion
assert is_dataclass(CardVersion)
def test_card_version_initialization(self):
"""CardVersion initializes with required fields."""
from local_deep_research.news.core.base_card import CardVersion
from datetime import datetime
version = CardVersion(
version_id="v1",
created_at=datetime.now(),
content={"result": "test"},
query_used="test query",
)
assert version.version_id == "v1"
assert version.query_used == "test query"
assert version.content == {"result": "test"}
def test_card_version_optional_search_strategy(self):
"""CardVersion has optional search_strategy."""
from local_deep_research.news.core.base_card import CardVersion
from datetime import datetime
version = CardVersion(
version_id="v1",
created_at=datetime.now(),
content={},
query_used="test",
)
assert version.search_strategy is None
def test_card_version_generates_id_if_empty(self):
"""CardVersion generates ID if provided ID is empty."""
from local_deep_research.news.core.base_card import CardVersion
from datetime import datetime
version = CardVersion(
version_id="",
created_at=datetime.now(),
content={},
query_used="test",
)
assert version.version_id != ""
assert len(version.version_id) > 0
class TestBaseCardClass:
"""Tests for BaseCard abstract class."""
def test_base_card_is_abstract(self):
"""BaseCard is an abstract class."""
from local_deep_research.news.core.base_card import BaseCard
assert issubclass(BaseCard, ABC)
def test_base_card_is_dataclass(self):
"""BaseCard is a dataclass."""
from local_deep_research.news.core.base_card import BaseCard
assert is_dataclass(BaseCard)
class TestConcreteCard:
"""Tests using a concrete implementation of BaseCard."""
@pytest.fixture
def card_source(self):
"""Create a card source."""
from local_deep_research.news.core.base_card import CardSource
return CardSource(type="test")
@pytest.fixture
def concrete_card_class(self):
"""Create a concrete card class."""
from local_deep_research.news.core.base_card import BaseCard
class TestCard(BaseCard):
def get_card_type(self):
return "test"
def to_dict(self):
return {"id": self.id, "topic": self.topic}
return TestCard
def test_card_initialization(self, concrete_card_class, card_source):
"""Card initializes with required fields."""
card = concrete_card_class(
topic="Test Topic",
source=card_source,
user_id="user123",
)
assert card.topic == "Test Topic"
assert card.source is card_source
assert card.user_id == "user123"
def test_card_generates_id(self, concrete_card_class, card_source):
"""Card generates ID when not provided."""
card = concrete_card_class(
topic="Test Topic",
source=card_source,
user_id="user123",
)
assert card.id is not None
assert len(card.id) > 0
def test_card_uses_provided_id(self, concrete_card_class, card_source):
"""Card uses provided card_id."""
card = concrete_card_class(
topic="Test Topic",
source=card_source,
user_id="user123",
card_id="custom-id-123",
)
assert card.id == "custom-id-123"
def test_card_timestamps_generated(self, concrete_card_class, card_source):
"""Card generates timestamps on creation."""
card = concrete_card_class(
topic="Test Topic",
source=card_source,
user_id="user123",
)
assert card.created_at is not None
assert card.updated_at is not None
def test_card_interaction_defaults(self, concrete_card_class, card_source):
"""Card has default interaction values."""
card = concrete_card_class(
topic="Test Topic",
source=card_source,
user_id="user123",
)
assert card.interaction["votes_up"] == 0
assert card.interaction["votes_down"] == 0
assert card.interaction["views"] == 0
assert card.interaction["shares"] == 0
def test_card_empty_versions_list(self, concrete_card_class, card_source):
"""Card has empty versions list initially."""
card = concrete_card_class(
topic="Test Topic",
source=card_source,
user_id="user123",
)
assert card.versions == []
def test_card_optional_parent_id(self, concrete_card_class, card_source):
"""Card has optional parent_card_id."""
card = concrete_card_class(
topic="Test Topic",
source=card_source,
user_id="user123",
parent_card_id="parent-123",
)
assert card.parent_card_id == "parent-123"
def test_card_default_metadata(self, concrete_card_class, card_source):
"""Card has empty default metadata."""
card = concrete_card_class(
topic="Test Topic",
source=card_source,
user_id="user123",
)
assert card.metadata == {}
def test_card_custom_metadata(self, concrete_card_class, card_source):
"""Card accepts custom metadata."""
card = concrete_card_class(
topic="Test Topic",
source=card_source,
user_id="user123",
metadata={"key": "value"},
)
assert card.metadata == {"key": "value"}
class TestCardProgressCallback:
"""Tests for card progress callback."""
@pytest.fixture
def card_source(self):
"""Create a card source."""
from local_deep_research.news.core.base_card import CardSource
return CardSource(type="test")
@pytest.fixture
def concrete_card_class(self):
"""Create a concrete card class."""
from local_deep_research.news.core.base_card import BaseCard
class TestCard(BaseCard):
def get_card_type(self):
return "test"
def to_dict(self):
return {"id": self.id, "topic": self.topic}
return TestCard
def test_card_progress_callback_initially_none(
self, concrete_card_class, card_source
):
"""Card progress_callback is None initially."""
card = concrete_card_class(
topic="Test",
source=card_source,
user_id="user123",
)
assert card.progress_callback is None
def test_card_set_progress_callback(self, concrete_card_class, card_source):
"""Card can set progress callback."""
card = concrete_card_class(
topic="Test",
source=card_source,
user_id="user123",
)
callback = Mock()
card.set_progress_callback(callback)
assert card.progress_callback is callback