generated from coulomb/repo-seed
Implemented all cleanup items from CLEANUP_REPORT.md: Legacy Code Removal: - Removed document-controls-legacy.js wrapper - Updated 4 test files to use DocumentControls directly - Updated scripts/list_components.py acronym mappings - Updated tests/test_component_listing.py expectations Archive and Organization: - Moved relicts/ to docs/prototypes/ with README explaining history - Moved MIGRATION_STATUS.md to docs/migration/ - Removed IMPLEMENTATION_NOTES.md legacy references Test Verification: - All 68 JavaScript tests passing (Jest) - All 3 Python component tests passing - No breaking changes to functionality The codebase is now cleaner with no legacy wrappers or empty directories. Migration is complete and documented. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
203 lines
7.5 KiB
Python
203 lines
7.5 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',
|
|
'DocumentControls': 'js/components/document-controls.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) |