feat: pass alarm style through crontab manager and GraphQL API

- crontab_manager.get_alarms now parses --style from the cron command
  (defaults to 'blink' for legacy entries without --style)
- GraphQL Alarm type gains a 'style' field
- setAlarm accepts a 'style' arg (default 'simple') and validates it
  against the styles registry; unknown styles raise a GraphQL error
- _default_command embeds --style <name> into the cron command
- startRinging accepts 'style' (default 'simple') and passes --style to
  the spawned wecker.py

The crontab remains the single source of truth; the style simply rides
in the cron command alongside --music-file.
This commit is contained in:
2026-07-31 16:20:16 +02:00
parent b3f3db6f13
commit c50f296232
4 changed files with 177 additions and 7 deletions
+35
View File
@@ -72,3 +72,38 @@ def test_set_alarm_rejects_invalid_cron_expression(crontab_file):
manager = CrontabManager(tabfile=crontab_file)
with pytest.raises(ValueError, match="Invalid cron expression"):
manager.set_alarm("test-id", "not-a-cron-expression", "cmd", True)
def test_get_alarms_parses_style(crontab_file):
manager = CrontabManager(tabfile=crontab_file)
manager.set_alarm(
alarm_id="style-id",
cron_expression="30 7 * * *",
command="python wecker.py --style simple",
is_enabled=True,
)
alarms = manager.get_alarms()
assert len(alarms) == 1
assert alarms[0]["style"] == "simple"
def test_get_alarms_parses_eq_style(crontab_file):
manager = CrontabManager(tabfile=crontab_file)
manager.set_alarm(
alarm_id="style-eq-id",
cron_expression="30 7 * * *",
command="python wecker.py --style=blink",
is_enabled=True,
)
assert manager.get_alarms()[0]["style"] == "blink"
def test_get_alarms_legacy_command_defaults_to_blink(crontab_file):
manager = CrontabManager(tabfile=crontab_file)
manager.set_alarm(
alarm_id="legacy-id",
cron_expression="30 7 * * *",
command="python wecker.py",
is_enabled=True,
)
assert manager.get_alarms()[0]["style"] == "blink"