Adds [tool.ruff] and [tool.ty] config to pyproject.toml with a curated ruff rule set (E, F, W, I, UP, B, C4, SIM, RUF, ASYNC, LOG, G, PIE, RET, PERF, N), pins ruff/ty in requirements-dev.txt, reformats the whole tree with `ruff format`, and fixes the pre-existing lint and type-check debt those tools surfaced so both run clean. Production-code type fixes include: HA's ConfigFlowResult vs. the generic FlowResult in config_flow.py, narrowing BoundEntity.desc to its platform-specific subclass (SelectDesc/NumberDesc/SensorDesc/etc.) via cast() instead of an unchecked annotation, converting HA device_class strings to their proper enum types, a resolve_registry callback typed as `object` instead of `DeviceRegistry | None`, and a couple of other narrow correctness fixes (CA key type validation, an index-out-of-bounds false positive from an empty-tuple fallback, a bool/dict argument swap). Test-file fixes are mechanical: narrowing SamsungEntityDescription to the correct subclass via isinstance()/cast() before accessing subclass-only fields, and asserting Optional write_fn/unit_fn fields are set before calling them.
76 lines
3.0 KiB
Python
76 lines
3.0 KiB
Python
"""Tests for the sensor platform."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers import entity_registry as er
|
|
|
|
from custom_components.localthings.const import DOMAIN
|
|
from custom_components.localthings.observe import MODE_POLL
|
|
|
|
|
|
async def test_sensors_registered(
|
|
hass: HomeAssistant, mock_entry, mock_coordinator_session
|
|
) -> None:
|
|
"""Sensors are registered for all SensorDesc entities in the fridge fixture."""
|
|
await hass.config_entries.async_setup(mock_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
ent_reg = er.async_get(hass)
|
|
entries = er.async_entries_for_config_entry(ent_reg, mock_entry.entry_id)
|
|
sensor_entries = [e for e in entries if e.domain == "sensor"]
|
|
assert sensor_entries, "Expected at least one sensor entity"
|
|
|
|
|
|
async def test_sensor_state_from_coordinator(
|
|
hass: HomeAssistant, mock_entry, mock_coordinator_session
|
|
) -> None:
|
|
"""A temperature sensor reads its value from coordinator.data.
|
|
|
|
Entity IDs are auto-generated by HA and don't embed capability path
|
|
segments, so we filter by the mdi:thermometer icon that the fridge
|
|
capability assigns to current-temperature sensors.
|
|
"""
|
|
await hass.config_entries.async_setup(mock_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
states = hass.states.async_all("sensor")
|
|
temp_states = [s for s in states if s.attributes.get("icon") == "mdi:thermometer"]
|
|
assert temp_states, f"No thermometer sensor found. Sensors: {[s.entity_id for s in states]}"
|
|
state = temp_states[0]
|
|
assert state.state not in ("unknown", "unavailable"), f"Sensor state is {state.state}"
|
|
|
|
|
|
async def test_connection_mode_sensor_registered_disabled_by_default(
|
|
hass: HomeAssistant, mock_entry, mock_coordinator_session
|
|
) -> None:
|
|
"""The connection-mode diagnostic sensor is registered but disabled by
|
|
default — it's for troubleshooting, not everyday use."""
|
|
await hass.config_entries.async_setup(mock_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
ent_reg = er.async_get(hass)
|
|
entries = er.async_entries_for_config_entry(ent_reg, mock_entry.entry_id)
|
|
mode_entries = [e for e in entries if e.unique_id.endswith("_connection_mode")]
|
|
assert len(mode_entries) == 1
|
|
entry = mode_entries[0]
|
|
assert entry.disabled_by is not None
|
|
assert entry.entity_category == "diagnostic"
|
|
|
|
|
|
async def test_connection_mode_sensor_reflects_coordinator_mode(
|
|
hass: HomeAssistant, mock_entry, mock_coordinator_session
|
|
) -> None:
|
|
"""native_value reads coordinator.observe_mode directly, live."""
|
|
from custom_components.localthings.sensor import LocalThingsConnectionModeSensor
|
|
|
|
await hass.config_entries.async_setup(mock_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
coordinator = hass.data[DOMAIN][mock_entry.entry_id]
|
|
sensor = LocalThingsConnectionModeSensor(coordinator)
|
|
assert sensor.native_value == MODE_POLL
|
|
|
|
coordinator._observe._set_mode("observe")
|
|
assert sensor.native_value == "observe"
|