mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-28 14:07:55 +00:00
* fix(channels): wire channel→agent handler and fix Telegram send pipeline * format code * add supported tests
165 lines
5.3 KiB
Python
165 lines
5.3 KiB
Python
"""Tests for SchedulerStore — SQLite CRUD for scheduled tasks and run logs."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from openjarvis.scheduler.store import SchedulerStore
|
|
|
|
|
|
@pytest.fixture()
|
|
def store(tmp_path):
|
|
"""Create a SchedulerStore backed by a temporary SQLite database."""
|
|
s = SchedulerStore(tmp_path / "scheduler_test.db")
|
|
yield s
|
|
s.close()
|
|
|
|
|
|
def _make_task(task_id: str = "t1", **overrides) -> dict:
|
|
base = {
|
|
"id": task_id,
|
|
"prompt": "summarize the news",
|
|
"schedule_type": "interval",
|
|
"schedule_value": "3600",
|
|
"context_mode": "isolated",
|
|
"status": "active",
|
|
"next_run": "2026-01-01T00:00:00+00:00",
|
|
"last_run": None,
|
|
"agent": "simple",
|
|
"tools": "",
|
|
"metadata": {},
|
|
}
|
|
base.update(overrides)
|
|
return base
|
|
|
|
|
|
# -- Task CRUD ---------------------------------------------------------------
|
|
|
|
|
|
class TestTaskCRUD:
|
|
def test_save_and_get(self, store):
|
|
task = _make_task()
|
|
store.save_task(task)
|
|
got = store.get_task("t1")
|
|
assert got is not None
|
|
assert got["id"] == "t1"
|
|
assert got["prompt"] == "summarize the news"
|
|
assert got["schedule_type"] == "interval"
|
|
assert got["schedule_value"] == "3600"
|
|
|
|
def test_get_missing_returns_none(self, store):
|
|
assert store.get_task("nonexistent") is None
|
|
|
|
def test_list_tasks_all(self, store):
|
|
store.save_task(_make_task("t1"))
|
|
store.save_task(_make_task("t2", status="paused"))
|
|
store.save_task(_make_task("t3", status="completed"))
|
|
all_tasks = store.list_tasks()
|
|
assert len(all_tasks) == 3
|
|
|
|
def test_list_tasks_filtered(self, store):
|
|
store.save_task(_make_task("t1", status="active"))
|
|
store.save_task(_make_task("t2", status="paused"))
|
|
store.save_task(_make_task("t3", status="active"))
|
|
active = store.list_tasks(status="active")
|
|
assert len(active) == 2
|
|
paused = store.list_tasks(status="paused")
|
|
assert len(paused) == 1
|
|
|
|
def test_update_task(self, store):
|
|
task = _make_task()
|
|
store.save_task(task)
|
|
task["status"] = "paused"
|
|
store.update_task(task)
|
|
got = store.get_task("t1")
|
|
assert got["status"] == "paused"
|
|
|
|
def test_delete_task(self, store):
|
|
store.save_task(_make_task())
|
|
store.delete_task("t1")
|
|
assert store.get_task("t1") is None
|
|
|
|
def test_metadata_serialized_as_json(self, store):
|
|
task = _make_task(metadata={"key": "value", "count": 42})
|
|
store.save_task(task)
|
|
got = store.get_task("t1")
|
|
assert got["metadata"] == {"key": "value", "count": 42}
|
|
|
|
|
|
# -- Due tasks ---------------------------------------------------------------
|
|
|
|
|
|
class TestDueTasks:
|
|
def test_get_due_tasks(self, store):
|
|
store.save_task(_make_task("t1", next_run="2026-01-01T00:00:00+00:00"))
|
|
store.save_task(_make_task("t2", next_run="2026-06-01T00:00:00+00:00"))
|
|
store.save_task(_make_task("t3", next_run="2026-03-01T00:00:00+00:00"))
|
|
due = store.get_due_tasks("2026-03-15T00:00:00+00:00")
|
|
ids = {d["id"] for d in due}
|
|
assert "t1" in ids
|
|
assert "t3" in ids
|
|
assert "t2" not in ids
|
|
|
|
def test_due_tasks_excludes_paused(self, store):
|
|
store.save_task(
|
|
_make_task("t1", next_run="2026-01-01T00:00:00+00:00", status="paused")
|
|
)
|
|
due = store.get_due_tasks("2026-06-01T00:00:00+00:00")
|
|
assert len(due) == 0
|
|
|
|
def test_due_tasks_excludes_null_next_run(self, store):
|
|
store.save_task(_make_task("t1", next_run=None))
|
|
due = store.get_due_tasks("2026-06-01T00:00:00+00:00")
|
|
assert len(due) == 0
|
|
|
|
|
|
# -- Run logs ----------------------------------------------------------------
|
|
|
|
|
|
class TestRunLogs:
|
|
def test_log_run_and_retrieve(self, store):
|
|
store.save_task(_make_task())
|
|
store.log_run(
|
|
task_id="t1",
|
|
started_at="2026-01-01T00:00:00+00:00",
|
|
finished_at="2026-01-01T00:01:00+00:00",
|
|
success=True,
|
|
result="Done",
|
|
error="",
|
|
)
|
|
logs = store.get_run_logs("t1")
|
|
assert len(logs) == 1
|
|
assert logs[0]["success"] == 1
|
|
assert logs[0]["result"] == "Done"
|
|
|
|
def test_log_run_failure(self, store):
|
|
store.save_task(_make_task())
|
|
store.log_run(
|
|
task_id="t1",
|
|
started_at="2026-01-01T00:00:00+00:00",
|
|
finished_at="2026-01-01T00:01:00+00:00",
|
|
success=False,
|
|
result="",
|
|
error="Connection timeout",
|
|
)
|
|
logs = store.get_run_logs("t1")
|
|
assert len(logs) == 1
|
|
assert logs[0]["success"] == 0
|
|
assert logs[0]["error"] == "Connection timeout"
|
|
|
|
def test_log_run_limit(self, store):
|
|
store.save_task(_make_task())
|
|
for i in range(20):
|
|
store.log_run(
|
|
task_id="t1",
|
|
started_at=f"2026-01-{i + 1:02d}T00:00:00+00:00",
|
|
finished_at=f"2026-01-{i + 1:02d}T00:01:00+00:00",
|
|
success=True,
|
|
)
|
|
logs = store.get_run_logs("t1", limit=5)
|
|
assert len(logs) == 5
|
|
|
|
def test_get_run_logs_empty(self, store):
|
|
logs = store.get_run_logs("nonexistent")
|
|
assert logs == []
|