142 lines
4.4 KiB
Python
142 lines
4.4 KiB
Python
"""Tests for note_capture.py — dumb capture into notes/inbox/ + audit log."""
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts"))
|
|
import note_capture # noqa: E402
|
|
|
|
FILENAME_RE = re.compile(r"^\d{4}-\d{2}-\d{2}_\d{2}_\d{2}_\d{2}_\d{6}-[a-z0-9-]+\.md$")
|
|
|
|
|
|
@pytest.fixture
|
|
def workspace(tmp_path, monkeypatch):
|
|
inbox = tmp_path / "notes" / "inbox"
|
|
log = tmp_path / "log" / "note.log"
|
|
monkeypatch.setattr(note_capture, "INBOX", inbox)
|
|
monkeypatch.setattr(note_capture, "LOG", log)
|
|
return tmp_path
|
|
|
|
|
|
def _run(workspace, text=None, argv_extra=None):
|
|
"""Build argv the way the skill does: text in a file, only its path in the command."""
|
|
argv = ["note_capture.py"]
|
|
if text is not None:
|
|
source = workspace / "note-capture.md"
|
|
source.write_text(text, encoding="utf-8")
|
|
argv += ["--file", str(source)]
|
|
if argv_extra:
|
|
argv += argv_extra
|
|
return argv
|
|
|
|
|
|
def test_slugify_from_words():
|
|
assert note_capture._slugify("Mazání starých images") == "mazani-starych-images"
|
|
|
|
|
|
def test_slugify_caps_word_count():
|
|
assert note_capture._slugify("one two three four five six") == "one-two-three-four"
|
|
|
|
|
|
def test_slugify_bare_url_uses_domain():
|
|
assert (
|
|
note_capture._slugify("https://www.darkove-sklo.com/x/y") == "darkove-sklo-com"
|
|
)
|
|
|
|
|
|
def test_slugify_empty_falls_back():
|
|
assert note_capture._slugify("!!!") == "note"
|
|
|
|
|
|
def test_capture_writes_inbox_file_and_log(workspace, monkeypatch):
|
|
monkeypatch.setattr(
|
|
sys,
|
|
"argv",
|
|
_run(workspace, "koupit kanistr na vodu", ["--channel", "telegram", "--chat-id", "42"]),
|
|
)
|
|
assert note_capture.main() == 0
|
|
|
|
files = list((workspace / "notes" / "inbox").glob("*.md"))
|
|
assert len(files) == 1
|
|
name = files[0].name
|
|
assert FILENAME_RE.match(name), name
|
|
|
|
content = files[0].read_text(encoding="utf-8")
|
|
assert content.startswith("---\n")
|
|
assert "channel: telegram" in content
|
|
assert 'chat_id: "42"' in content
|
|
assert "koupit kanistr na vodu" in content
|
|
|
|
log_lines = (
|
|
(workspace / "log" / "note.log").read_text(encoding="utf-8").splitlines()
|
|
)
|
|
assert len(log_lines) == 1
|
|
assert "CAPTURE" in log_lines[0]
|
|
assert name in log_lines[0]
|
|
|
|
|
|
def test_capture_no_leftover_tmp_files(workspace, monkeypatch):
|
|
monkeypatch.setattr(sys, "argv", _run(workspace, "neco"))
|
|
assert note_capture.main() == 0
|
|
tmp_files = list((workspace / "notes" / "inbox").glob(".*"))
|
|
assert tmp_files == []
|
|
|
|
|
|
def test_capture_omits_absent_provenance(workspace, monkeypatch):
|
|
monkeypatch.setattr(sys, "argv", _run(workspace, "bez kanalu"))
|
|
assert note_capture.main() == 0
|
|
content = next((workspace / "notes" / "inbox").glob("*.md")).read_text(
|
|
encoding="utf-8"
|
|
)
|
|
assert "channel:" not in content
|
|
assert "chat_id:" not in content
|
|
|
|
|
|
def test_capture_empty_input_fails(workspace, monkeypatch):
|
|
monkeypatch.setattr(sys, "argv", _run(workspace, " "))
|
|
assert note_capture.main() == 1
|
|
assert list((workspace / "notes" / "inbox").glob("*.md")) == []
|
|
|
|
|
|
def test_capture_accepts_text_the_exec_guard_would_reject_on_a_command_line(
|
|
workspace, monkeypatch
|
|
):
|
|
"""Regression: a note like `Cíl: …` parses as a Windows drive path in the exec guard.
|
|
|
|
Capture takes the user's input verbatim, so such text must reach the script
|
|
through a file, never as an argument, a heredoc or a pipe.
|
|
"""
|
|
text = "Cíl: koupit mléko. Závěr: zítra."
|
|
monkeypatch.setattr(sys, "argv", _run(workspace, text))
|
|
|
|
assert note_capture.main() == 0
|
|
|
|
content = next((workspace / "notes" / "inbox").glob("*.md")).read_text(
|
|
encoding="utf-8"
|
|
)
|
|
assert text in content
|
|
|
|
|
|
def test_capture_rejects_missing_file(workspace, monkeypatch, capsys):
|
|
monkeypatch.setattr(
|
|
sys, "argv", ["note_capture.py", "--file", str(workspace / "chybi.md")]
|
|
)
|
|
|
|
assert note_capture.main() == 1
|
|
|
|
assert "No such file" in capsys.readouterr().err
|
|
assert list((workspace / "notes" / "inbox").glob("*.md")) == []
|
|
|
|
|
|
def test_capture_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", ["note_capture.py", "--text", "něco"])
|
|
|
|
with pytest.raises(SystemExit) as excinfo:
|
|
note_capture.main()
|
|
|
|
assert excinfo.value.code == 2
|