mirror of
https://github.com/esphome/esphome.git
synced 2026-10-07 11:26:39 +00:00
Merge remote-tracking branch 'upstream/dev' into neutral-ble-client
# Conflicts: # esphome/components/ble_device_base/ble_gatt_client.h # esphome/components/bluetooth_connection/__init__.py # esphome/components/bluetooth_connection/bluetooth_connection.cpp # esphome/components/bluetooth_connection/bluetooth_connection.h # esphome/components/bluetooth_connection/bluetooth_connection_bluedroid.cpp # esphome/components/bluetooth_connection/bluetooth_connection_bluedroid.h # esphome/components/bluetooth_connection/bluetooth_connection_hub.cpp # esphome/components/bluetooth_connection/bluetooth_connection_hub.h # esphome/components/bluetooth_proxy/__init__.py # esphome/components/bluetooth_proxy/bluetooth_proxy.cpp # esphome/core/defines.h # tests/component_tests/bluetooth_proxy/test_platform_gates.py # tests/components/ble_device_base/__init__.py # tests/components/bluetooth_proxy/test-passive.esp32-c6-idf.yaml
This commit is contained in:
@@ -1,30 +1,62 @@
|
||||
"""Tests for the wake button's wakeup_pin requirement in ld6002b."""
|
||||
"""Tests for the ld6002b validators that reach across platforms.
|
||||
|
||||
wake needs a pin on its own hub, apply_area needs a select on its own hub, and
|
||||
area_config needs both a button and a select on its own hub. Every one of them
|
||||
is a same-instance check, which is the half that breaks quietly.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.components.ld6002b.button import CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA
|
||||
from esphome.components.ld6002b.button import (
|
||||
CONFIG_SCHEMA as BUTTON_CONFIG_SCHEMA,
|
||||
FINAL_VALIDATE_SCHEMA as BUTTON_FINAL_VALIDATE_SCHEMA,
|
||||
)
|
||||
from esphome.components.ld6002b.const import CONF_AREA_CONFIG, CONF_Z_MIN
|
||||
from esphome.components.ld6002b.number import (
|
||||
CONFIG_SCHEMA as NUMBER_CONFIG_SCHEMA,
|
||||
FINAL_VALIDATE_SCHEMA as NUMBER_FINAL_VALIDATE_SCHEMA,
|
||||
)
|
||||
from esphome.config import Config
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_WAKEUP_PIN, PlatformFramework
|
||||
from esphome.const import (
|
||||
CONF_AREA_ID,
|
||||
CONF_BUTTON,
|
||||
CONF_ID,
|
||||
CONF_WAKEUP_PIN,
|
||||
PlatformFramework,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.types import ConfigType
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
HUB_ID = "ld6002b_hub"
|
||||
OTHER_HUB_ID = "ld6002b_other"
|
||||
|
||||
|
||||
def _full_config(hub: ConfigType) -> Config:
|
||||
def _full_config(
|
||||
hub: ConfigType,
|
||||
*,
|
||||
selects: list[ConfigType] | None = None,
|
||||
buttons: list[ConfigType] | None = None,
|
||||
) -> Config:
|
||||
"""A full config carrying one ld6002b hub, as the ID pass leaves it.
|
||||
|
||||
final_validate resolves the hub through get_path_for_id, so the declaring
|
||||
path has to be registered the way validate_config registers it: the path of
|
||||
the id value itself, whose parent is the hub's own config.
|
||||
|
||||
The platform lists are what the cross-platform validators scan, so a test can
|
||||
say which of them exist and which hub each one names.
|
||||
"""
|
||||
full = Config()
|
||||
full["ld6002b"] = [hub]
|
||||
full.declare_ids.append((hub[CONF_ID], ["ld6002b", 0, CONF_ID]))
|
||||
if selects is not None:
|
||||
full["select"] = selects
|
||||
if buttons is not None:
|
||||
full[CONF_BUTTON] = buttons
|
||||
return full
|
||||
|
||||
|
||||
@@ -44,10 +76,33 @@ def _buttons(**buttons: str) -> ConfigType:
|
||||
return config
|
||||
|
||||
|
||||
def _select(*, hub_id: str = HUB_ID) -> ConfigType:
|
||||
"""A select platform config naming area_id on the given hub."""
|
||||
return {
|
||||
"ld6002b_id": ID(hub_id, is_declaration=False, type="ld6002b"),
|
||||
CONF_AREA_ID: {"name": "Area ID"},
|
||||
}
|
||||
|
||||
|
||||
def _area_numbers(*, hub_id: str = HUB_ID) -> ConfigType:
|
||||
"""A number platform config carrying one area_config bound."""
|
||||
return {
|
||||
"ld6002b_id": ID(hub_id, is_declaration=False, type="ld6002b"),
|
||||
CONF_AREA_CONFIG: {CONF_Z_MIN: {"name": "Area Z Min"}},
|
||||
}
|
||||
|
||||
|
||||
def _validated(config: ConfigType) -> ConfigType:
|
||||
"""Run the button schema, then the final validation the hub is checked in."""
|
||||
config = CONFIG_SCHEMA(config)
|
||||
FINAL_VALIDATE_SCHEMA(config)
|
||||
config = BUTTON_CONFIG_SCHEMA(config)
|
||||
BUTTON_FINAL_VALIDATE_SCHEMA(config)
|
||||
return config
|
||||
|
||||
|
||||
def _validated_numbers(config: ConfigType) -> ConfigType:
|
||||
"""The same two passes for the number platform."""
|
||||
config = NUMBER_CONFIG_SCHEMA(config)
|
||||
NUMBER_FINAL_VALIDATE_SCHEMA(config)
|
||||
return config
|
||||
|
||||
|
||||
@@ -80,3 +135,82 @@ def test_other_buttons_do_not_need_the_pin(
|
||||
)
|
||||
|
||||
_validated(_buttons(get_delay="Get Delay"))
|
||||
|
||||
|
||||
def test_apply_area_without_select_is_rejected(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""apply_area sends the staged bounds to whichever area the select names."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF, full_config=_full_config(_hub(wakeup_pin=False))
|
||||
)
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid,
|
||||
match=(
|
||||
r"^apply_area requires select\.area_id for the same ld6002b instance"
|
||||
r" @ data\['apply_area'\]$"
|
||||
),
|
||||
):
|
||||
_validated(_buttons(apply_area="Apply Area"))
|
||||
|
||||
|
||||
def test_apply_area_select_on_another_hub_is_rejected(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""A select exists, but on a second ld6002b -- which cannot serve this one."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
full_config=_full_config(
|
||||
_hub(wakeup_pin=False), selects=[_select(hub_id=OTHER_HUB_ID)]
|
||||
),
|
||||
)
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid,
|
||||
match=(
|
||||
r"^apply_area requires select\.area_id for the same ld6002b instance"
|
||||
r" @ data\['apply_area'\]$"
|
||||
),
|
||||
):
|
||||
_validated(_buttons(apply_area="Apply Area"))
|
||||
|
||||
|
||||
def test_area_config_without_apply_area_is_rejected(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""The six numbers only stage a write; apply_area is what sends it."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
full_config=_full_config(_hub(wakeup_pin=False), selects=[_select()]),
|
||||
)
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid,
|
||||
match=(
|
||||
r"^area_config requires button\.apply_area for the same ld6002b instance"
|
||||
r" @ data\['area_config'\]$"
|
||||
),
|
||||
):
|
||||
_validated_numbers(_area_numbers())
|
||||
|
||||
|
||||
def test_area_config_without_select_is_rejected(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""The validator's other half: the staged bounds also need an area to land in."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
full_config=_full_config(
|
||||
_hub(wakeup_pin=False), buttons=[_buttons(apply_area="Apply Area")]
|
||||
),
|
||||
)
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid,
|
||||
match=(
|
||||
r"^area_config requires select\.area_id for the same ld6002b instance"
|
||||
r" @ data\['area_config'\]$"
|
||||
),
|
||||
):
|
||||
_validated_numbers(_area_numbers())
|
||||
|
||||
Reference in New Issue
Block a user