mirror of
https://github.com/kuhyx/signal-bot.git
synced 2026-11-10 18:07:29 +01:00
Two commands, food_today and workout_today, each printing the current Warsaw day out of a log another program owns: every meal with its time, calories and source plus the day's total and macros; every workout with every field it carries. Three workout fields are withheld (a reservation phone number, a screenshot path, the sync record id), and the food budget is never printed -- diet_guard keeps that number on the machine on purpose. The spellings the group uses carry a surname, so they are custom aliases in the state directory; aliases.json ships only plain words. The suite points both logs at absent temp files so it can never read the operator's own, and the e2e run writes one invented entry of each under today's date. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
73 lines
2.6 KiB
Python
73 lines
2.6 KiB
Python
# Copyright (c) 2026 Krzysztof Rudnicki. MIT licence.
|
|
"""Reading one day out of a log another program keeps."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from signal_bot.day_log import DayLogError, path_from_env, read_day
|
|
|
|
DAY = "2026-09-04"
|
|
|
|
|
|
def _write(path: Path, document: object) -> Path:
|
|
path.write_text(json.dumps(document), encoding="utf-8")
|
|
return path
|
|
|
|
|
|
def test_the_days_entries_come_back_in_file_order(tmp_path: Path) -> None:
|
|
log = _write(
|
|
tmp_path / "log.json",
|
|
{DAY: [{"desc": "a"}, {"desc": "b"}], "2026-09-03": [{"desc": "old"}]},
|
|
)
|
|
assert read_day(log, DAY) == [{"desc": "a"}, {"desc": "b"}]
|
|
|
|
|
|
def test_a_day_the_log_has_not_reached_is_empty_not_an_error(tmp_path: Path) -> None:
|
|
"""Before breakfast the day has no key yet; that is the normal case."""
|
|
assert read_day(_write(tmp_path / "log.json", {"2026-09-03": [{}]}), DAY) == []
|
|
assert read_day(_write(tmp_path / "log.json", {}), DAY) == []
|
|
|
|
|
|
def test_entries_that_are_not_objects_are_dropped(tmp_path: Path) -> None:
|
|
log = _write(tmp_path / "log.json", {DAY: [{"desc": "a"}, "junk", 3, None]})
|
|
assert read_day(log, DAY) == [{"desc": "a"}]
|
|
|
|
|
|
def test_a_missing_file_is_an_error_because_nothing_today_would_be_a_lie(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
with pytest.raises(DayLogError, match="cannot be read"):
|
|
read_day(tmp_path / "absent.json", DAY)
|
|
|
|
|
|
def test_a_file_that_is_not_json_is_an_error(tmp_path: Path) -> None:
|
|
broken = tmp_path / "log.json"
|
|
broken.write_text("{not json", encoding="utf-8")
|
|
with pytest.raises(DayLogError, match="cannot be read"):
|
|
read_day(broken, DAY)
|
|
|
|
|
|
def test_a_document_that_is_not_an_object_of_days_is_an_error(tmp_path: Path) -> None:
|
|
with pytest.raises(DayLogError, match="not an object of days"):
|
|
read_day(_write(tmp_path / "log.json", [1, 2]), DAY)
|
|
|
|
|
|
def test_a_day_that_is_not_a_list_is_an_error(tmp_path: Path) -> None:
|
|
with pytest.raises(DayLogError, match="not a list of entries"):
|
|
read_day(_write(tmp_path / "log.json", {DAY: {"desc": "a"}}), DAY)
|
|
|
|
|
|
def test_the_path_comes_from_the_environment_or_the_programs_default(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
) -> None:
|
|
monkeypatch.delenv("SOME_LOG", raising=False)
|
|
assert path_from_env("SOME_LOG", "~/x/log.json") == Path.home() / "x/log.json"
|
|
monkeypatch.setenv("SOME_LOG", f" {tmp_path / 'mine.json'} ")
|
|
assert path_from_env("SOME_LOG", "~/x/log.json") == tmp_path / "mine.json"
|
|
monkeypatch.setenv("SOME_LOG", " ")
|
|
assert path_from_env("SOME_LOG", "~/x/log.json") == Path.home() / "x/log.json"
|