from pathlib import Path from click.testing import CliRunner from markitect_tool.cli import main from markitect_tool.schema import ( InvalidSchemaFormatError, SchemaNotFoundError, load_schema_file, validate_markdown_file, validate_schema, ) SCHEMA_TEXT = """--- schema-id: "https://example.test/schemas/document/v1" version: "1.0.0" status: "stable" --- # Document Schema ## Schema Definition ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Document Schema", "type": "object", "required": ["frontmatter", "headings"], "properties": { "frontmatter": { "type": "object", "required": ["title"], "properties": { "title": {"type": "string"} } }, "headings": { "type": "array", "minItems": 1, "items": { "type": "object", "required": ["level", "text"], "properties": { "level": {"type": "integer"}, "text": {"type": "string"} } } } } } ``` """ def test_load_schema_file_extracts_metadata_and_json_schema(tmp_path: Path): schema_file = tmp_path / "document-schema.md" schema_file.write_text(SCHEMA_TEXT, encoding="utf-8") loaded = load_schema_file(schema_file) assert loaded.metadata["schema-id"] == "https://example.test/schemas/document/v1" assert loaded.metadata["status"] == "stable" assert loaded.schema["title"] == "Document Schema" assert loaded.schema["x-markitect-source"]["format"] == "markdown" assert loaded.source_path == str(schema_file) def test_load_schema_file_requires_json_block(tmp_path: Path): schema_file = tmp_path / "missing.md" schema_file.write_text("# Missing\n\nNo schema.", encoding="utf-8") try: load_schema_file(schema_file) except SchemaNotFoundError as exc: assert "No JSON schema found" in str(exc) else: raise AssertionError("expected SchemaNotFoundError") def test_load_schema_file_rejects_invalid_json(tmp_path: Path): schema_file = tmp_path / "invalid.md" schema_file.write_text("```json\n{invalid json}\n```", encoding="utf-8") try: load_schema_file(schema_file) except InvalidSchemaFormatError as exc: assert "Invalid JSON schema block" in str(exc) else: raise AssertionError("expected InvalidSchemaFormatError") def test_validate_markdown_file_returns_valid_result(tmp_path: Path): schema_file = tmp_path / "document-schema.md" schema_file.write_text(SCHEMA_TEXT, encoding="utf-8") markdown_file = tmp_path / "document.md" markdown_file.write_text("---\ntitle: Example\n---\n\n# Example\n\nBody.", encoding="utf-8") result = validate_markdown_file(markdown_file, schema_file) assert result.valid is True assert result.violations == [] assert result.document_path == str(markdown_file) assert result.schema_path == str(schema_file) def test_validate_markdown_file_reports_violations(tmp_path: Path): schema_file = tmp_path / "document-schema.md" schema_file.write_text(SCHEMA_TEXT, encoding="utf-8") markdown_file = tmp_path / "document.md" markdown_file.write_text("# Missing Title\n\nBody.", encoding="utf-8") result = validate_markdown_file(markdown_file, schema_file) assert result.valid is False assert result.violations assert result.violations[0].path == "$.frontmatter" assert "title" in result.violations[0].message def test_validate_schema_reports_invalid_schema(): result = validate_schema({"type": 7}) assert result.valid is False assert result.violations def test_mkt_validate_exits_zero_for_valid_document(tmp_path: Path): schema_file = tmp_path / "document-schema.md" schema_file.write_text(SCHEMA_TEXT, encoding="utf-8") markdown_file = tmp_path / "document.md" markdown_file.write_text("---\ntitle: Example\n---\n\n# Example\n", encoding="utf-8") result = CliRunner().invoke( main, ["validate", str(markdown_file), "--schema", str(schema_file)] ) assert result.exit_code == 0 assert "valid" in result.output def test_mkt_validate_exits_nonzero_for_invalid_document(tmp_path: Path): schema_file = tmp_path / "document-schema.md" schema_file.write_text(SCHEMA_TEXT, encoding="utf-8") markdown_file = tmp_path / "document.md" markdown_file.write_text("# Missing Title\n", encoding="utf-8") result = CliRunner().invoke( main, ["validate", str(markdown_file), "--schema", str(schema_file)] ) assert result.exit_code == 1 assert "invalid" in result.output def test_mkt_schema_validate(tmp_path: Path): schema_file = tmp_path / "document-schema.md" schema_file.write_text(SCHEMA_TEXT, encoding="utf-8") result = CliRunner().invoke(main, ["schema", "validate", str(schema_file)]) assert result.exit_code == 0 assert "valid" in result.output