1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-20 12:12:24 +01:00

Merge branch 'password_api' into integration

This commit is contained in:
J. Nick Koston
2025-07-02 14:05:12 -05:00
71 changed files with 880 additions and 1137 deletions

View 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

View 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

View 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

View 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"

View 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

View 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

View 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

View 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

View File

@@ -2,6 +2,7 @@ network:
enable_ipv6: true
openthread:
device_type: FTD
channel: 13
network_name: OpenThread-8f28
network_key: 0xdfd34f0f05cad978ec4e32b0413038ff

View File

@@ -1,3 +1,11 @@
esphome:
name: test-web-server-no-ota-idf
esp32:
board: esp32dev
framework:
type: esp-idf
packages:
device_base: !include common.yaml
@@ -6,4 +14,3 @@ packages:
web_server:
port: 8080
version: 2
ota: false

View File

@@ -1,8 +1,6 @@
# Test configuration for ESP-IDF web server with OTA enabled
esphome:
name: test-web-server-ota-idf
# Force ESP-IDF framework
esp32:
board: esp32dev
framework:
@@ -15,17 +13,17 @@ packages:
ota:
- platform: esphome
password: "test_ota_password"
- platform: web_server
# Web server with OTA enabled
# Web server configuration
web_server:
port: 8080
version: 2
ota: true
include_internal: true
# Enable debug logging for OTA
logger:
level: DEBUG
level: VERBOSE
logs:
web_server: VERBOSE
web_server_idf: VERBOSE

View File

@@ -1,11 +1,18 @@
esphome:
name: test-ws-ota-disabled-idf
esp32:
board: esp32dev
framework:
type: esp-idf
packages:
device_base: !include common.yaml
# OTA is configured but web_server OTA is disabled
# OTA is configured but web_server OTA is NOT included
ota:
- platform: esphome
web_server:
port: 8080
version: 2
ota: false