from pathlib import Path import shutil import pytest from markitect_tool.render import RenderExportRequest from markitect_quarkdown import ( MARKITECT_QUARKDOWN_VERSION_POLICY, MarkitectQuarkdownAdapter, QuarkdownProcessResult, build_quarkdown_execution_plan, export_quarkdown_source, quarkdown_adapter_descriptor, quarkdown_profile_for, validate_quarkdown_artifact, ) def test_quarkdown_descriptor_matches_markitect_render_contract(): descriptor = quarkdown_adapter_descriptor() data = descriptor.to_dict() assert descriptor.id == "render.quarkdown" assert data["kind"] == "render-export" assert descriptor.operations == ["inspect-profile", "export-source", "render-artifact"] assert "pdf" in descriptor.output_profiles assert "application/pdf" in descriptor.artifact_media_types assert descriptor.safety["external_process"] is True assert descriptor.metadata["version_policy"] == MARKITECT_QUARKDOWN_VERSION_POLICY assert descriptor.metadata["open_reuse_integration"] == "integration/quarkdown.integration.yaml" def test_profile_matrix_maps_markitect_profiles_to_quarkdown_modes(): pdf = quarkdown_profile_for("pdf") docs = quarkdown_profile_for("docs") static_site = quarkdown_profile_for("static-site") assert pdf.quarkdown_document_type == "paged" assert pdf.output_format == "pdf" assert pdf.artifact_extension == ".pdf" assert docs.quarkdown_document_type == "docs" assert static_site.output_format == "html" def test_export_source_preserves_render_manifest_identifier(): request = RenderExportRequest( source="# Demo", operation="export-source", profile="docs", render_manifest={"manifest_id": "render-manifest:test"}, ) exported = export_quarkdown_source(request) assert "" in exported assert "" in exported assert "" in exported assert exported.endswith("# Demo") def test_adapter_exports_quarkdown_source_without_invoking_runtime(): adapter = MarkitectQuarkdownAdapter(command_resolver=lambda _command: None) request = RenderExportRequest( source="# Demo", operation="export-source", profile="docs", source_path="docs/demo.md", ) result = adapter.render(request) assert result.valid assert result.exported_source is not None assert result.artifacts[0].role == "renderer-source" assert result.metadata["external_renderer_invoked"] is False def test_render_artifact_reports_missing_runtime_as_structured_diagnostic(): adapter = MarkitectQuarkdownAdapter(command_resolver=lambda _command: None) request = RenderExportRequest(source="# Demo", operation="render-artifact", profile="pdf") result = adapter.render(request) assert not result.valid assert result.diagnostics[0].code == "render.quarkdown.runtime_missing" assert result.metadata["external_renderer_invoked"] is False def test_execution_plan_maps_permissions_and_output_conventions(tmp_path: Path): request = RenderExportRequest( source="# Demo", operation="render-artifact", profile="pdf", options={"artifact_stem": "demo", "permissions": ["project-read"], "deny_network": True}, ) plan = build_quarkdown_execution_plan( request, source_path=tmp_path / "source.qd", output_dir=tmp_path / "out", command="/usr/bin/quarkdown", ) assert plan.expected_artifact_path.endswith("demo.pdf") assert "--allow" in plan.command assert "project-read" in plan.command assert "--deny" in plan.command assert "network" in plan.command assert plan.environment["requires_java"] == "17+" assert plan.environment["requires_node_for_pdf"] == "true" def test_adapter_validates_fake_runner_artifact(tmp_path: Path): def fake_runner(plan): Path(plan.expected_artifact_path).write_text("rendered", encoding="utf-8") return QuarkdownProcessResult(returncode=0, stdout="ok") adapter = MarkitectQuarkdownAdapter( command_resolver=lambda _command: "/usr/bin/quarkdown", runner=fake_runner, ) request = RenderExportRequest( source="# Demo", operation="render-artifact", profile="docs", source_path="docs/demo.md", options={"workspace": str(tmp_path), "output_dir": str(tmp_path / "out"), "artifact_stem": "demo"}, ) result = adapter.render(request) assert result.valid assert result.metadata["external_renderer_invoked"] is True assert result.artifacts[1].role == "rendered-artifact" assert result.artifacts[1].media_type == "text/html" assert result.artifacts[1].path.endswith("demo.html") assert result.artifacts[1].digest.startswith("sha256:") assert result.provenance[0].artifact_id == result.artifacts[1].artifact_id def test_artifact_validation_reports_missing_artifact(tmp_path: Path): request = RenderExportRequest(source="# Demo", operation="render-artifact", profile="pdf") plan = build_quarkdown_execution_plan( request, source_path=tmp_path / "source.qd", output_dir=tmp_path / "out", ) artifact, diagnostics = validate_quarkdown_artifact(plan) assert artifact is None assert diagnostics[0].code == "render.quarkdown.artifact_missing" def test_real_quarkdown_runtime_smoke_skips_when_unavailable(): if shutil.which("quarkdown") is None: pytest.skip("Quarkdown CLI is not installed in this environment.")