generated from coulomb/repo-seed
WP-0001 (Foundation & LEVEL1 Core):
- manifest model (FR-100), MD→DOCX builder (FR-200), DOCX→MD importer
(FR-300/400), template family registry (FR-600), drift detector (FR-700),
CLI wiring, pre-commit config, CI skeleton, regression harness
WP-0002 (Service Interfaces & Workflow Orchestration):
- REST service via FastAPI (FR-900): /health, /version, /capabilities,
/templates, /styles, /validate, /build, /import, /compare,
/templates/register, /workflows/{name}, /evidence/{run_id}
- Evidence & report store (FR-1400): JSON-backed, per-run, retrievable
through all interfaces, classification (pass/warnings/failed)
- Composite workflow orchestration (FR-1300): single-file-roundtrip,
multi-file-roundtrip, release-regression, family-switch-build
- MCP server via FastMCP (FR-1000): all tools + resources
- CLI additions: `markidocx serve`, `markidocx workflow`, `markidocx mcp`
- Interface parity tests: CLI / REST / MCP produce equivalent results
135 tests passing, ruff + mypy clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
86 lines
3.3 KiB
Python
86 lines
3.3 KiB
Python
"""Tests for MD→DOCX builder (FR-200, FR-501–508)."""
|
||
|
||
from __future__ import annotations
|
||
|
||
from pathlib import Path
|
||
|
||
from markidocx.builder import build_document
|
||
from markidocx.manifest import load_manifest
|
||
|
||
|
||
class TestBuildDocument:
|
||
def test_build_produces_docx(self, tmp_project: Path) -> None:
|
||
manifest = load_manifest(tmp_project / "manifest.yaml")
|
||
result = build_document(manifest)
|
||
assert result.success
|
||
assert result.output_path.exists()
|
||
assert result.output_path.suffix == ".docx"
|
||
|
||
def test_build_result_has_family_and_level(self, tmp_project: Path) -> None:
|
||
manifest = load_manifest(tmp_project / "manifest.yaml")
|
||
result = build_document(manifest)
|
||
assert result.family == "article"
|
||
assert result.feature_level == "level1"
|
||
|
||
def test_build_creates_output_dir(self, tmp_path: Path) -> None:
|
||
(tmp_path / "doc.md").write_text("# Hello\n\nContent.", encoding="utf-8")
|
||
import yaml
|
||
|
||
(tmp_path / "manifest.yaml").write_text(
|
||
yaml.dump(
|
||
{
|
||
"project": {"name": "Test", "feature_level": "level1", "family": "article"},
|
||
"sources": [{"path": "doc.md"}],
|
||
"output": {"dir": "./out/nested"},
|
||
}
|
||
)
|
||
)
|
||
manifest = load_manifest(tmp_path / "manifest.yaml")
|
||
result = build_document(manifest)
|
||
assert result.success
|
||
assert result.output_path.exists()
|
||
|
||
def test_build_all_families(self, tmp_path: Path) -> None:
|
||
import yaml
|
||
|
||
(tmp_path / "doc.md").write_text("# Hello\n\nContent.", encoding="utf-8")
|
||
for family in ("article", "book", "website"):
|
||
(tmp_path / "manifest.yaml").write_text(
|
||
yaml.dump(
|
||
{
|
||
"project": {"name": family, "feature_level": "level1", "family": family},
|
||
"sources": [{"path": "doc.md"}],
|
||
"output": {"dir": f"./dist/{family}"},
|
||
}
|
||
)
|
||
)
|
||
manifest = load_manifest(tmp_path / "manifest.yaml")
|
||
result = build_document(manifest)
|
||
assert result.success, f"Build failed for family {family}"
|
||
assert result.output_path.exists()
|
||
|
||
def test_build_with_metadata(self, tmp_path: Path) -> None:
|
||
import yaml
|
||
|
||
(tmp_path / "doc.md").write_text("# Hello\n\nContent.", encoding="utf-8")
|
||
(tmp_path / "manifest.yaml").write_text(
|
||
yaml.dump(
|
||
{
|
||
"project": {"name": "Meta Doc", "feature_level": "level1", "family": "article"},
|
||
"sources": [{"path": "doc.md"}],
|
||
"output": {"dir": "./dist"},
|
||
"metadata": {"title": "My Title", "author": "Alice"},
|
||
}
|
||
)
|
||
)
|
||
manifest = load_manifest(tmp_path / "manifest.yaml")
|
||
result = build_document(manifest)
|
||
assert result.success
|
||
|
||
def test_build_level1_constructs(self, tmp_project: Path) -> None:
|
||
"""Build with headings, lists, tables present in SIMPLE_MARKDOWN."""
|
||
manifest = load_manifest(tmp_project / "manifest.yaml")
|
||
result = build_document(manifest)
|
||
assert result.success
|
||
assert not result.errors
|