mdgrep/tests/test_snippets.py
dschlueter 9c7b7e81f9 feat: mdgrep 0.1.0 – boolean full-text search for Markdown
- query language: substrings, phrases, /regex/, AND/OR/NOT (+ UND/ODER/NICHT),
  parentheses; case-insensitive; ReDoS protection via regex timeouts;
  syntax errors with stable code and position
- SearchEngine over in-memory blocks: filters, predicate, grouping, sorting,
  paging, time budget, automatic reload, highlighted snippets
- Markdown loader with split modes file/heading/list/paragraph
- grep-like CLI (mdgrep), JSON output, grep exit codes
- Flask blueprint/app with JSON API and widget assets, dev server
- framework-free JS widget: live search, URL state, filters, paging,
  syntax help, en/de labels, CSS custom properties for theming

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:29:44 +02:00

59 lines
2 KiB
Python

from mdgrep.snippets import ELLIPSIS, segments
def join(segs):
return "".join(s["t"] for s in segs)
def test_short_text_full_with_hits():
segs = segments("hello world", [(6, 11)])
assert segs == [{"t": "hello ", "hit": False}, {"t": "world", "hit": True}]
def test_no_spans_returns_whole_text():
assert segments("abc", []) == [{"t": "abc", "hit": False}]
def test_long_text_windowed_around_hit():
text = " ".join(f"w{i}" for i in range(400))
hit_start = text.index("w200")
segs = segments(text, [(hit_start, hit_start + 4)], max_chars=100, context=30)
assert segs[0]["t"] == ELLIPSIS and segs[-1]["t"] == ELLIPSIS
assert any(s["hit"] and s["t"] == "w200" for s in segs)
assert len(join(segs)) < 150
def test_windows_snap_to_word_boundaries():
text = "alpha beta gamma delta epsilon zeta eta theta iota kappa lambda"
start = text.index("epsilon")
segs = segments(text, [(start, start + 7)], max_chars=20, context=8)
inner = join(s for s in segs if s["t"] != ELLIPSIS)
assert not inner.startswith("lta") and inner.split()[0] in ("gamma", "delta")
def test_multiple_hits_separate_windows():
text = "x " * 300 + "foo " + "y " * 300 + "bar " + "z " * 300
f, b = text.index("foo"), text.index("bar")
segs = segments(text, [(f, f + 3), (b, b + 3)], max_chars=200, context=20)
hits = [s["t"] for s in segs if s["hit"]]
assert hits == ["foo", "bar"]
assert sum(1 for s in segs if s["t"] == ELLIPSIS) == 3
def test_budget_limits_windows_but_keeps_first_hit():
text = ("filler " * 50 + "hit ") * 10
spans = []
pos = 0
while (i := text.find("hit", pos)) != -1:
spans.append((i, i + 3))
pos = i + 3
segs = segments(text, spans, max_chars=60, context=20)
assert sum(1 for s in segs if s["hit"]) >= 1
assert len(join(segs)) < 200
def test_no_hits_long_text_shows_beginning():
text = "start " + "word " * 200
segs = segments(text, [], max_chars=50)
assert segs[0]["t"].startswith("start")
assert segs[-1]["t"] == ELLIPSIS