Files
markitect-main/capabilities/testdrive-jsui/tests/test_component_listing.py
tegwick 4262310302 feat: enhance ControlBase with advanced panel behavior patterns
Implement comprehensive control panel functionality based on reference patterns:

## New Features
- Icon-only collapsed state with compass positioning
- Expand/drag functionality for repositioning panels
- Bottom-left corner resize with minimum size constraints
- Collapse button returns to original position
- Header toggle for content visibility control

## Technical Improvements
- Enhanced DOM structure with expanded/collapsed states
- Robust event handling with automatic cleanup
- State management for drag, resize, expand operations
- Position restoration system for collapse behavior
- Comprehensive styling system with backdrop effects

## Components Added
- Enhanced ControlBase class with 5 core behaviors
- ContentsControl, StatusControl, EditControl, DebugControl panels
- Component discovery system with TDD implementation
- Legacy DocumentControlsLegacy for backward compatibility

## Testing & Documentation
- Interactive test page for behavior validation
- Comprehensive implementation notes
- TDD test suite with 84 passing tests
- Component listing automation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 11:33:49 +01:00

203 lines
7.6 KiB
Python

#!/usr/bin/env python3
"""
Test for Component Listing Functionality
Tests that all expected UI components are properly discovered and listed
by the component analysis system.
"""
import sys
from pathlib import Path
import json
import subprocess
import pytest
# Add the scripts directory to path
sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))
from list_components import ComponentAnalyzer, list_components
@pytest.mark.javascript
class TestComponentListing:
"""Test cases for component listing functionality."""
def setup_method(self):
"""Setup test environment."""
self.capability_root = Path(__file__).parent.parent
self.analyzer = ComponentAnalyzer(self.capability_root)
def test_expected_panel_components_exist(self):
"""Test that all expected panel components are found."""
expected_panels = {
'ContentsControl': 'js/controls/contents-control.js',
'StatusControl': 'js/controls/status-control.js',
'EditControl': 'js/controls/edit-control.js',
'DebugControl': 'js/controls/debug-control.js',
'DebugPanel': 'js/components/debug-panel.js',
'DocumentControlsLegacy': 'js/components/document-controls-legacy.js',
'SectionManager': 'js/core/section-manager.js',
'DOMRenderer': 'js/components/dom-renderer.js'
}
# Get actual components found by analyzer
js_files = []
js_root = self.capability_root / "js"
if js_root.exists():
for pattern in ["**/*.js"]:
for file_path in js_root.glob(pattern):
path_str = str(file_path)
if ('test' not in file_path.name.lower() and
'/tests/' not in path_str and
'node_modules' not in path_str and
not file_path.name.lower().endswith('.test.js')):
js_files.append(file_path)
# Analyze each file
found_components = {}
for file_path in sorted(js_files):
component_info = self.analyzer.analyze_file(file_path)
if component_info:
found_components[component_info.name] = component_info.file_path
# Check that all expected panels are found
missing_components = []
for expected_name, expected_path in expected_panels.items():
if expected_name not in found_components:
missing_components.append(f"{expected_name} (expected at {expected_path})")
elif found_components[expected_name] != expected_path:
missing_components.append(
f"{expected_name} found at {found_components[expected_name]} "
f"but expected at {expected_path}"
)
if missing_components:
print(f"\n❌ Missing or misplaced components:")
for missing in missing_components:
print(f" - {missing}")
print(f"\n✅ Found components:")
for name, path in found_components.items():
print(f" - {name}: {path}")
assert False, f"Missing {len(missing_components)} expected components: {missing_components}"
print(f"✅ All {len(expected_panels)} expected components found!")
return True
def test_component_lister_json_output_completeness(self):
"""Test that JSON output includes all expected components with proper structure."""
# Capture JSON output
result = subprocess.run([
sys.executable,
str(self.capability_root / "scripts" / "list_components.py"),
"json"
], capture_output=True, text=True, cwd=str(self.capability_root))
assert result.returncode == 0, f"Component lister failed: {result.stderr}"
try:
data = json.loads(result.stdout)
except json.JSONDecodeError as e:
assert False, f"Invalid JSON output: {e}"
# Verify JSON structure
assert "capability" in data
assert "total_components" in data
assert "components" in data
assert data["capability"] == "testdrive-jsui"
# Verify each component has required fields
required_fields = ["name", "type", "file_path", "description", "classes", "methods"]
for component in data["components"]:
for field in required_fields:
assert field in component, f"Component {component.get('name')} missing field: {field}"
# Check for expected panel types
component_names = {comp["name"] for comp in data["components"]}
expected_controls = {"ContentsControl", "StatusControl", "EditControl", "DebugControl"}
found_controls = component_names.intersection(expected_controls)
missing_controls = expected_controls - found_controls
if missing_controls:
print(f"\n❌ Missing control components: {missing_controls}")
print(f"✅ Found components: {component_names}")
assert False, f"Missing control components: {missing_controls}"
return True
def test_component_descriptions_are_meaningful(self):
"""Test that all components have meaningful descriptions."""
result = subprocess.run([
sys.executable,
str(self.capability_root / "scripts" / "list_components.py"),
"json"
], capture_output=True, text=True, cwd=str(self.capability_root))
assert result.returncode == 0, f"Component lister failed: {result.stderr}"
data = json.loads(result.stdout)
generic_descriptions = ["Component implementation", ""]
components_with_poor_descriptions = []
for component in data["components"]:
description = component["description"].strip()
if (not description or
description in generic_descriptions or
len(description) < 20):
components_with_poor_descriptions.append(component["name"])
if components_with_poor_descriptions:
print(f"\n❌ Components with poor descriptions: {components_with_poor_descriptions}")
for comp in data["components"]:
if comp["name"] in components_with_poor_descriptions:
print(f" - {comp['name']}: '{comp['description']}'")
assert False, f"Components need better descriptions: {components_with_poor_descriptions}"
return True
def run_tests():
"""Run all component listing tests."""
test_instance = TestComponentListing()
test_methods = [method for method in dir(test_instance) if method.startswith('test_')]
results = {}
for method_name in test_methods:
print(f"\n🧪 Running {method_name}")
print("=" * 60)
try:
test_instance.setup_method()
method = getattr(test_instance, method_name)
result = method()
results[method_name] = True
print(f"{method_name} PASSED")
except Exception as e:
results[method_name] = False
print(f"{method_name} FAILED: {e}")
import traceback
traceback.print_exc()
# Summary
passed = sum(1 for result in results.values() if result)
total = len(results)
print(f"\n📊 Test Summary:")
print(f" Passed: {passed}/{total}")
print(f" Failed: {total - passed}/{total}")
if passed == total:
print("✅ All tests passed!")
return True
else:
print("❌ Some tests failed!")
return False
if __name__ == "__main__":
success = run_tests()
sys.exit(0 if success else 1)