Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions tests/hermes_cli/test_cron.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Tests for hermes_cli.cron command handling."""

from argparse import Namespace
from types import SimpleNamespace

import pytest

from cron.jobs import create_job, get_job, list_jobs
from hermes_cli import cron as cron_cli
from hermes_cli.cron import cron_command


Expand Down Expand Up @@ -57,6 +59,11 @@ def test_edit_can_replace_and_clear_skills(self, tmp_cron_dir, capsys):
skills=["maps", "blogwatcher"],
profile="default",
clear_skills=False,
add_skills=None,
remove_skills=None,
script=None,
workdir=None,
no_agent=None,
)
)
updated = get_job(job["id"])
Expand All @@ -79,6 +86,11 @@ def test_edit_can_replace_and_clear_skills(self, tmp_cron_dir, capsys):
skills=None,
profile="",
clear_skills=True,
add_skills=None,
remove_skills=None,
script=None,
workdir=None,
no_agent=None,
)
)
cleared = get_job(job["id"])
Expand All @@ -101,6 +113,9 @@ def test_create_with_multiple_skills(self, tmp_cron_dir, capsys):
skill=None,
skills=["blogwatcher", "maps"],
profile="default",
script=None,
workdir=None,
no_agent=False,
)
)
out = capsys.readouterr().out
Expand All @@ -127,3 +142,127 @@ def test_list_does_not_crash_when_repeat_is_null(self, tmp_cron_dir, capsys):

out = capsys.readouterr().out
assert "Repeat: ∞" in out


def test_cron_list_warns_when_gateway_not_running(monkeypatch, capsys):
monkeypatch.setattr(
"cron.jobs.list_jobs",
lambda include_disabled=False: [
{
"id": "job-1",
"name": "Nightly docs",
"schedule_display": "every day",
"state": "scheduled",
"enabled": True,
"next_run_at": "2026-06-01T00:00:00Z",
"deliver": ["local"],
}
],
)
monkeypatch.setattr("hermes_cli.gateway.find_gateway_pids", lambda: [])

cron_cli.cron_list()

out = capsys.readouterr().out
assert "Gateway is not running" in out
assert "Nightly docs" in out



def test_cron_status_reports_running_gateway(monkeypatch, capsys):
monkeypatch.setattr("hermes_cli.gateway.find_gateway_pids", lambda: [1234, 5678])
monkeypatch.setattr(
"cron.jobs.list_jobs",
lambda include_disabled=False: [
{"next_run_at": "2026-06-01T00:00:00Z"},
{"next_run_at": "2026-05-31T12:00:00Z"},
],
)

cron_cli.cron_status()

out = capsys.readouterr().out
assert "Gateway is running" in out
assert "1234, 5678" in out
assert "2 active job(s)" in out
assert "2026-05-31T12:00:00Z" in out



def test_cron_tick_invokes_scheduler_tick_with_verbose(monkeypatch):
calls = []
monkeypatch.setattr("cron.scheduler.tick", lambda verbose=False: calls.append(verbose))

cron_cli.cron_tick()

assert calls == [True]



def test_cron_create_success_prints_job_details(monkeypatch, capsys):
monkeypatch.setattr(
cron_cli,
"_cron_api",
lambda **kwargs: {
"success": True,
"job_id": "job-1",
"name": "Nightly docs",
"schedule": "every day",
"skills": ["docs"],
"next_run_at": "2026-06-01T00:00:00Z",
"job": {
"script": "scripts/build_docs.py",
"no_agent": True,
"workdir": "/tmp/repo",
"profile": "docs-profile",
},
},
)

args = SimpleNamespace(
schedule="every day",
prompt="refresh docs",
name="Nightly docs",
deliver=None,
repeat=None,
skill="docs",
skills=None,
script="scripts/build_docs.py",
workdir="/tmp/repo",
profile="docs-profile",
no_agent=True,
)

rc = cron_cli.cron_create(args)

out = capsys.readouterr().out
assert rc == 0
assert "Created job: job-1" in out
assert "Skills: docs" in out
assert "Mode: no-agent" in out
assert "Profile: docs-profile" in out



def test_cron_create_failure_returns_nonzero(monkeypatch, capsys):
monkeypatch.setattr(cron_cli, "_cron_api", lambda **kwargs: {"success": False, "error": "boom"})

args = SimpleNamespace(
schedule="every day",
prompt="refresh docs",
name=None,
deliver=None,
repeat=None,
skill=None,
skills=None,
script=None,
workdir=None,
profile=None,
no_agent=False,
)

rc = cron_cli.cron_create(args)

out = capsys.readouterr().out
assert rc == 1
assert "Failed to create job: boom" in out