Files
Orchestrator/shared/tools/monorepo-cli/tests/test_capture.py
T

179 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Tests for QuickCapture schnelle Wissenserfassung.
Requirements: 3.1, 3.2, 3.3, 3.7, 8.3
"""
from __future__ import annotations
import re
from datetime import datetime
from pathlib import Path
import pytest
from monorepo.knowledge.ingestion.capture import QuickCapture
@pytest.fixture
def monorepo_root(tmp_path: Path) -> Path:
"""Create a minimal monorepo structure for testing."""
for ctx in ("bahn", "dhive", "privat"):
(tmp_path / ctx / "knowledge" / "inbox").mkdir(parents=True)
return tmp_path
@pytest.fixture
def capture(monorepo_root: Path) -> QuickCapture:
"""Create a QuickCapture instance."""
return QuickCapture(monorepo_root)
# ---------------------------------------------------------------------------
# _detect_input_type tests
# ---------------------------------------------------------------------------
class TestDetectInputType:
"""Tests for _detect_input_type."""
def test_detects_http_url(self, capture: QuickCapture) -> None:
assert capture._detect_input_type("http://example.com") == "url"
def test_detects_https_url(self, capture: QuickCapture) -> None:
assert capture._detect_input_type("https://docs.python.org/3/") == "url"
def test_detects_url_with_whitespace(self, capture: QuickCapture) -> None:
assert capture._detect_input_type(" https://example.com ") == "url"
def test_detects_file_path_with_extension(self, capture: QuickCapture) -> None:
assert capture._detect_input_type("/home/user/notes.md") == "file"
def test_detects_windows_path(self, capture: QuickCapture) -> None:
assert capture._detect_input_type("C:\\Users\\doc.pdf") == "file"
def test_plain_text(self, capture: QuickCapture) -> None:
assert capture._detect_input_type("Just a note about something") == "text"
def test_text_with_dot_but_no_separator(self, capture: QuickCapture) -> None:
# e.g. "version 3.14" should not be detected as file
assert capture._detect_input_type("version 3.14 is out") == "text"
# ---------------------------------------------------------------------------
# _generate_filename tests
# ---------------------------------------------------------------------------
class TestGenerateFilename:
"""Tests for _generate_filename."""
def test_filename_format(self, capture: QuickCapture) -> None:
filename = capture._generate_filename("My Test Note")
# Should match YYYY-MM-DD-HH-MM-slug.md
pattern = r"^\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-my-test-note\.md$"
assert re.match(pattern, filename), f"Unexpected filename: {filename}"
def test_filename_slugifies_special_chars(self, capture: QuickCapture) -> None:
filename = capture._generate_filename("Hello, World! (2024)")
assert "hello-world-2024" in filename
def test_filename_limits_slug_length(self, capture: QuickCapture) -> None:
long_title = "a" * 100
filename = capture._generate_filename(long_title)
# Timestamp is 16 chars (YYYY-MM-DD-HH-MM) + 1 dash + slug (<=50) + .md
slug_part = filename.split("-", 5)[-1].replace(".md", "")
assert len(slug_part) <= 50
def test_filename_ends_with_md(self, capture: QuickCapture) -> None:
filename = capture._generate_filename("test")
assert filename.endswith(".md")
def test_filename_collapses_multiple_hyphens(self, capture: QuickCapture) -> None:
filename = capture._generate_filename("foo---bar///baz")
# Should not have consecutive hyphens in slug
slug_part = filename[17:] # skip timestamp prefix "YYYY-MM-DD-HH-MM-"
assert "--" not in slug_part
# ---------------------------------------------------------------------------
# capture() integration tests
# ---------------------------------------------------------------------------
class TestCapture:
"""Tests for capture()."""
def test_capture_text_creates_file(
self, capture: QuickCapture, monorepo_root: Path
) -> None:
result = capture.capture("Eine schnelle Notiz", context="bahn")
assert result.exists()
assert result.parent == monorepo_root / "bahn" / "knowledge" / "inbox"
def test_capture_text_returns_path(self, capture: QuickCapture) -> None:
result = capture.capture("Notiz", context="privat")
assert isinstance(result, Path)
def test_capture_text_frontmatter(
self, capture: QuickCapture, monorepo_root: Path
) -> None:
result = capture.capture(
"Meeting notes from today",
context="dhive",
tags=["meeting", "project-x"],
)
content = result.read_text(encoding="utf-8")
assert "type: inbox" in content
assert 'title: "Meeting notes from today"' in content
assert "created:" in content
assert "source:" in content
assert "type: text" in content
assert "tags: [meeting, project-x]" in content
assert "source_context: dhive" in content
def test_capture_url_detected(
self, capture: QuickCapture, monorepo_root: Path
) -> None:
url = "https://docs.python.org/3/library/pathlib.html"
result = capture.capture(url, context="bahn")
content = result.read_text(encoding="utf-8")
assert "type: url" in content
assert f"[{url}]({url})" in content
def test_capture_file_detected(
self, capture: QuickCapture, monorepo_root: Path
) -> None:
filepath = "/home/user/documents/report.pdf"
result = capture.capture(filepath, context="privat")
content = result.read_text(encoding="utf-8")
assert "type: file" in content
assert f"Source file: `{filepath}`" in content
def test_capture_creates_inbox_dir_if_missing(
self, capture: QuickCapture, monorepo_root: Path
) -> None:
# Remove inbox dir
import shutil
inbox = monorepo_root / "bahn" / "knowledge" / "inbox"
shutil.rmtree(inbox)
assert not inbox.exists()
result = capture.capture("test", context="bahn")
assert result.exists()
assert inbox.exists()
def test_capture_empty_tags(
self, capture: QuickCapture, monorepo_root: Path
) -> None:
result = capture.capture("note", context="bahn")
content = result.read_text(encoding="utf-8")
assert "tags: []" in content
def test_capture_url_title_from_domain(
self, capture: QuickCapture, monorepo_root: Path
) -> None:
result = capture.capture("https://example.com/docs/intro", context="bahn")
content = result.read_text(encoding="utf-8")
assert "example.com/docs/intro" in content