skills-vault/skills/fix-title/tests/test_semantic_heading_repai...

193 lines
6.8 KiB
Python

import importlib.util
import json
import pathlib
import sys
import tempfile
import unittest
SCRIPT = (
pathlib.Path(__file__).resolve().parents[1]
/ "scripts"
/ "semantic_heading_repair.py"
)
SPEC = importlib.util.spec_from_file_location("semantic_heading_repair", SCRIPT)
repair = importlib.util.module_from_spec(SPEC)
assert SPEC.loader is not None
sys.modules[SPEC.name] = repair
SPEC.loader.exec_module(repair)
class SemanticHeadingRepairTest(unittest.TestCase):
def test_inspect_reports_only_real_atx_headings(self):
with tempfile.TemporaryDirectory() as tmp:
source = pathlib.Path(tmp) / "source.md"
source.write_text(
"\n".join(
[
"# Title",
"",
"## Section",
"```md",
"# Not a heading",
"```",
"> # quoted content",
" # indented code",
"### Child",
"",
]
),
encoding="utf-8",
)
payload = repair.inspect_payload(source)
self.assertEqual(
[(item["line"], item["level"], item["text"]) for item in payload["headings"]],
[(1, 1, "Title"), (3, 2, "Section"), (9, 3, "Child")],
)
def test_write_inspection_file_uses_utf8(self):
with tempfile.TemporaryDirectory() as tmp:
source = pathlib.Path(tmp) / "source.md"
output = pathlib.Path(tmp) / "heading-map.json"
source.write_text("# 标题\n", encoding="utf-8")
repair.write_inspection(source, output, output_format="json")
payload = json.loads(output.read_text(encoding="utf-8"))
self.assertEqual(payload["headings"][0]["text"], "标题")
def test_apply_plan_rewrites_only_requested_heading_levels(self):
with tempfile.TemporaryDirectory() as tmp:
source = pathlib.Path(tmp) / "source.md"
output = pathlib.Path(tmp) / "fixed.md"
report = pathlib.Path(tmp) / "report.md"
plan = pathlib.Path(tmp) / "plan.json"
source.write_text(
"\n".join(
[
"# 1",
"",
"## GPT",
"",
"# Wrong parent",
"",
"## Wrong child",
"",
"```md",
"# Not a heading",
"```",
"",
]
),
encoding="utf-8",
)
plan.write_text(
json.dumps(
{
"mode": "discussion",
"edits": [
{
"line": 5,
"from_level": 1,
"to_level": 3,
"reason": "GPT reply content belongs under ## GPT.",
},
{
"line": 7,
"from_level": 2,
"to_level": 4,
"reason": "Child heading follows the repaired parent.",
},
],
},
ensure_ascii=False,
),
encoding="utf-8",
)
changed = repair.apply_plan(source, plan, output, report)
self.assertEqual(changed, 2)
self.assertEqual(
output.read_text(encoding="utf-8"),
"\n".join(
[
"# 1",
"",
"## GPT",
"",
"### Wrong parent",
"",
"#### Wrong child",
"",
"```md",
"# Not a heading",
"```",
"",
]
),
)
report_text = report.read_text(encoding="utf-8")
self.assertIn("| 5 | 1 | 3 | Wrong parent |", report_text)
self.assertIn("GPT reply content belongs under ## GPT.", report_text)
def test_apply_plan_rejects_stale_or_wrong_source_plans(self):
with tempfile.TemporaryDirectory() as tmp:
source = pathlib.Path(tmp) / "source.md"
plan = pathlib.Path(tmp) / "plan.json"
source.write_text("# Title\n\n## Section\n", encoding="utf-8")
plan.write_text(
json.dumps(
{
"edits": [
{
"line": 3,
"from_level": 1,
"to_level": 3,
"reason": "This plan was made for another source.",
}
]
},
ensure_ascii=False,
),
encoding="utf-8",
)
with self.assertRaisesRegex(ValueError, "expected level 1"):
repair.apply_plan(source, plan, pathlib.Path(tmp) / "fixed.md", None)
def test_prepare_batch_scaffold_accepts_file_array(self):
with tempfile.TemporaryDirectory() as tmp:
root = pathlib.Path(tmp)
first = root / "one.md"
second = root / "two.md"
output_dir = root / "out"
first.write_text("# One\n\n# Bad\n", encoding="utf-8")
second.write_text("# Two\n\n## Good\n", encoding="utf-8")
items = repair.prepare_batch_scaffold(
[first, second],
mode="artifact",
output_dir=output_dir,
)
self.assertEqual(len(items), 2)
for item in items:
self.assertEqual(item["mode"], "artifact")
self.assertTrue(pathlib.Path(item["heading_map"]).exists())
self.assertTrue(pathlib.Path(item["plan"]).exists())
self.assertTrue(str(item["fixed"]).endswith(".fixed.md"))
plan_payload = json.loads(pathlib.Path(item["plan"]).read_text(encoding="utf-8"))
self.assertEqual(plan_payload["mode"], "artifact")
self.assertEqual(plan_payload["edits"], [])
batch_report = output_dir / "fix-title-batch-report.md"
self.assertIn("one.md", batch_report.read_text(encoding="utf-8"))
if __name__ == "__main__":
unittest.main()