mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-25 05:03:52 +01:00 
			
		
		
		
	Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io>
		
			
				
	
	
		
			132 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Tests for AUTO_LOAD functionality including dynamic AUTO_LOAD."""
 | |
| 
 | |
| from pathlib import Path
 | |
| from typing import Any
 | |
| from unittest.mock import Mock
 | |
| 
 | |
| import pytest
 | |
| 
 | |
| from esphome import config, config_validation as cv, yaml_util
 | |
| from esphome.core import CORE
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def fixtures_dir() -> Path:
 | |
|     """Get the fixtures directory."""
 | |
|     return Path(__file__).parent / "fixtures"
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def default_component() -> Mock:
 | |
|     """Create a default mock component for unmocked components."""
 | |
|     return Mock(
 | |
|         auto_load=[],
 | |
|         is_platform_component=False,
 | |
|         is_platform=False,
 | |
|         multi_conf=False,
 | |
|         multi_conf_no_default=False,
 | |
|         dependencies=[],
 | |
|         conflicts_with=[],
 | |
|         config_schema=cv.Schema({}, extra=cv.ALLOW_EXTRA),
 | |
|     )
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def static_auto_load_component() -> Mock:
 | |
|     """Create a mock component with static AUTO_LOAD."""
 | |
|     return Mock(
 | |
|         auto_load=["logger"],
 | |
|         is_platform_component=False,
 | |
|         is_platform=False,
 | |
|         multi_conf=False,
 | |
|         multi_conf_no_default=False,
 | |
|         dependencies=[],
 | |
|         conflicts_with=[],
 | |
|         config_schema=cv.Schema({}, extra=cv.ALLOW_EXTRA),
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_static_auto_load_adds_components(
 | |
|     mock_get_component: Mock,
 | |
|     fixtures_dir: Path,
 | |
|     static_auto_load_component: Mock,
 | |
|     default_component: Mock,
 | |
| ) -> None:
 | |
|     """Test that static AUTO_LOAD triggers loading of specified components."""
 | |
|     CORE.config_path = fixtures_dir / "auto_load_static.yaml"
 | |
| 
 | |
|     config_file = fixtures_dir / "auto_load_static.yaml"
 | |
|     raw_config = yaml_util.load_yaml(config_file)
 | |
| 
 | |
|     component_mocks = {"test_component": static_auto_load_component}
 | |
|     mock_get_component.side_effect = lambda name: component_mocks.get(
 | |
|         name, default_component
 | |
|     )
 | |
| 
 | |
|     result = config.validate_config(raw_config, {})
 | |
| 
 | |
|     # Check for validation errors
 | |
|     assert not result.errors, f"Validation errors: {result.errors}"
 | |
| 
 | |
|     # Logger should have been auto-loaded by test_component
 | |
|     assert "logger" in result
 | |
|     assert "test_component" in result
 | |
| 
 | |
| 
 | |
| def test_dynamic_auto_load_with_config_param(
 | |
|     mock_get_component: Mock,
 | |
|     fixtures_dir: Path,
 | |
|     default_component: Mock,
 | |
| ) -> None:
 | |
|     """Test that dynamic AUTO_LOAD evaluates based on configuration."""
 | |
|     CORE.config_path = fixtures_dir / "auto_load_dynamic.yaml"
 | |
| 
 | |
|     config_file = fixtures_dir / "auto_load_dynamic.yaml"
 | |
|     raw_config = yaml_util.load_yaml(config_file)
 | |
| 
 | |
|     # Track if auto_load was called with config
 | |
|     auto_load_calls = []
 | |
| 
 | |
|     def dynamic_auto_load(conf: dict[str, Any]) -> list[str]:
 | |
|         """Dynamically load components based on config."""
 | |
|         auto_load_calls.append(conf)
 | |
|         component_map = {
 | |
|             "enable_logger": "logger",
 | |
|             "enable_api": "api",
 | |
|         }
 | |
|         return [comp for key, comp in component_map.items() if conf.get(key)]
 | |
| 
 | |
|     dynamic_component = Mock(
 | |
|         auto_load=dynamic_auto_load,
 | |
|         is_platform_component=False,
 | |
|         is_platform=False,
 | |
|         multi_conf=False,
 | |
|         multi_conf_no_default=False,
 | |
|         dependencies=[],
 | |
|         conflicts_with=[],
 | |
|         config_schema=cv.Schema({}, extra=cv.ALLOW_EXTRA),
 | |
|     )
 | |
| 
 | |
|     component_mocks = {"test_component": dynamic_component}
 | |
|     mock_get_component.side_effect = lambda name: component_mocks.get(
 | |
|         name, default_component
 | |
|     )
 | |
| 
 | |
|     result = config.validate_config(raw_config, {})
 | |
| 
 | |
|     # Check for validation errors
 | |
|     assert not result.errors, f"Validation errors: {result.errors}"
 | |
| 
 | |
|     # Verify auto_load was called with the validated config
 | |
|     assert len(auto_load_calls) == 1, "auto_load should be called exactly once"
 | |
|     assert auto_load_calls[0].get("enable_logger") is True
 | |
|     assert auto_load_calls[0].get("enable_api") is False
 | |
| 
 | |
|     # Only logger should be auto-loaded (enable_logger=true in YAML)
 | |
|     assert "logger" in result, (
 | |
|         f"Logger not found in result. Result keys: {list(result.keys())}"
 | |
|     )
 | |
|     # API should NOT be auto-loaded (enable_api=false in YAML)
 | |
|     assert "api" not in result
 | |
|     assert "test_component" in result
 |