nanobot: 2026-09-11 09:44:11

This commit is contained in:
lachtan
2026-09-11 09:44:13 +02:00
parent 335d718cd4
commit dd3c076f2c
6 changed files with 175 additions and 77 deletions

View File

@@ -34,65 +34,117 @@ def today():
return datetime.now(ZoneInfo("Europe/Prague")).date().isoformat()
@pytest.fixture
def entry_file(tmp_path):
"""Write entry text to a file and return its path, the way the skill does."""
def write(text):
path = tmp_path / "entry.md"
path.write_text(text, encoding="utf-8")
return str(path)
return write
# -- log ---------------------------------------------------------------------
def test_log_appends_with_today_date(projects, capsys):
def test_log_appends_with_today_date(projects, entry_file, capsys):
directory = make_project(projects, "chata")
assert project_cli.cmd_log("chata", "Dřevo objednáno") == 0
assert project_cli.cmd_log("chata", entry_file("Dřevo objednáno")) == 0
memory = (directory / "memory.md").read_text(encoding="utf-8")
assert memory == f"- {today()}: Dřevo objednáno\n"
assert json.loads(capsys.readouterr().out)["appended"].startswith(f"- {today()}:")
def test_log_does_not_join_when_file_lacks_trailing_newline(projects):
def test_log_does_not_join_when_file_lacks_trailing_newline(projects, entry_file):
directory = make_project(projects, "chata", memory="- 2026-09-01: první")
project_cli.cmd_log("chata", "druhý")
project_cli.cmd_log("chata", entry_file("druhý"))
lines = (directory / "memory.md").read_text(encoding="utf-8").splitlines()
assert lines == ["- 2026-09-01: první", f"- {today()}: druhý"]
def test_log_creates_missing_memory_file(projects):
def test_log_creates_missing_memory_file(projects, entry_file):
directory = projects / "chata"
directory.mkdir()
assert project_cli.cmd_log("chata", "první") == 0
assert project_cli.cmd_log("chata", entry_file("první")) == 0
assert (directory / "memory.md").read_text(encoding="utf-8").endswith("první\n")
def test_log_reads_stdin_verbatim(projects, monkeypatch):
def test_log_reads_file_verbatim(projects, entry_file):
directory = make_project(projects, "chata")
text = "Uvozovky „takhle\" a apostrof ' a \"tohle\"\ndruhý řádek"
monkeypatch.setattr(sys, "stdin", io.StringIO(text))
assert project_cli.cmd_log("chata", None) == 0
assert project_cli.cmd_log("chata", entry_file(text)) == 0
memory = (directory / "memory.md").read_text(encoding="utf-8")
assert memory == f"- {today()}: {text}\n"
def test_log_does_not_shorten_long_entry(projects):
def test_log_accepts_text_the_exec_guard_would_reject_on_a_command_line(projects, entry_file):
"""Regression: `Cíl:` / `Závěr:` parse as Windows drive paths in the exec guard.
The guard scans the raw command string, so such text must reach the script
through a file, never as an argument, a heredoc or a pipe.
"""
directory = make_project(projects, "chata")
text = "Cíl: srovnat pánev. Diagnóza/směr: mobilita kyčle. Závěr: pokračovat."
assert project_cli.cmd_log("chata", entry_file(text)) == 0
assert text in (directory / "memory.md").read_text(encoding="utf-8")
def test_log_reads_stdin_when_no_file_given(projects, monkeypatch):
directory = make_project(projects, "chata")
monkeypatch.setattr(sys, "stdin", io.StringIO("ze stdinu"))
assert project_cli.cmd_log("chata", None) == 0
assert (directory / "memory.md").read_text(encoding="utf-8") == f"- {today()}: ze stdinu\n"
def test_log_rejects_missing_file_without_touching_memory(projects, tmp_path, capsys):
directory = make_project(projects, "chata", memory="- 2026-09-01: první\n")
assert project_cli.cmd_log("chata", str(tmp_path / "chybi.md")) == 1
assert "No such file" in capsys.readouterr().err
assert (directory / "memory.md").read_text(encoding="utf-8") == "- 2026-09-01: první\n"
def test_log_does_not_shorten_long_entry(projects, entry_file):
directory = make_project(projects, "chata")
text = "x" * 3000
project_cli.cmd_log("chata", text)
project_cli.cmd_log("chata", entry_file(text))
assert text in (directory / "memory.md").read_text(encoding="utf-8")
def test_log_rejects_empty_input(projects):
def test_log_rejects_empty_input(projects, entry_file):
directory = make_project(projects, "chata", memory="- 2026-09-01: první\n")
assert project_cli.cmd_log("chata", " ") == 1
assert project_cli.cmd_log("chata", entry_file(" ")) == 1
assert (directory / "memory.md").read_text(encoding="utf-8") == "- 2026-09-01: první\n"
def test_log_rejects_unknown_project(projects):
assert project_cli.cmd_log("neznamy", "text") == 1
def test_log_rejects_unknown_project(projects, entry_file):
assert project_cli.cmd_log("neznamy", entry_file("text")) == 1
def test_log_no_longer_accepts_text_on_the_command_line(monkeypatch):
"""`--text` is gone for good: prose in argv is what the exec guard blocks."""
monkeypatch.setattr(sys, "argv", ["project_cli.py", "log", "chata", "--text", "něco"])
with pytest.raises(SystemExit) as excinfo:
project_cli.main()
assert excinfo.value.code == 2
# -- activate ----------------------------------------------------------------