#!/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)