SurfSense/surfsense_backend/tests/unit/automations/test_stores.py
DESKTOP-RTLN3BA\$punk 94e834134f chore: linting
2026-05-28 19:21:29 -07:00

117 lines
3.5 KiB
Python

"""Lock the trigger + action registry contracts.
Both stores share the same API shape (register/get/all + duplicate-raise),
so they're tested together to keep the contract visible side-by-side.
"""
from __future__ import annotations
import pytest
from pydantic import BaseModel
from app.automations.actions.store import (
get_action,
register_action,
)
from app.automations.actions.types import ActionDefinition
from app.automations.triggers.store import (
all_triggers,
get_trigger,
register_trigger,
)
from app.automations.triggers.types import TriggerDefinition
pytestmark = pytest.mark.unit
class _Params(BaseModel):
"""Empty params model used by test-only registrations."""
def _trigger(type_: str = "test_trigger") -> TriggerDefinition:
return TriggerDefinition(
type=type_, description="Test trigger.", params_model=_Params
)
def _action(type_: str = "test_action") -> ActionDefinition:
return ActionDefinition(
type=type_,
name="Test",
description="Test action.",
params_model=_Params,
build_handler=lambda _ctx: lambda _p: {}, # type: ignore[arg-type,return-value]
)
def test_register_trigger_then_get_trigger_returns_the_same_definition(
isolated_trigger_registry: None,
) -> None:
"""The canonical round-trip: register, look up by type, get the same
definition back. Locks the basic registry contract."""
definition = _trigger()
register_trigger(definition)
assert get_trigger("test_trigger") is definition
def test_register_action_then_get_action_returns_the_same_definition(
isolated_action_registry: None,
) -> None:
"""Same round-trip contract for the action registry."""
definition = _action()
register_action(definition)
assert get_action("test_action") is definition
def test_get_trigger_returns_none_for_unknown_type(
isolated_trigger_registry: None,
) -> None:
"""An unknown type returns ``None`` (not raises). Lets callers like
the dispatcher branch on "is this trigger still registered?" without
try/except."""
assert get_trigger("never_registered") is None
def test_get_action_returns_none_for_unknown_type(
isolated_action_registry: None,
) -> None:
"""Same ``None``-not-raise contract on the action side."""
assert get_action("never_registered") is None
def test_register_trigger_rejects_duplicate_type(
isolated_trigger_registry: None,
) -> None:
"""Re-registering the same ``type`` raises rather than silently
overwriting. Locks the safety net against accidental double-import
(e.g., circular imports re-running the registration block)."""
register_trigger(_trigger())
with pytest.raises(ValueError, match="test_trigger"):
register_trigger(_trigger())
def test_register_action_rejects_duplicate_type(
isolated_action_registry: None,
) -> None:
"""Same duplicate-rejection contract on the action side."""
register_action(_action())
with pytest.raises(ValueError, match="test_action"):
register_action(_action())
def test_all_triggers_returns_defensive_snapshot(
isolated_trigger_registry: None,
) -> None:
"""``all_triggers()`` returns a copy: mutating the returned dict does
not corrupt the internal registry. Locks the snapshot contract that
UI/listing endpoints rely on."""
register_trigger(_trigger("snapshot_test"))
snapshot = all_triggers()
snapshot.pop("snapshot_test")
assert get_trigger("snapshot_test") is not None