mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 06:33:51 +00:00 
			
		
		
		
	Replace custom OTA implementation in web_server_base (#9274)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										102
									
								
								tests/component_tests/ota/test_web_server_ota.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								tests/component_tests/ota/test_web_server_ota.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| """Tests for the web_server OTA platform.""" | ||||
|  | ||||
| from collections.abc import Callable | ||||
|  | ||||
|  | ||||
| def test_web_server_ota_generated(generate_main: Callable[[str], str]) -> None: | ||||
|     """Test that web_server OTA platform generates correct code.""" | ||||
|     main_cpp = generate_main("tests/component_tests/ota/test_web_server_ota.yaml") | ||||
|  | ||||
|     # Check that the web server OTA component is included | ||||
|     assert "WebServerOTAComponent" in main_cpp | ||||
|     assert "web_server::WebServerOTAComponent" in main_cpp | ||||
|  | ||||
|     # Check that global web server base is referenced | ||||
|     assert "global_web_server_base" in main_cpp | ||||
|  | ||||
|     # Check component is registered | ||||
|     assert "App.register_component(web_server_webserverotacomponent_id)" in main_cpp | ||||
|  | ||||
|  | ||||
| def test_web_server_ota_with_callbacks(generate_main: Callable[[str], str]) -> None: | ||||
|     """Test web_server OTA with state callbacks.""" | ||||
|     main_cpp = generate_main( | ||||
|         "tests/component_tests/ota/test_web_server_ota_callbacks.yaml" | ||||
|     ) | ||||
|  | ||||
|     # Check that web server OTA component is present | ||||
|     assert "WebServerOTAComponent" in main_cpp | ||||
|  | ||||
|     # Check that callbacks are configured | ||||
|     # The actual callback code is in the component implementation, not main.cpp | ||||
|     # But we can check that logger.log statements are present from the callbacks | ||||
|     assert "logger.log" in main_cpp | ||||
|     assert "OTA started" in main_cpp | ||||
|     assert "OTA completed" in main_cpp | ||||
|     assert "OTA error" in main_cpp | ||||
|  | ||||
|  | ||||
| def test_web_server_ota_idf_multipart(generate_main: Callable[[str], str]) -> None: | ||||
|     """Test that ESP-IDF builds include multipart parser dependency.""" | ||||
|     main_cpp = generate_main("tests/component_tests/ota/test_web_server_ota_idf.yaml") | ||||
|  | ||||
|     # Check that web server OTA component is present | ||||
|     assert "WebServerOTAComponent" in main_cpp | ||||
|  | ||||
|     # For ESP-IDF builds, the framework type is esp-idf | ||||
|     # The multipart parser dependency is added by web_server_idf | ||||
|     assert "web_server::WebServerOTAComponent" in main_cpp | ||||
|  | ||||
|  | ||||
| def test_web_server_ota_without_web_server_fails( | ||||
|     generate_main: Callable[[str], str], | ||||
| ) -> None: | ||||
|     """Test that web_server OTA requires web_server component.""" | ||||
|     # This should fail during validation since web_server_base is required | ||||
|     # but we can't test validation failures with generate_main | ||||
|     # Instead, verify that both components are needed in valid config | ||||
|     main_cpp = generate_main("tests/component_tests/ota/test_web_server_ota.yaml") | ||||
|  | ||||
|     # Both web server and OTA components should be present | ||||
|     assert "WebServer" in main_cpp | ||||
|     assert "WebServerOTAComponent" in main_cpp | ||||
|  | ||||
|  | ||||
| def test_multiple_ota_platforms(generate_main: Callable[[str], str]) -> None: | ||||
|     """Test multiple OTA platforms can coexist.""" | ||||
|     main_cpp = generate_main("tests/component_tests/ota/test_web_server_ota_multi.yaml") | ||||
|  | ||||
|     # Check all OTA platforms are included | ||||
|     assert "WebServerOTAComponent" in main_cpp | ||||
|     assert "ESPHomeOTAComponent" in main_cpp | ||||
|     assert "OtaHttpRequestComponent" in main_cpp | ||||
|  | ||||
|     # Check components are from correct namespaces | ||||
|     assert "web_server::WebServerOTAComponent" in main_cpp | ||||
|     assert "esphome::ESPHomeOTAComponent" in main_cpp | ||||
|     assert "http_request::OtaHttpRequestComponent" in main_cpp | ||||
|  | ||||
|  | ||||
| def test_web_server_ota_arduino_with_auth(generate_main: Callable[[str], str]) -> None: | ||||
|     """Test web_server OTA with Arduino framework and authentication.""" | ||||
|     main_cpp = generate_main( | ||||
|         "tests/component_tests/ota/test_web_server_ota_arduino.yaml" | ||||
|     ) | ||||
|  | ||||
|     # Check web server OTA component is present | ||||
|     assert "WebServerOTAComponent" in main_cpp | ||||
|  | ||||
|     # Check authentication is set up for web server | ||||
|     assert "set_auth_username" in main_cpp | ||||
|     assert "set_auth_password" in main_cpp | ||||
|  | ||||
|  | ||||
| def test_web_server_ota_esp8266(generate_main: Callable[[str], str]) -> None: | ||||
|     """Test web_server OTA on ESP8266 platform.""" | ||||
|     main_cpp = generate_main( | ||||
|         "tests/component_tests/ota/test_web_server_ota_esp8266.yaml" | ||||
|     ) | ||||
|  | ||||
|     # Check web server OTA component is present | ||||
|     assert "WebServerOTAComponent" in main_cpp | ||||
|     assert "web_server::WebServerOTAComponent" in main_cpp | ||||
							
								
								
									
										15
									
								
								tests/component_tests/ota/test_web_server_ota.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/component_tests/ota/test_web_server_ota.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| esphome: | ||||
|   name: test_web_server_ota | ||||
|  | ||||
| esp32: | ||||
|   board: esp32dev | ||||
|  | ||||
| wifi: | ||||
|   ssid: MySSID | ||||
|   password: password1 | ||||
|  | ||||
| web_server: | ||||
|   port: 80 | ||||
|  | ||||
| ota: | ||||
|   - platform: web_server | ||||
							
								
								
									
										18
									
								
								tests/component_tests/ota/test_web_server_ota_arduino.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								tests/component_tests/ota/test_web_server_ota_arduino.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| esphome: | ||||
|   name: test_web_server_ota_arduino | ||||
|  | ||||
| esp32: | ||||
|   board: esp32dev | ||||
|  | ||||
| wifi: | ||||
|   ssid: MySSID | ||||
|   password: password1 | ||||
|  | ||||
| web_server: | ||||
|   port: 80 | ||||
|   auth: | ||||
|     username: admin | ||||
|     password: admin | ||||
|  | ||||
| ota: | ||||
|   - platform: web_server | ||||
							
								
								
									
										31
									
								
								tests/component_tests/ota/test_web_server_ota_callbacks.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tests/component_tests/ota/test_web_server_ota_callbacks.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| esphome: | ||||
|   name: test_web_server_ota_callbacks | ||||
|  | ||||
| esp32: | ||||
|   board: esp32dev | ||||
|  | ||||
| wifi: | ||||
|   ssid: MySSID | ||||
|   password: password1 | ||||
|  | ||||
| logger: | ||||
|  | ||||
| web_server: | ||||
|   port: 80 | ||||
|  | ||||
| ota: | ||||
|   - platform: web_server | ||||
|     on_begin: | ||||
|       - logger.log: "OTA started" | ||||
|     on_progress: | ||||
|       - logger.log: | ||||
|           format: "OTA progress: %.1f%%" | ||||
|           args: ["x"] | ||||
|     on_end: | ||||
|       - logger.log: "OTA completed" | ||||
|     on_error: | ||||
|       - logger.log: | ||||
|           format: "OTA error: %d" | ||||
|           args: ["x"] | ||||
|     on_state_change: | ||||
|       - logger.log: "OTA state changed" | ||||
							
								
								
									
										15
									
								
								tests/component_tests/ota/test_web_server_ota_esp8266.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/component_tests/ota/test_web_server_ota_esp8266.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| esphome: | ||||
|   name: test_web_server_ota_esp8266 | ||||
|  | ||||
| esp8266: | ||||
|   board: nodemcuv2 | ||||
|  | ||||
| wifi: | ||||
|   ssid: MySSID | ||||
|   password: password1 | ||||
|  | ||||
| web_server: | ||||
|   port: 80 | ||||
|  | ||||
| ota: | ||||
|   - platform: web_server | ||||
							
								
								
									
										17
									
								
								tests/component_tests/ota/test_web_server_ota_idf.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tests/component_tests/ota/test_web_server_ota_idf.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| esphome: | ||||
|   name: test_web_server_ota_idf | ||||
|  | ||||
| esp32: | ||||
|   board: esp32dev | ||||
|   framework: | ||||
|     type: esp-idf | ||||
|  | ||||
| wifi: | ||||
|   ssid: MySSID | ||||
|   password: password1 | ||||
|  | ||||
| web_server: | ||||
|   port: 80 | ||||
|  | ||||
| ota: | ||||
|   - platform: web_server | ||||
							
								
								
									
										21
									
								
								tests/component_tests/ota/test_web_server_ota_multi.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/component_tests/ota/test_web_server_ota_multi.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| esphome: | ||||
|   name: test_web_server_ota_multi | ||||
|  | ||||
| esp32: | ||||
|   board: esp32dev | ||||
|  | ||||
| wifi: | ||||
|   ssid: MySSID | ||||
|   password: password1 | ||||
|  | ||||
| web_server: | ||||
|   port: 80 | ||||
|  | ||||
| http_request: | ||||
|   verify_ssl: false | ||||
|  | ||||
| ota: | ||||
|   - platform: esphome | ||||
|     password: "test_password" | ||||
|   - platform: web_server | ||||
|   - platform: http_request | ||||
							
								
								
									
										38
									
								
								tests/component_tests/web_server/test_ota_migration.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								tests/component_tests/web_server/test_ota_migration.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| """Tests for web_server OTA migration validation.""" | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from esphome import config_validation as cv | ||||
| from esphome.types import ConfigType | ||||
|  | ||||
|  | ||||
| def test_web_server_ota_true_fails_validation() -> None: | ||||
|     """Test that web_server with ota: true fails validation with helpful message.""" | ||||
|     from esphome.components.web_server import validate_ota_removed | ||||
|  | ||||
|     # Config with ota: true should fail | ||||
|     config: ConfigType = {"ota": True} | ||||
|  | ||||
|     with pytest.raises(cv.Invalid) as exc_info: | ||||
|         validate_ota_removed(config) | ||||
|  | ||||
|     # Check error message contains migration instructions | ||||
|     error_msg = str(exc_info.value) | ||||
|     assert "has been removed from 'web_server'" in error_msg | ||||
|     assert "platform: web_server" in error_msg | ||||
|     assert "ota:" in error_msg | ||||
|  | ||||
|  | ||||
| def test_web_server_ota_false_passes_validation() -> None: | ||||
|     """Test that web_server with ota: false passes validation.""" | ||||
|     from esphome.components.web_server import validate_ota_removed | ||||
|  | ||||
|     # Config with ota: false should pass | ||||
|     config: ConfigType = {"ota": False} | ||||
|     result = validate_ota_removed(config) | ||||
|     assert result == config | ||||
|  | ||||
|     # Config without ota should also pass | ||||
|     config: ConfigType = {} | ||||
|     result = validate_ota_removed(config) | ||||
|     assert result == config | ||||
		Reference in New Issue
	
	Block a user