generated from coulomb/repo-seed
feat: add refactored testdrive-jsui capability with consolidated architecture
Complete integration of refactored testdrive-jsui capability: ## Refactored Architecture - js/ - All JavaScript source (controls, components, core) - static/ - CSS, images, templates - src/testdrive_jsui/ - Python package - tests/ - Python tests ## Plugin Self-Declaration - get_plugin_source_dir() - plugin declares own location - get_asset_paths() - organized asset paths - No hardcoded discovery logic ## Merged Content - Baseline UI scaffold (tutorials, LICENSE, INTRODUCTION.md) - Refactored capability implementation - Comprehensive documentation Ready for standalone use or integration with markitect. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
203
tests/test_component_listing.py
Normal file
203
tests/test_component_listing.py
Normal file
@@ -0,0 +1,203 @@
|
||||
#!/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)
|
||||
Reference in New Issue
Block a user