Files
markitect-main/tests/test_issue_40_associated_files.py
tegwick 3168de49ac
Some checks failed
Test Suite / code-quality (push) Has been cancelled
Test Suite / unit-tests (3.11) (push) Has been cancelled
Test Suite / unit-tests (3.12) (push) Has been cancelled
Test Suite / integration-tests (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / performance-tests (push) Has been cancelled
Test Suite / security-scan (push) Has been cancelled
Test Suite / test-summary (push) Has been cancelled
feat: Complete Issue #40 - Associated Files Management with Interactive vs Automation Mode System
This commit implements comprehensive associated files management and introduces
a mode-based architecture that resolves conflicting requirements between
interactive user workflows and automation/testing scenarios.

## Key Features

### Associated Files Management
- Convention-based file pairing (document.md ↔ document.json)
- Automatic path resolution and file discovery
- Complete CLI command suite for managing file pairs
- Performance optimizations with caching

### Interactive vs Automation Mode System
- Automatic mode detection via TTY, CI environment, and pipes
- Environment variable override (MARKITECT_MODE)
- Interactive mode: Uses associated file paths by default
- Automation mode: Optimizes for speed, memory, and stdout output

### Enhanced CLI Commands
- schema-generate: Auto-places output next to source in interactive mode
- generate-stub: Auto-places output next to schema in interactive mode
- validate: Auto-discovers associated schema files
- New associated-files command group with list, info, status, create subcommands

### Bug Fixes
- Fixed isinstance() errors caused by function shadowing built-in types
- Resolved test failures with new mode system integration
- Ensured backward compatibility for all existing functionality

## Technical Implementation
- Added AssociatedFilesManager class with comprehensive file operations
- Implemented mode detection using environment analysis
- Enhanced format_output function with proper type checking
- Added pytest configuration for automation mode during testing
- Complete test coverage for all new functionality

All 448 tests passing. Maintains full backward compatibility while adding
powerful new interactive features for improved developer experience.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-30 13:09:37 +02:00

271 lines
10 KiB
Python

"""
Tests for Issue #40: Associated Files Management.
This module tests the functionality for managing associated markdown and schema files
with convention-based naming and automatic file placement.
"""
import pytest
from pathlib import Path
from tempfile import TemporaryDirectory
from markitect.associated_files import AssociatedFilesManager
class TestIssue40AssociatedFiles:
"""Test suite for associated files management."""
@pytest.fixture
def manager(self):
"""Create an AssociatedFilesManager instance."""
return AssociatedFilesManager()
@pytest.fixture
def temp_dir(self):
"""Create a temporary directory for testing."""
with TemporaryDirectory() as temp_dir:
yield Path(temp_dir)
def test_associated_files_manager_can_be_created(self, manager):
"""AssociatedFilesManager class should be importable and instantiable."""
assert manager is not None
assert isinstance(manager, AssociatedFilesManager)
def test_get_associated_schema_path(self, manager, temp_dir):
"""Should generate correct associated schema path for markdown file."""
md_file = temp_dir / "document.md"
md_file.write_text("# Test Document")
schema_path = manager.get_associated_schema_path(md_file)
assert schema_path == temp_dir / "document.json"
assert schema_path.parent == md_file.parent
assert schema_path.stem == md_file.stem
def test_get_associated_markdown_path(self, manager, temp_dir):
"""Should generate correct associated markdown path for schema file."""
schema_file = temp_dir / "document.json"
schema_file.write_text('{"type": "object"}')
md_path = manager.get_associated_markdown_path(schema_file)
assert md_path == temp_dir / "document.md"
assert md_path.parent == schema_file.parent
assert md_path.stem == schema_file.stem
def test_find_associated_schema(self, manager, temp_dir):
"""Should find existing associated schema file."""
md_file = temp_dir / "blog_post.md"
schema_file = temp_dir / "blog_post.json"
md_file.write_text("# Blog Post")
schema_file.write_text('{"type": "object"}')
found_schema = manager.find_associated_schema(md_file)
assert found_schema == schema_file
assert found_schema.exists()
def test_find_associated_markdown(self, manager, temp_dir):
"""Should find existing associated markdown file."""
md_file = temp_dir / "article.md"
schema_file = temp_dir / "article.json"
md_file.write_text("# Article")
schema_file.write_text('{"type": "object"}')
found_md = manager.find_associated_markdown(schema_file)
assert found_md == md_file
assert found_md.exists()
def test_find_associated_files_returns_none_when_not_found(self, manager, temp_dir):
"""Should return None when associated files don't exist."""
md_file = temp_dir / "lonely.md"
md_file.write_text("# Lonely Document")
schema_file = temp_dir / "orphan.json"
schema_file.write_text('{"type": "object"}')
assert manager.find_associated_schema(md_file) is None
assert manager.find_associated_markdown(schema_file) is None
def test_has_associated_schema(self, manager, temp_dir):
"""Should correctly detect if markdown file has associated schema."""
md_file = temp_dir / "test.md"
schema_file = temp_dir / "test.json"
md_file.write_text("# Test")
# No schema initially
assert not manager.has_associated_schema(md_file)
# Create schema
schema_file.write_text('{"type": "object"}')
assert manager.has_associated_schema(md_file)
def test_has_associated_markdown(self, manager, temp_dir):
"""Should correctly detect if schema file has associated markdown."""
md_file = temp_dir / "guide.md"
schema_file = temp_dir / "guide.json"
schema_file.write_text('{"type": "object"}')
# No markdown initially
assert not manager.has_associated_markdown(schema_file)
# Create markdown
md_file.write_text("# Guide")
assert manager.has_associated_markdown(schema_file)
def test_list_file_pairs(self, manager, temp_dir):
"""Should list all associated file pairs in directory."""
# Create some paired files
(temp_dir / "doc1.md").write_text("# Doc 1")
(temp_dir / "doc1.json").write_text('{"type": "object"}')
(temp_dir / "doc2.md").write_text("# Doc 2")
(temp_dir / "doc2.json").write_text('{"type": "object"}')
# Create orphaned files
(temp_dir / "orphan.md").write_text("# Orphan")
(temp_dir / "lonely.json").write_text('{"type": "object"}')
pairs = manager.list_file_pairs(temp_dir)
assert len(pairs) == 2
pair_names = {pair['basename'] for pair in pairs}
assert 'doc1' in pair_names
assert 'doc2' in pair_names
def test_get_file_pair_info(self, manager, temp_dir):
"""Should provide detailed information about file pairs."""
md_file = temp_dir / "example.md"
schema_file = temp_dir / "example.json"
md_file.write_text("# Example Document\n\nContent here.")
schema_file.write_text('{"type": "object", "title": "Example Schema"}')
pair_info = manager.get_file_pair_info(md_file)
assert pair_info['basename'] == 'example'
assert pair_info['markdown_file'] == md_file
assert pair_info['schema_file'] == schema_file
assert pair_info['both_exist'] is True
assert 'markdown_size' in pair_info
assert 'schema_size' in pair_info
def test_supports_nested_directories(self, manager, temp_dir):
"""Should work correctly with nested directory structures."""
nested_dir = temp_dir / "docs" / "architecture"
nested_dir.mkdir(parents=True)
md_file = nested_dir / "system.md"
schema_file = nested_dir / "system.json"
md_file.write_text("# System Architecture")
schema_path = manager.get_associated_schema_path(md_file)
assert schema_path == schema_file
assert not manager.has_associated_schema(md_file)
schema_file.write_text('{"type": "object"}')
assert manager.has_associated_schema(md_file)
def test_handles_complex_filenames(self, manager, temp_dir):
"""Should handle complex filenames with special characters."""
complex_name = "my-complex_file.name-v2"
md_file = temp_dir / f"{complex_name}.md"
md_file.write_text("# Complex File")
schema_path = manager.get_associated_schema_path(md_file)
expected_schema = temp_dir / f"{complex_name}.json"
assert schema_path == expected_schema
assert schema_path.stem == complex_name
def test_validate_file_extensions(self, manager, temp_dir):
"""Should validate that files have correct extensions."""
txt_file = temp_dir / "document.txt"
txt_file.write_text("Not markdown")
from markitect.associated_files import InvalidFileTypeError
with pytest.raises(InvalidFileTypeError, match="Expected markdown file"):
manager.get_associated_schema_path(txt_file)
xml_file = temp_dir / "schema.xml"
xml_file.write_text("<schema/>")
with pytest.raises(InvalidFileTypeError, match="Expected schema file"):
manager.get_associated_markdown_path(xml_file)
class TestAssociatedFilesIntegration:
"""Test integration of associated files with existing commands."""
@pytest.fixture
def manager(self):
return AssociatedFilesManager()
@pytest.fixture
def temp_dir(self):
with TemporaryDirectory() as temp_dir:
yield Path(temp_dir)
def test_schema_generate_default_output_placement(self, manager, temp_dir):
"""Schema generation should default to placing output next to source."""
md_file = temp_dir / "article.md"
md_file.write_text("# Article\n\n## Introduction\n\nContent here.")
expected_schema_path = manager.get_associated_schema_path(md_file)
# This would be the expected behavior for schema-generate command
assert expected_schema_path == temp_dir / "article.json"
def test_stub_generate_default_output_placement(self, manager, temp_dir):
"""Stub generation should default to placing output next to schema."""
schema_file = temp_dir / "template.json"
schema_file.write_text('''{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "Template Schema"
}''')
expected_md_path = manager.get_associated_markdown_path(schema_file)
# This would be the expected behavior for generate-stub command
assert expected_md_path == temp_dir / "template.md"
def test_validation_auto_discovery(self, manager, temp_dir):
"""Validation should auto-discover associated schema files."""
md_file = temp_dir / "document.md"
schema_file = temp_dir / "document.json"
md_file.write_text("# Document")
schema_file.write_text('{"type": "object"}')
# Validation command should find schema automatically
found_schema = manager.find_associated_schema(md_file)
assert found_schema == schema_file
def test_workflow_roundtrip(self, manager, temp_dir):
"""Test complete workflow: markdown → schema → stub."""
# Start with markdown
original_md = temp_dir / "workflow_test.md"
original_md.write_text("# Workflow Test\n\n## Section 1\n\nContent.")
# Generate schema (should place next to original)
schema_path = manager.get_associated_schema_path(original_md)
assert schema_path == temp_dir / "workflow_test.json"
# Create the schema (simulating schema-generate command)
schema_path.write_text('{"type": "object", "title": "Workflow Test"}')
# Generate stub from schema (should use different name to avoid conflict)
stub_path = temp_dir / "workflow_test_stub.md" # Avoiding conflict with original
# Verify the association logic works
assert manager.has_associated_schema(original_md)
assert manager.has_associated_markdown(schema_path)