mirror of
https://github.com/esphome/esphome.git
synced 2026-10-08 20:06:03 +00:00
111 lines
3.9 KiB
Python
111 lines
3.9 KiB
Python
"""Unit tests for esphome/pins.py."""
|
|
|
|
import pytest
|
|
|
|
from esphome import config_validation as cv, pins
|
|
import esphome.codegen as cg
|
|
from esphome.const import CONF_ADDRESS
|
|
from esphome.core import ID
|
|
from esphome.schema_extractors import SCHEMA_EXTRACT
|
|
|
|
SomeHub = cg.esphome_ns.class_("SomeHub")
|
|
|
|
|
|
def test_use_id_or_address_with_explicit_id() -> None:
|
|
"""An explicit id string still resolves exactly like cv.use_id."""
|
|
validator = pins.use_id_or_address(SomeHub)
|
|
result = validator("my_hub")
|
|
|
|
assert isinstance(result, ID)
|
|
assert result.id == "my_hub"
|
|
assert result.type is SomeHub
|
|
assert result.is_declaration is False
|
|
assert result.match_config is None
|
|
|
|
|
|
def test_use_id_or_address_with_omitted_id() -> None:
|
|
"""Omitting the id (None) still falls back to the single-instance auto-pick."""
|
|
validator = pins.use_id_or_address(SomeHub)
|
|
result = validator(None)
|
|
|
|
assert isinstance(result, ID)
|
|
assert result.id is None
|
|
assert result.type is SomeHub
|
|
assert result.match_config is None
|
|
|
|
|
|
def test_use_id_or_address_with_address_mapping() -> None:
|
|
"""A {address: ...} mapping produces an unnamed ID with match_config set."""
|
|
validator = pins.use_id_or_address(SomeHub)
|
|
result = validator({CONF_ADDRESS: 0x21})
|
|
|
|
assert isinstance(result, ID)
|
|
assert result.id is None
|
|
assert result.type is SomeHub
|
|
assert result.is_declaration is False
|
|
assert result.match_config == {CONF_ADDRESS: 0x21}
|
|
|
|
|
|
def test_use_id_or_address_with_string_address() -> None:
|
|
"""A hex string address is normalized the same way cv.i2c_address does."""
|
|
validator = pins.use_id_or_address(SomeHub)
|
|
result = validator({CONF_ADDRESS: "0x21"})
|
|
|
|
assert result.match_config == {CONF_ADDRESS: 0x21}
|
|
|
|
|
|
def test_use_id_or_address_mapping_requires_address_key() -> None:
|
|
"""A mapping without the address key is rejected, not silently ignored."""
|
|
validator = pins.use_id_or_address(SomeHub)
|
|
|
|
with pytest.raises(cv.Invalid):
|
|
validator({})
|
|
|
|
|
|
def test_use_id_or_address_mapping_rejects_invalid_address() -> None:
|
|
"""An out-of-range address is still validated by cv.i2c_address."""
|
|
validator = pins.use_id_or_address(SomeHub)
|
|
|
|
with pytest.raises(cv.Invalid):
|
|
validator({CONF_ADDRESS: 0x1FF})
|
|
|
|
|
|
def test_use_id_or_address_custom_address_key() -> None:
|
|
"""A custom address_key is honored both in the mapping and match_config."""
|
|
validator = pins.use_id_or_address(SomeHub, address_key="i2c_address")
|
|
result = validator({"i2c_address": 0x10})
|
|
|
|
assert result.match_config == {"i2c_address": 0x10}
|
|
|
|
|
|
def test_use_id_or_address_marks_address_match_as_manual() -> None:
|
|
"""The resolved id must survive strip_default_ids(), unlike a plain
|
|
omitted-id auto-pick, since the user explicitly gave selection criteria."""
|
|
validator = pins.use_id_or_address(SomeHub)
|
|
result = validator({CONF_ADDRESS: 0x21})
|
|
|
|
assert result.is_manual is True
|
|
|
|
|
|
def test_use_id_or_address_schema_extract_passthrough() -> None:
|
|
"""Called with the SCHEMA_EXTRACT sentinel (as build_language_schema.py
|
|
does), the wrapper must fall through to cv.use_id's own handling and
|
|
return the hub type, not try to treat it as an address mapping."""
|
|
validator = pins.use_id_or_address(SomeHub)
|
|
|
|
assert validator(SCHEMA_EXTRACT) is SomeHub
|
|
|
|
|
|
def test_use_id_or_address_registers_as_use_id_schema(monkeypatch) -> None:
|
|
"""The wrapper must be discoverable by build_language_schema.py as a
|
|
`use_id` schema (like a bare cv.use_id), or the generated language schema
|
|
silently drops hub-id completion for every pin schema using it."""
|
|
from esphome import schema_extractors
|
|
|
|
monkeypatch.setattr(schema_extractors, "EnableSchemaExtraction", True)
|
|
monkeypatch.setattr(schema_extractors, "hidden_schemas", {})
|
|
|
|
validator = pins.use_id_or_address(SomeHub)
|
|
|
|
assert schema_extractors.hidden_schemas.get(repr(validator)) == "use_id"
|