core/tests/components/lamarzocco/test_number.py
Josef Zweck 42b984ee4f
Migrate lamarzocco to lmcloud 1.1 (#113935)
* migrate to 1.1

* bump to 1.1.1

* fix newlines docstring

* cleanup entity_description fns

* strict generics

* restructure import

* tweaks to generics

* tweaks to generics

* removed exceptions

* move initialization, websocket clean shutdown

* get rid of duplicate entry addign

* bump lmcloud

* re-add calendar, auto on/off switches

* use asdict for diagnostics

* change number generator

* use name as entry title

* also migrate title

* don't migrate title

* remove generics for now

* satisfy mypy

* add s

* adapt

* migrate entry.runtime_data

* remove auto/onoff

* add issue on wrong gw firmware

* silence mypy

* remove breaks in ha version

* parametrize issue test

* Update update.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Update test_config_flow.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* regen snapshots

* mapping steam level

* remove commented code

* fix typo

* coderabbitai availability tweak

* remove microsecond moving

* additonal schedule for coverage

* be more specific on date offset

* keep mappings the same

* config_entry imports sharpened

* remove unneccessary testcase, clenup date moving

* remove superfluous calendar testcase from diag

* guard against future version downgrade

* use new entry for downgrade test

* switch to lmcloud 1.1.11

* revert runtimedata

* revert runtimedata

* version to helper

* conistent Generator

* generator from typing_extensions

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2024-06-10 19:59:39 +02:00

382 lines
11 KiB
Python

"""Tests for the La Marzocco number entities."""
from unittest.mock import MagicMock
from lmcloud.const import (
KEYS_PER_MODEL,
BoilerType,
MachineModel,
PhysicalKey,
PrebrewMode,
)
import pytest
from syrupy import SnapshotAssertion
from homeassistant.components.number import (
ATTR_VALUE,
DOMAIN as NUMBER_DOMAIN,
SERVICE_SET_VALUE,
)
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from . import async_init_integration
from tests.common import MockConfigEntry
async def test_coffee_boiler(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion,
) -> None:
"""Test the La Marzocco coffee temperature Number."""
await async_init_integration(hass, mock_config_entry)
serial_number = mock_lamarzocco.serial_number
state = hass.states.get(f"number.{serial_number}_coffee_target_temperature")
assert state
assert state == snapshot
entry = entity_registry.async_get(state.entity_id)
assert entry
assert entry.device_id
assert entry == snapshot
device = device_registry.async_get(entry.device_id)
assert device
# service call
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: f"number.{serial_number}_coffee_target_temperature",
ATTR_VALUE: 94,
},
blocking=True,
)
assert len(mock_lamarzocco.set_temp.mock_calls) == 1
mock_lamarzocco.set_temp.assert_called_once_with(
boiler=BoilerType.COFFEE, temperature=94
)
@pytest.mark.parametrize("device_fixture", [MachineModel.GS3_AV, MachineModel.GS3_MP])
@pytest.mark.parametrize(
("entity_name", "value", "func_name", "kwargs"),
[
(
"steam_target_temperature",
131,
"set_temp",
{"boiler": BoilerType.STEAM, "temperature": 131},
),
("tea_water_duration", 15, "set_dose_tea_water", {"dose": 15}),
],
)
async def test_gs3_exclusive(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion,
entity_name: str,
value: float,
func_name: str,
kwargs: dict[str, float],
) -> None:
"""Test exclusive entities for GS3 AV/MP."""
await async_init_integration(hass, mock_config_entry)
serial_number = mock_lamarzocco.serial_number
func = getattr(mock_lamarzocco, func_name)
state = hass.states.get(f"number.{serial_number}_{entity_name}")
assert state
assert state == snapshot
entry = entity_registry.async_get(state.entity_id)
assert entry
assert entry.device_id
assert entry == snapshot
device = device_registry.async_get(entry.device_id)
assert device
# service call
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: f"number.{serial_number}_{entity_name}",
ATTR_VALUE: value,
},
blocking=True,
)
assert len(func.mock_calls) == 1
func.assert_called_once_with(**kwargs)
@pytest.mark.parametrize(
"device_fixture", [MachineModel.LINEA_MICRA, MachineModel.LINEA_MINI]
)
async def test_gs3_exclusive_none(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Ensure GS3 exclusive is None for unsupported models."""
await async_init_integration(hass, mock_config_entry)
ENTITIES = ("steam_target_temperature", "tea_water_duration")
serial_number = mock_lamarzocco.serial_number
for entity in ENTITIES:
state = hass.states.get(f"number.{serial_number}_{entity}")
assert state is None
@pytest.mark.parametrize(
"device_fixture", [MachineModel.LINEA_MICRA, MachineModel.LINEA_MINI]
)
@pytest.mark.parametrize(
("entity_name", "function_name", "prebrew_mode", "value", "kwargs"),
[
(
"prebrew_off_time",
"set_prebrew_time",
PrebrewMode.PREBREW,
6,
{"prebrew_off_time": 6.0, "key": PhysicalKey.A},
),
(
"prebrew_on_time",
"set_prebrew_time",
PrebrewMode.PREBREW,
6,
{"prebrew_on_time": 6.0, "key": PhysicalKey.A},
),
(
"preinfusion_time",
"set_preinfusion_time",
PrebrewMode.PREINFUSION,
7,
{"preinfusion_time": 7.0, "key": PhysicalKey.A},
),
],
)
async def test_pre_brew_infusion_numbers(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
entity_name: str,
function_name: str,
prebrew_mode: PrebrewMode,
value: float,
kwargs: dict[str, float],
) -> None:
"""Test the La Marzocco prebrew/-infusion sensors."""
mock_lamarzocco.config.prebrew_mode = prebrew_mode
await async_init_integration(hass, mock_config_entry)
serial_number = mock_lamarzocco.serial_number
state = hass.states.get(f"number.{serial_number}_{entity_name}")
assert state
assert state == snapshot
entry = entity_registry.async_get(state.entity_id)
assert entry
assert entry == snapshot
# service call
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: f"number.{serial_number}_{entity_name}",
ATTR_VALUE: value,
},
blocking=True,
)
function = getattr(mock_lamarzocco, function_name)
function.assert_called_once_with(**kwargs)
@pytest.mark.parametrize(
"device_fixture", [MachineModel.LINEA_MICRA, MachineModel.LINEA_MINI]
)
@pytest.mark.parametrize(
("prebrew_mode", "entity", "unavailable"),
[
(
PrebrewMode.PREBREW,
("prebrew_off_time", "prebrew_on_time"),
("preinfusion_time",),
),
(
PrebrewMode.PREINFUSION,
("preinfusion_time",),
("prebrew_off_time", "prebrew_on_time"),
),
],
)
async def test_pre_brew_infusion_numbers_unavailable(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
prebrew_mode: PrebrewMode,
entity: tuple[str, ...],
unavailable: tuple[str, ...],
) -> None:
"""Test entities are unavailable depending on selected state."""
mock_lamarzocco.config.prebrew_mode = prebrew_mode
await async_init_integration(hass, mock_config_entry)
serial_number = mock_lamarzocco.serial_number
for entity_name in entity:
state = hass.states.get(f"number.{serial_number}_{entity_name}")
assert state
assert state.state != STATE_UNAVAILABLE
for entity_name in unavailable:
state = hass.states.get(f"number.{serial_number}_{entity_name}")
assert state
assert state.state == STATE_UNAVAILABLE
@pytest.mark.parametrize("device_fixture", [MachineModel.GS3_AV])
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
@pytest.mark.parametrize(
("entity_name", "value", "prebrew_mode", "function_name", "kwargs"),
[
(
"prebrew_off_time",
6,
PrebrewMode.PREBREW,
"set_prebrew_time",
{"prebrew_off_time": 6.0},
),
(
"prebrew_on_time",
6,
PrebrewMode.PREBREW,
"set_prebrew_time",
{"prebrew_on_time": 6.0},
),
(
"preinfusion_time",
7,
PrebrewMode.PREINFUSION,
"set_preinfusion_time",
{"preinfusion_time": 7.0},
),
("dose", 6, PrebrewMode.DISABLED, "set_dose", {"dose": 6}),
],
)
async def test_pre_brew_infusion_key_numbers(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
entity_name: str,
value: float,
prebrew_mode: PrebrewMode,
function_name: str,
kwargs: dict[str, float],
) -> None:
"""Test the La Marzocco number sensors for GS3AV model."""
mock_lamarzocco.config.prebrew_mode = prebrew_mode
await async_init_integration(hass, mock_config_entry)
serial_number = mock_lamarzocco.serial_number
func = getattr(mock_lamarzocco, function_name)
state = hass.states.get(f"number.{serial_number}_{entity_name}")
assert state is None
for key in PhysicalKey:
state = hass.states.get(f"number.{serial_number}_{entity_name}_key_{key}")
assert state
assert state == snapshot(name=f"{serial_number}_{entity_name}_key_{key}-state")
# service call
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: f"number.{serial_number}_{entity_name}_key_{key}",
ATTR_VALUE: value,
},
blocking=True,
)
kwargs["key"] = key
assert len(func.mock_calls) == key.value
func.assert_called_with(**kwargs)
@pytest.mark.parametrize("device_fixture", [MachineModel.GS3_AV])
async def test_disabled_entites(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the La Marzocco prebrew/-infusion sensors for GS3AV model."""
await async_init_integration(hass, mock_config_entry)
ENTITIES = (
"prebrew_off_time",
"prebrew_on_time",
"preinfusion_time",
"set_dose",
)
serial_number = mock_lamarzocco.serial_number
for entity_name in ENTITIES:
for key in PhysicalKey:
state = hass.states.get(f"number.{serial_number}_{entity_name}_key_{key}")
assert state is None
@pytest.mark.parametrize(
"device_fixture",
[MachineModel.GS3_MP, MachineModel.LINEA_MICRA, MachineModel.LINEA_MINI],
)
async def test_not_existing_key_entities(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Assert not existing key entities."""
await async_init_integration(hass, mock_config_entry)
serial_number = mock_lamarzocco.serial_number
for entity in (
"prebrew_off_time",
"prebrew_on_time",
"preinfusion_time",
"set_dose",
):
for key in range(1, KEYS_PER_MODEL[MachineModel.GS3_AV] + 1):
state = hass.states.get(f"number.{serial_number}_{entity}_key_{key}")
assert state is None