Files
pablan/backend/tests/test_authoring_sections.py
T
ProfessorNovaandClaude Opus 5 784b76baf7 Pablan, as it stands
Self-hosted knowledge management for SMEs: a split-screen Markdown editor
whose sections an LLM refines while you write, and RAG question answering
over the documents that result. FastAPI + Postgres/pgvector on the back,
SvelteKit on the front, everything OpenAI-compatible and self-hostable.

Squashed into a single commit; the development history stays local.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CA43ZJda8Rbp2hKXNy8f6b
2026-09-04 09:21:37 +02:00

71 lines
2.4 KiB
Python

"""Unit tests for the active-section boundary — the authoritative computation
the refinement endpoint uses (client mirrors it only for a visual hint)."""
from app.authoring.sections import active_section, slice_lines
DOC = """## Zweck
Dieser Ablauf beschreibt die Rechnungsstellung.
## Ablauf
Erst exportieren, dann versenden.
## Fallstricke
"""
def _span(md: str, cursor_line: int) -> tuple[int, int]:
section = active_section(md, cursor_line)
return section.start_line, section.end_line
def test_cursor_in_a_section_selects_from_its_heading_to_the_next() -> None:
# Line 5 is "Erst exportieren, dann versenden." under "## Ablauf" (line 4).
assert _span(DOC, 5) == (4, 5)
_prefix, section, _suffix = slice_lines(DOC, 4, 5)
assert section == "## Ablauf\nErst exportieren, dann versenden."
def test_cursor_on_the_heading_selects_that_section() -> None:
assert _span(DOC, 1) == (1, 2)
def test_trailing_blank_lines_are_excluded() -> None:
# "## Ablauf" body is followed by a blank line before "## Fallstricke";
# the blank must not be part of the section.
start, end = _span(DOC, 4)
assert (start, end) == (4, 5)
def test_content_before_the_first_heading_is_its_own_section() -> None:
md = "Eine Einleitung ohne Überschrift.\n\n## Danach\nText."
assert _span(md, 1) == (1, 1)
def test_a_document_without_headings_is_one_section() -> None:
md = "Nur Fließtext.\nZweite Zeile."
assert _span(md, 2) == (1, 2)
def test_nested_headings_stop_at_a_same_or_higher_level() -> None:
md = "## A\natext\n### A1\nsub\n## B\nbtext"
# Cursor in "## A" (line 1) spans through its subsection "### A1" up to
# the line before "## B".
assert _span(md, 1) == (1, 4)
# Cursor in the subsection spans only the subsection.
assert _span(md, 4) == (3, 4)
def test_a_heading_inside_a_code_fence_is_not_a_boundary() -> None:
md = "## Code\n```\n## nicht echt\n```\nfertig"
assert _span(md, 3) == (1, 5)
def test_a_large_section_narrows_to_the_paragraph_at_the_cursor() -> None:
big = "\n\n".join(f"Absatz {i} " + "x" * 400 for i in range(6))
md = f"## Groß\n{big}"
start, end = _span(md, 6) # somewhere deep in the section
_prefix, section, _suffix = slice_lines(md, start, end)
# Narrowed: a single paragraph, not the whole oversized section.
assert "\n\n" not in section
assert section.startswith("Absatz")