Files
activity-core/tests/test_automation_status.py
2026-07-01 20:12:04 +02:00

185 lines
4.9 KiB
Python

from __future__ import annotations
from datetime import datetime
from pathlib import Path
from zoneinfo import ZoneInfo
from activity_core import automation_status as status
ACTIVITY_ID = "00000000-0000-0000-0000-000000000123"
def _window():
return status.resolve_window(
"2026-06-26",
"2026-06-29",
"Europe/Berlin",
)
def _definition(enabled: bool = True):
return {
"id": ACTIVITY_ID,
"name": "Daily Check",
"enabled": enabled,
"trigger_type": "cron",
"trigger_config": {
"trigger_type": "cron",
"cron_expression": "0 9 * * *",
"timezone": "Europe/Berlin",
"misfire_policy": "skip",
},
"source": "test",
}
def test_friday_shortcut_resolves_to_previous_friday_start() -> None:
now = datetime(2026, 6, 29, 12, 0, tzinfo=ZoneInfo("Europe/Berlin"))
window = status.resolve_window("friday", None, "Europe/Berlin", now=now)
assert window["since"].isoformat() == "2026-06-26T00:00:00+02:00"
assert window["until"].isoformat() == "2026-06-29T12:00:00+02:00"
def test_expected_fires_for_simple_cron_window() -> None:
fires = status.expected_fires(_definition(), _window())
assert fires == [
"2026-06-26T09:00:00+02:00",
"2026-06-27T09:00:00+02:00",
"2026-06-28T09:00:00+02:00",
"2026-06-29T09:00:00+02:00",
]
def test_completed_when_expected_run_exists() -> None:
run = {
"run_id": "run-1",
"activity_id": ACTIVITY_ID,
"scheduled_for": "2026-06-26T07:00:00+00:00",
"fired_at": "2026-06-26T07:00:10+00:00",
"tasks_spawned": 1,
}
report = status.classify_activity(
_definition(),
_window(),
[run],
[{"source": "state_hub_progress", "run_id": "run-1", "output_validated": True}],
None,
["2026-06-26T09:00:00+02:00"],
runs_available=True,
)
assert report["status"] == "completed"
def test_validation_failure_wins_over_completed_run() -> None:
run = {"run_id": "run-1", "activity_id": ACTIVITY_ID, "scheduled_for": None, "fired_at": "2026-06-26T07:00:10+00:00"}
report = status.classify_activity(
_definition(),
_window(),
[run],
[{"source": "working_memory", "run_id": "run-1", "output_validated": False}],
None,
["2026-06-26T09:00:00+02:00"],
runs_available=True,
)
assert report["status"] == "validation_failed"
def test_missed_when_expected_fire_has_no_run_and_runs_available() -> None:
report = status.classify_activity(
_definition(),
_window(),
[],
[],
None,
["2026-06-26T09:00:00+02:00"],
runs_available=True,
)
assert report["status"] == "missed"
def test_disabled_schedule_is_not_counted_as_missed() -> None:
report = status.classify_activity(
_definition(enabled=False),
_window(),
[],
[],
None,
["2026-06-26T09:00:00+02:00"],
runs_available=True,
)
assert report["status"] == "disabled"
def test_scheduled_definition_reports_one_shot_schedule_id() -> None:
definition = {
"id": ACTIVITY_ID,
"name": "One Shot",
"enabled": True,
"trigger_type": "scheduled",
"trigger_config": {
"trigger_type": "scheduled",
"at": "2026-06-26T09:00:00+02:00",
"timezone": "Europe/Berlin",
},
"source": "test",
}
report = status.classify_activity(
definition,
_window(),
[],
[],
None,
["2026-06-26T09:00:00+02:00"],
runs_available=False,
)
assert status.automation_schedule_id(_definition()) == f"activity-schedule-{ACTIVITY_ID}"
assert report["schedule_id"] == f"activity-schedule-{ACTIVITY_ID}-once"
def test_partial_source_availability_is_unknown_not_missed() -> None:
report = status.classify_activity(
_definition(),
_window(),
[],
[],
None,
["2026-06-26T09:00:00+02:00"],
runs_available=False,
)
assert report["status"] == "unknown"
assert "missed-run verdict is unknown" in report["warnings"][0]
def test_working_memory_frontmatter_evidence(tmp_path: Path) -> None:
note = tmp_path / "daily-triage-2026-06-26-run.md"
note.write_text(
"---\n"
"source: activity-core\n"
f"activity_id: {ACTIVITY_ID}\n"
"activity_core_run_id: run-1\n"
"scheduled_for: 2026-06-26T07:00:00+00:00\n"
"output_validated: false\n"
"created: 2026-06-26T07:01:00+00:00\n"
"---\n"
"body\n",
encoding="utf-8",
)
evidence, source = status.load_working_memory_evidence(str(tmp_path), _window())
assert source["status"] == "ok"
assert evidence[0]["run_id"] == "run-1"
assert evidence[0]["output_validated"] is False