Scenario-based dashboard testing (042/044) and scenario automation (046) replace the legacy policy/run based validation surface. - drop backend validation routes, service, schemas and DashboardValidationPlugin - add migration 0025_drop_legacy_validation removing legacy tables - redirect legacy settings/automation page to scenario automation surface - remove frontend validation models, routes, components and i18n bundles - repair dangling semantic relations and dead plugin-id fixtures
99 lines
3.2 KiB
Python
99 lines
3.2 KiB
Python
# #region Test.Schemas.Settings [C:2] [TYPE Module] [SEMANTICS test,schema,settings]
|
|
# @BRIEF Tests for schemas/settings.py — NotificationChannel, TranslationScheduleItem.
|
|
# @RELATION BINDS_TO -> [Schemas.Settings.SettingsSchemas]
|
|
# @TEST_EDGE: missing_field -> optional fields default correctly
|
|
# @TEST_EDGE: invalid_type -> validation rejects bad types
|
|
# @TEST_EDGE: serialization -> round-trip via model_dump/model_validate
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from src.schemas.settings import (
|
|
NotificationChannel,
|
|
TranslationScheduleItem,
|
|
)
|
|
|
|
|
|
class TestNotificationChannel:
|
|
"""NotificationChannel — type and target."""
|
|
|
|
def test_minimal(self):
|
|
nc = NotificationChannel(type="SLACK", target="#alerts")
|
|
assert nc.type == "SLACK"
|
|
assert nc.target == "#alerts"
|
|
|
|
def test_missing_field_raises(self):
|
|
with pytest.raises(ValidationError):
|
|
NotificationChannel(type="SLACK")
|
|
with pytest.raises(ValidationError):
|
|
NotificationChannel(target="#alerts")
|
|
|
|
def test_serialize_roundtrip(self):
|
|
nc = NotificationChannel(type="TELEGRAM", target="chat-1")
|
|
data = nc.model_dump()
|
|
restored = NotificationChannel.model_validate(data)
|
|
assert restored.type == "TELEGRAM"
|
|
assert restored.target == "chat-1"
|
|
|
|
|
|
class TestTranslationScheduleItem:
|
|
"""TranslationScheduleItem — schedule with joined job name."""
|
|
|
|
def make_item(self, **overrides):
|
|
defaults = dict(
|
|
schedule_id="s-1",
|
|
job_id="j-1",
|
|
cron_expression="0 * * * *",
|
|
timezone="UTC",
|
|
is_active=True,
|
|
)
|
|
defaults.update(overrides)
|
|
return TranslationScheduleItem(**defaults)
|
|
|
|
def test_minimal(self):
|
|
item = self.make_item()
|
|
assert item.schedule_id == "s-1"
|
|
assert item.job_id == "j-1"
|
|
assert item.job_name is None
|
|
assert item.execution_mode == "full"
|
|
assert item.last_run_at is None
|
|
assert item.next_run_at is None
|
|
|
|
def test_full(self):
|
|
now = datetime.now(timezone.utc)
|
|
item = self.make_item(
|
|
job_name="nightly",
|
|
execution_mode="delta",
|
|
last_run_at=now,
|
|
next_run_at=now,
|
|
created_by="admin",
|
|
created_at=now,
|
|
)
|
|
assert item.job_name == "nightly"
|
|
assert item.execution_mode == "delta"
|
|
assert item.last_run_at == now
|
|
|
|
def test_missing_required_raises(self):
|
|
with pytest.raises(ValidationError):
|
|
TranslationScheduleItem(job_id="j-1", cron_expression="* * * * *", timezone="UTC", is_active=True)
|
|
|
|
def test_from_attributes(self):
|
|
class FakeRow:
|
|
schedule_id = "s-2"
|
|
job_id = "j-2"
|
|
job_name = "nightly"
|
|
cron_expression = "0 0 * * *"
|
|
timezone = "UTC"
|
|
is_active = False
|
|
execution_mode = "full"
|
|
last_run_at = None
|
|
next_run_at = None
|
|
created_by = "admin"
|
|
created_at = None
|
|
|
|
item = TranslationScheduleItem.model_validate(FakeRow())
|
|
assert item.schedule_id == "s-2"
|
|
assert item.is_active is False
|