update
This commit is contained in:
@@ -66,3 +66,96 @@ async def test_done_step(testdb):
|
||||
assert await gb.done_step(TOPIC, FMT) == 3 # bis fakten_gate fertig
|
||||
await db.set_guide_card(TOPIC, FMT, "a", stage="done")
|
||||
assert await gb.done_step(TOPIC, FMT) == len(gb.GUIDE_STAGES)
|
||||
|
||||
|
||||
async def test_run_card_sets_and_clears_live_info(testdb, monkeypatch):
|
||||
"""Regression: _live nutzte env.format_name (existiert nicht) → AttributeError beim
|
||||
ersten Stage-Start. Treibt eine Karte durch _run_card mit Fake-Stage."""
|
||||
import asyncio
|
||||
from types import SimpleNamespace
|
||||
import guide_board as gb
|
||||
db = testdb
|
||||
await db.upsert_guide_card("t", "Guide", "alpha", "Alpha")
|
||||
env = SimpleNamespace(ctx=None, guide_id="g-live", topic="t", format="Guide")
|
||||
card = {"block_norm": "alpha", "block": "Alpha", "stage": "lernziele", "status": "open"}
|
||||
seen = {}
|
||||
|
||||
async def fake_stage(env2, card2):
|
||||
seen.update(dict(gb._live_info))
|
||||
card2["stage"] = "done"
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(gb, "_STAGE_FN", {"lernziele": fake_stage})
|
||||
await gb._run_card(env, card, asyncio.Semaphore(1))
|
||||
assert card["stage"] == "done"
|
||||
assert ("t", "Guide", "alpha") in seen # live info stand während der Stage
|
||||
assert ("t", "Guide", "alpha") not in gb._live_info # und wurde aufgeräumt
|
||||
|
||||
|
||||
def test_merge_split_sections_one_section_all_markers():
|
||||
import guide_board as gb
|
||||
from textkit import _parse_fragment
|
||||
a = _parse_fragment("""<!-- section: Front Matter -->
|
||||
<!-- compact -->
|
||||
Kurzer Einstieg kompakt.
|
||||
<!-- sub: beginner | YAML-Basics -->
|
||||
YAML kompakt.
|
||||
<!-- ausführlich -->
|
||||
Einstieg ausführlich.
|
||||
<!-- sub: beginner | YAML-Basics -->
|
||||
YAML ausführlich.""")[0]
|
||||
b = _parse_fragment("""<!-- section: Front Matter (Teil 2) -->
|
||||
<!-- compact -->
|
||||
<!-- sub: advanced | TOML-Sektionen -->
|
||||
TOML kompakt.
|
||||
<!-- ausführlich -->
|
||||
Unerwünschter zweiter Einstieg.
|
||||
<!-- sub: advanced | TOML-Sektionen -->
|
||||
TOML ausführlich.""")[0]
|
||||
merged = gb._merge_split_sections(a, b)
|
||||
secs = _parse_fragment(merged)
|
||||
assert len(secs) == 1
|
||||
sec = secs[0]
|
||||
assert sec["title"] == "Front Matter"
|
||||
assert [s["title"] for s in sec["subs"]] == ["YAML-Basics", "TOML-Sektionen"]
|
||||
assert sec["anchor"] == "Einstieg ausführlich." # Teil-B-Einstieg verworfen
|
||||
assert "TOML ausführlich." in sec["md"] and "YAML kompakt." in sec["compact"]
|
||||
|
||||
|
||||
async def test_writer_splits_oversized_first_draft(testdb, monkeypatch, tmp_path):
|
||||
import guide_board as gb
|
||||
from types import SimpleNamespace
|
||||
db = testdb
|
||||
await db.upsert_guide_card("t", "Guide", "gross", "Gross")
|
||||
calls = []
|
||||
|
||||
async def fake_slot(ctx, label, *, key, prompt, role, capabilities, payload, timeout, on_line=None):
|
||||
calls.append(label)
|
||||
part = "2" if key.endswith("-b") else "1"
|
||||
p = tmp_path / f"out-{key[-1]}.md"
|
||||
p.write_text(f"<!-- section: Gross -->\n<!-- ausführlich -->\n"
|
||||
+ ("Einstieg.\n" if part == "1" else "")
|
||||
+ f"<!-- sub: beginner | Sub {part} -->\nText {part}.", encoding="utf-8")
|
||||
# payload liest die ECHTE Slot-Datei — wir schreiben direkt an deren Pfad
|
||||
import re as _re
|
||||
m = _re.search(r"(/\S+\.md)", prompt)
|
||||
with open(m.group(1), "w", encoding="utf-8") as f:
|
||||
f.write(p.read_text(encoding="utf-8"))
|
||||
return "ok", payload(None)
|
||||
|
||||
monkeypatch.setattr(gb, "run_single_slot", fake_slot)
|
||||
subs = [{"title": f"Sub {i}", "level": "beginner", "relevance": "relevant"} for i in range(31)]
|
||||
env = SimpleNamespace(ctx=SimpleNamespace(topic="t", provider="p", is_cancelled=lambda: False),
|
||||
guide_id="g", topic="t", format="Guide", instructions="",
|
||||
subs_by_title={"Gross": subs}, spec="",
|
||||
slot=lambda name: tmp_path / name)
|
||||
monkeypatch.setattr(gb, "_card_facts", lambda e, b: "")
|
||||
card = {"block_norm": "gross", "block": "Gross", "stage": "writer", "status": "open",
|
||||
"writer_rounds": 0, "gate_info": "", "md": "", "chapter": "K1"}
|
||||
ok = await gb._stage_writer(env, card)
|
||||
assert ok is True
|
||||
assert [c for c in calls if "(1/2)" in c] and [c for c in calls if "(2/2)" in c]
|
||||
from textkit import _parse_fragment
|
||||
secs = _parse_fragment(card["md"])
|
||||
assert len(secs) == 1 and [s["title"] for s in secs[0]["subs"]] == ["Sub 1", "Sub 2"]
|
||||
assert card["stage"] == "fakten_gate"
|
||||
|
||||
Reference in New Issue
Block a user