mirror of
https://github.com/esphome/esphome.git
synced 2026-10-07 03:16:37 +00:00
Merge branch 'dev' into store-yaml-firmware
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
"""Tests for RP2040 component public helpers."""
|
||||
"""Tests for RP2040 component public helpers and variant detection."""
|
||||
|
||||
from esphome.components.rp2040 import board_id_has_wifi
|
||||
import pytest
|
||||
|
||||
from esphome.components.rp2040 import _detect_variant, board_id_has_wifi
|
||||
from esphome.components.rp2040.const import VARIANT_RP2040, VARIANT_RP2350
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_BOARD, CONF_VARIANT
|
||||
|
||||
|
||||
def test_board_id_has_wifi_for_known_wifi_board() -> None:
|
||||
@@ -27,3 +32,61 @@ def test_board_id_has_wifi_for_unknown_board_returns_true() -> None:
|
||||
"no CYW43" guard at compile time.
|
||||
"""
|
||||
assert board_id_has_wifi("not-a-real-board-id") is True
|
||||
|
||||
|
||||
def test_detect_variant_derives_variant_from_board() -> None:
|
||||
"""Board alone resolves to the matching variant."""
|
||||
result = _detect_variant({CONF_BOARD: "rpipicow"})
|
||||
assert result[CONF_BOARD] == "rpipicow"
|
||||
assert result[CONF_VARIANT] == VARIANT_RP2040
|
||||
|
||||
|
||||
def test_detect_variant_derives_variant_from_rp2350_board() -> None:
|
||||
"""An RP2350 board resolves to ``RP2350``."""
|
||||
result = _detect_variant({CONF_BOARD: "rpipico2"})
|
||||
assert result[CONF_BOARD] == "rpipico2"
|
||||
assert result[CONF_VARIANT] == VARIANT_RP2350
|
||||
|
||||
|
||||
def test_detect_variant_only_picks_default_board_rp2040() -> None:
|
||||
"""Variant alone picks Pico W as the canonical RP2040 board."""
|
||||
result = _detect_variant({CONF_VARIANT: VARIANT_RP2040})
|
||||
assert result[CONF_BOARD] == "rpipicow"
|
||||
assert result[CONF_VARIANT] == VARIANT_RP2040
|
||||
|
||||
|
||||
def test_detect_variant_only_picks_default_board_rp2350() -> None:
|
||||
"""Variant alone picks Pico 2 W as the canonical RP2350 board."""
|
||||
result = _detect_variant({CONF_VARIANT: VARIANT_RP2350})
|
||||
assert result[CONF_BOARD] == "rpipico2w"
|
||||
assert result[CONF_VARIANT] == VARIANT_RP2350
|
||||
|
||||
|
||||
def test_detect_variant_matching_explicit_variant_passes() -> None:
|
||||
"""Specifying both a board and the matching variant is allowed."""
|
||||
result = _detect_variant({CONF_BOARD: "rpipico2", CONF_VARIANT: VARIANT_RP2350})
|
||||
assert result[CONF_BOARD] == "rpipico2"
|
||||
assert result[CONF_VARIANT] == VARIANT_RP2350
|
||||
|
||||
|
||||
def test_detect_variant_mismatched_variant_raises() -> None:
|
||||
"""Board/variant mismatch must be rejected and name the offending board."""
|
||||
with pytest.raises(
|
||||
cv.Invalid, match=r"does not match the selected board 'rpipicow'"
|
||||
):
|
||||
_detect_variant({CONF_BOARD: "rpipicow", CONF_VARIANT: VARIANT_RP2350})
|
||||
|
||||
|
||||
def test_detect_variant_unknown_board_without_variant_raises() -> None:
|
||||
"""Unknown board with no variant tells the user how to recover."""
|
||||
with pytest.raises(cv.Invalid, match="please specify the chip variant"):
|
||||
_detect_variant({CONF_BOARD: "not-a-real-board"})
|
||||
|
||||
|
||||
def test_detect_variant_unknown_board_with_variant_passes() -> None:
|
||||
"""Unknown board + explicit variant is accepted (with a warning)."""
|
||||
result = _detect_variant(
|
||||
{CONF_BOARD: "not-a-real-board", CONF_VARIANT: VARIANT_RP2040}
|
||||
)
|
||||
assert result[CONF_BOARD] == "not-a-real-board"
|
||||
assert result[CONF_VARIANT] == VARIANT_RP2040
|
||||
|
||||
@@ -70,11 +70,11 @@ def test_numeric_offset_slash() -> None:
|
||||
|
||||
|
||||
def test_star() -> None:
|
||||
assert _parse_cron_part("*", 0, 59, {}) == set(range(0, 60))
|
||||
assert _parse_cron_part("*", 0, 59, {}) == set(range(60))
|
||||
|
||||
|
||||
def test_question() -> None:
|
||||
assert _parse_cron_part("?", 0, 59, {}) == set(range(0, 60))
|
||||
assert _parse_cron_part("?", 0, 59, {}) == set(range(60))
|
||||
|
||||
|
||||
def test_range() -> None:
|
||||
|
||||
@@ -3,8 +3,20 @@
|
||||
import pytest
|
||||
|
||||
from esphome.components.esp32 import const
|
||||
from esphome.components.wifi import has_native_wifi, variant_has_wifi
|
||||
from esphome.const import Platform
|
||||
from esphome.components.wifi import (
|
||||
check_placeholder_credentials,
|
||||
has_native_wifi,
|
||||
variant_has_wifi,
|
||||
)
|
||||
from esphome.const import (
|
||||
CONF_AP,
|
||||
CONF_NETWORKS,
|
||||
CONF_SSID,
|
||||
CONF_WIFI,
|
||||
PLACEHOLDER_WIFI_SSID,
|
||||
Platform,
|
||||
)
|
||||
from esphome.core import EsphomeError, Lambda
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -123,3 +135,65 @@ def test_has_native_wifi_esp32_without_variant_assumes_wifi() -> None:
|
||||
def test_has_native_wifi_rp2040_without_board_assumes_wifi() -> None:
|
||||
"""RP2040 without a board id falls open to True (custom-board default)."""
|
||||
assert has_native_wifi(platform=Platform.RP2040) is True
|
||||
|
||||
|
||||
def _wifi_config(
|
||||
*,
|
||||
networks: list[dict] | None = None,
|
||||
ap: dict | None = None,
|
||||
) -> dict:
|
||||
"""Build a minimal config dict matching the post-validation shape."""
|
||||
wifi: dict = {}
|
||||
if networks is not None:
|
||||
wifi[CONF_NETWORKS] = networks
|
||||
if ap is not None:
|
||||
wifi[CONF_AP] = ap
|
||||
return {CONF_WIFI: wifi}
|
||||
|
||||
|
||||
def test_check_placeholder_credentials_passes_with_real_ssid() -> None:
|
||||
"""A real SSID compiles without complaint."""
|
||||
config = _wifi_config(networks=[{CONF_SSID: "home_network"}])
|
||||
assert check_placeholder_credentials(config) is None
|
||||
|
||||
|
||||
def test_check_placeholder_credentials_refuses_placeholder_ssid() -> None:
|
||||
"""The placeholder SSID is rejected with an actionable message."""
|
||||
config = _wifi_config(networks=[{CONF_SSID: PLACEHOLDER_WIFI_SSID}])
|
||||
with pytest.raises(EsphomeError) as exc_info:
|
||||
check_placeholder_credentials(config)
|
||||
message = str(exc_info.value)
|
||||
assert "wifi.networks[0].ssid" in message
|
||||
assert "secrets.yaml" in message
|
||||
|
||||
|
||||
def test_check_placeholder_credentials_refuses_placeholder_in_second_network() -> None:
|
||||
"""Index reporting picks the placeholder out of a mixed network list."""
|
||||
config = _wifi_config(
|
||||
networks=[
|
||||
{CONF_SSID: "home_network"},
|
||||
{CONF_SSID: PLACEHOLDER_WIFI_SSID},
|
||||
],
|
||||
)
|
||||
with pytest.raises(EsphomeError) as exc_info:
|
||||
check_placeholder_credentials(config)
|
||||
assert "wifi.networks[1].ssid" in str(exc_info.value)
|
||||
|
||||
|
||||
def test_check_placeholder_credentials_refuses_placeholder_ap_ssid() -> None:
|
||||
"""An AP using the placeholder broadcast name is also refused."""
|
||||
config = _wifi_config(ap={CONF_SSID: PLACEHOLDER_WIFI_SSID})
|
||||
with pytest.raises(EsphomeError) as exc_info:
|
||||
check_placeholder_credentials(config)
|
||||
assert "wifi.ap.ssid" in str(exc_info.value)
|
||||
|
||||
|
||||
def test_check_placeholder_credentials_no_wifi_passes() -> None:
|
||||
"""Ethernet-only / wifi-less configs skip the check entirely."""
|
||||
assert check_placeholder_credentials({}) is None
|
||||
|
||||
|
||||
def test_check_placeholder_credentials_skips_template_ssid() -> None:
|
||||
"""A templated (Lambda) SSID is not a string and is skipped."""
|
||||
config = _wifi_config(networks=[{CONF_SSID: Lambda('return "x";')}])
|
||||
assert check_placeholder_credentials(config) is None
|
||||
|
||||
Reference in New Issue
Block a user