mirror of
https://github.com/esphome/esphome.git
synced 2026-10-10 21:39:06 +00:00
186 lines
6.2 KiB
Python
186 lines
6.2 KiB
Python
"""Validation tests for the unpaired access policy.
|
|
|
|
The hub's `unpaired_access` key and an `unpaired_access` switch both set the
|
|
policy, so the switch platform rejects a config that has both.
|
|
"""
|
|
|
|
import logging
|
|
|
|
import pytest
|
|
|
|
from esphome import config_validation as cv
|
|
from esphome.components.sendspin import (
|
|
CONF_UNPAIRED_ACCESS,
|
|
CONFIG_SCHEMA as HUB_CONFIG_SCHEMA,
|
|
DOMAIN,
|
|
FINAL_VALIDATE_SCHEMA as HUB_FINAL_VALIDATE_SCHEMA,
|
|
_get_data,
|
|
request_pairing_code_display_support,
|
|
)
|
|
from esphome.components.sendspin.switch import (
|
|
CONFIG_SCHEMA as SWITCH_CONFIG_SCHEMA,
|
|
FINAL_VALIDATE_SCHEMA as SWITCH_FINAL_VALIDATE_SCHEMA,
|
|
)
|
|
from esphome.const import PlatformFramework
|
|
from esphome.types import ConfigType
|
|
from tests.component_tests.types import SetCoreConfigCallable
|
|
|
|
HUB_ID = "sendspin_hub_id"
|
|
NO_PAIRING_WARNING = "no new server can pair with this device"
|
|
|
|
|
|
def _switch_config(switch_type: str) -> ConfigType:
|
|
return SWITCH_CONFIG_SCHEMA(
|
|
{"name": "Sendspin Switch", "type": switch_type, "sendspin_id": HUB_ID}
|
|
)
|
|
|
|
|
|
def test_hub_key_absent_by_default(set_core_config: SetCoreConfigCallable) -> None:
|
|
"""With no default in the schema, the switch can tell whether the key was set."""
|
|
set_core_config(PlatformFramework.ESP32_IDF)
|
|
|
|
assert CONF_UNPAIRED_ACCESS not in HUB_CONFIG_SCHEMA({"id": HUB_ID})
|
|
|
|
|
|
@pytest.mark.parametrize("value", [True, False])
|
|
def test_hub_key_accepted(set_core_config: SetCoreConfigCallable, value: bool) -> None:
|
|
set_core_config(PlatformFramework.ESP32_IDF)
|
|
|
|
config = HUB_CONFIG_SCHEMA({"id": HUB_ID, CONF_UNPAIRED_ACCESS: value})
|
|
|
|
assert config[CONF_UNPAIRED_ACCESS] is value
|
|
|
|
|
|
def test_off_without_pairing_method_warns(
|
|
set_core_config: SetCoreConfigCallable, caplog: pytest.LogCaptureFixture
|
|
) -> None:
|
|
"""With unpaired access off and no way to pair, no new server could pair."""
|
|
set_core_config(PlatformFramework.ESP32_IDF)
|
|
config = HUB_CONFIG_SCHEMA({"id": HUB_ID, CONF_UNPAIRED_ACCESS: False})
|
|
|
|
with caplog.at_level(logging.WARNING):
|
|
HUB_FINAL_VALIDATE_SCHEMA(config)
|
|
|
|
assert NO_PAIRING_WARNING in caplog.text
|
|
|
|
|
|
@pytest.mark.parametrize("method", ["static_pairing_code", "pairing_code"])
|
|
def test_off_with_pairing_method_does_not_warn(
|
|
set_core_config: SetCoreConfigCallable,
|
|
caplog: pytest.LogCaptureFixture,
|
|
method: str,
|
|
) -> None:
|
|
set_core_config(PlatformFramework.ESP32_IDF)
|
|
hub_config = {"id": HUB_ID, CONF_UNPAIRED_ACCESS: False}
|
|
if method == "static_pairing_code":
|
|
hub_config["static_pairing_code"] = "01234567"
|
|
else:
|
|
request_pairing_code_display_support()
|
|
config = HUB_CONFIG_SCHEMA(hub_config)
|
|
|
|
with caplog.at_level(logging.WARNING):
|
|
HUB_FINAL_VALIDATE_SCHEMA(config)
|
|
|
|
assert NO_PAIRING_WARNING not in caplog.text
|
|
|
|
|
|
def test_on_does_not_warn(
|
|
set_core_config: SetCoreConfigCallable, caplog: pytest.LogCaptureFixture
|
|
) -> None:
|
|
set_core_config(PlatformFramework.ESP32_IDF)
|
|
config = HUB_CONFIG_SCHEMA({"id": HUB_ID})
|
|
|
|
with caplog.at_level(logging.WARNING):
|
|
HUB_FINAL_VALIDATE_SCHEMA(config)
|
|
|
|
assert NO_PAIRING_WARNING not in caplog.text
|
|
|
|
|
|
def test_switch_with_hub_key_rejected(set_core_config: SetCoreConfigCallable) -> None:
|
|
"""Both would set the policy, and the hub's value would be silently ignored."""
|
|
set_core_config(
|
|
PlatformFramework.ESP32_IDF,
|
|
full_config={DOMAIN: {"id": HUB_ID, CONF_UNPAIRED_ACCESS: False}},
|
|
)
|
|
config = _switch_config(CONF_UNPAIRED_ACCESS)
|
|
|
|
with pytest.raises(cv.Invalid, match="set the switch's restore_mode instead"):
|
|
SWITCH_FINAL_VALIDATE_SCHEMA(config)
|
|
|
|
|
|
def test_switch_without_hub_key_accepted(
|
|
set_core_config: SetCoreConfigCallable,
|
|
) -> None:
|
|
set_core_config(PlatformFramework.ESP32_IDF, full_config={DOMAIN: {"id": HUB_ID}})
|
|
config = _switch_config(CONF_UNPAIRED_ACCESS)
|
|
|
|
assert SWITCH_FINAL_VALIDATE_SCHEMA(config) is config
|
|
|
|
|
|
def test_switch_without_pairing_method_warns(
|
|
set_core_config: SetCoreConfigCallable, caplog: pytest.LogCaptureFixture
|
|
) -> None:
|
|
"""Turning the switch off would leave no way for a new server to pair."""
|
|
set_core_config(PlatformFramework.ESP32_IDF, full_config={DOMAIN: {"id": HUB_ID}})
|
|
config = _switch_config(CONF_UNPAIRED_ACCESS)
|
|
|
|
with caplog.at_level(logging.WARNING):
|
|
SWITCH_FINAL_VALIDATE_SCHEMA(config)
|
|
|
|
assert NO_PAIRING_WARNING in caplog.text
|
|
|
|
|
|
def test_switch_with_pairing_method_does_not_warn(
|
|
set_core_config: SetCoreConfigCallable, caplog: pytest.LogCaptureFixture
|
|
) -> None:
|
|
set_core_config(
|
|
PlatformFramework.ESP32_IDF,
|
|
full_config={DOMAIN: {"id": HUB_ID, "static_pairing_code": "01234567"}},
|
|
)
|
|
config = _switch_config(CONF_UNPAIRED_ACCESS)
|
|
|
|
with caplog.at_level(logging.WARNING):
|
|
SWITCH_FINAL_VALIDATE_SCHEMA(config)
|
|
|
|
assert NO_PAIRING_WARNING not in caplog.text
|
|
|
|
|
|
def test_enabled_switch_ignores_hub_key(set_core_config: SetCoreConfigCallable) -> None:
|
|
"""Only the unpaired access switch competes with the hub key."""
|
|
set_core_config(
|
|
PlatformFramework.ESP32_IDF,
|
|
full_config={DOMAIN: {"id": HUB_ID, CONF_UNPAIRED_ACCESS: False}},
|
|
)
|
|
config = _switch_config("enabled")
|
|
|
|
assert SWITCH_FINAL_VALIDATE_SCHEMA(config) is config
|
|
|
|
|
|
@pytest.mark.parametrize("switch_type", ["enabled", CONF_UNPAIRED_ACCESS])
|
|
def test_duplicate_switch_type_rejected(
|
|
set_core_config: SetCoreConfigCallable, switch_type: str
|
|
) -> None:
|
|
"""Two switches of one type would fight over the same hub setting."""
|
|
entry = {"platform": DOMAIN, "type": switch_type}
|
|
set_core_config(
|
|
PlatformFramework.ESP32_IDF,
|
|
full_config={DOMAIN: {"id": HUB_ID}, "switch": [entry, dict(entry)]},
|
|
)
|
|
config = _switch_config(switch_type)
|
|
|
|
with pytest.raises(cv.Invalid, match="Only one sendspin"):
|
|
SWITCH_FINAL_VALIDATE_SCHEMA(config)
|
|
|
|
|
|
@pytest.mark.parametrize("switch_type", ["enabled", CONF_UNPAIRED_ACCESS])
|
|
def test_switch_requests_its_type(
|
|
set_core_config: SetCoreConfigCallable, switch_type: str
|
|
) -> None:
|
|
"""The hub skips the codegen value for a setting a switch drives, so the client
|
|
waits for that switch to restore before its first start."""
|
|
set_core_config(PlatformFramework.ESP32_IDF)
|
|
|
|
_switch_config(switch_type)
|
|
|
|
assert _get_data().switch_types == {switch_type}
|