* ConfigFlow (translation to change)

* +1

* With implemn in thermostat_switch (not finished)

* GUI fixe

* +1

* Select Working

* Test input in config_flow ok

* documentation

* Add github copilot
Add first test ok for UnderlyingSwitch

* All tests ok

* Fix warnings

* Fix All tests ok

* Translations

* safety

* Add quick-start documentation

---------

Co-authored-by: Jean-Marc Collin <jean-marc.collin-extern@renault.com>
This commit is contained in:
Jean-Marc Collin
2025-02-04 14:35:41 +01:00
committed by GitHub
parent ebc2d8b6ac
commit a0cdaa8a7f
27 changed files with 772 additions and 188 deletions

View File

@@ -624,6 +624,7 @@ async def test_security_over_climate(
assert entity._saved_preset_mode == "none"
@pytest.mark.parametrize("expected_lingering_timers", [True])
async def test_migration_security_safety(
hass: HomeAssistant,
skip_hass_states_is_state,

View File

@@ -0,0 +1,168 @@
""" Test of virtual switch """
# pylint: disable=wildcard-import, unused-wildcard-import, protected-access, line-too-long
from unittest.mock import patch, MagicMock, PropertyMock
import pytest
from homeassistant.const import STATE_ON, STATE_OFF
from custom_components.versatile_thermostat.underlyings import UnderlyingSwitch
from custom_components.versatile_thermostat.thermostat_switch import ThermostatOverSwitch
from .commons import *
@pytest.mark.parametrize(
"is_inversed, vswitch_on_command, vswitch_off_command, expected_command_on, expected_data_on, expected_state_on, expected_command_off, expected_data_off, expected_state_off, is_ok",
[
# Select (with stripping - trim)
(
False,
" select_option/option:comfort ",
" select_option/option:frost ",
"select_option",
{"entity_id": "switch.test", "option": "comfort"},
PRESET_COMFORT,
"select_option",
{"entity_id": "switch.test", "option": "frost"},
PRESET_FROST_PROTECTION,
True,
),
# Inversed Select
(
True,
"select_option/option:comfort",
"select_option/option:eco",
"select_option",
{"entity_id": "switch.test", "option": "eco"},
PRESET_ECO,
"select_option",
{"entity_id": "switch.test", "option": "comfort"},
PRESET_COMFORT,
True,
),
# switch
(False, "turn_on", "turn_off", "turn_on", {"entity_id": "switch.test"}, STATE_ON, "turn_off", {"entity_id": "switch.test"}, STATE_OFF, True),
# inversed switch
(True, "turn_on", "turn_off", "turn_off", {"entity_id": "switch.test"}, STATE_OFF, "turn_on", {"entity_id": "switch.test"}, STATE_ON, True),
# Climate
(
False,
"set_hvac_mode/hvac_mode:heat",
"set_hvac_mode/hvac_mode:off",
"set_hvac_mode",
{"entity_id": "switch.test", "hvac_mode": "heat"},
HVACMode.HEAT,
"set_hvac_mode",
{"entity_id": "switch.test", "hvac_mode": "off"},
HVACMode.OFF,
True,
),
# Inversed Climate
(
True,
"set_hvac_mode/hvac_mode:heat",
"set_hvac_mode/hvac_mode:off",
"set_hvac_mode",
{"entity_id": "switch.test", "hvac_mode": "off"},
HVACMode.OFF,
"set_hvac_mode",
{"entity_id": "switch.test", "hvac_mode": "heat"},
HVACMode.HEAT,
True,
),
# Error cases invalid command
(
False,
"select_ option/option:comfort", # whitespace
"select_option/option:frost",
"select_option",
{"entity_id": "switch.test", "option": "comfort"},
PRESET_COMFORT,
"select_option",
{"entity_id": "switch.test", "option": "frost"},
PRESET_FROST_PROTECTION,
False,
),
(
False,
"select_option/option comfort", # whitespace
"select_option/option:frost",
"select_option",
{"entity_id": "switch.test", "option": "comfort"},
PRESET_COMFORT,
"select_option",
{"entity_id": "switch.test", "option": "frost"},
PRESET_FROST_PROTECTION,
False,
),
(
False,
"select_option/option:com fort", # whitespace
"select_option/option:frost",
"select_option",
{"entity_id": "switch.test", "option": "comfort"},
PRESET_COMFORT,
"select_option",
{"entity_id": "switch.test", "option": "frost"},
PRESET_FROST_PROTECTION,
False,
),
],
)
async def test_build_command(
hass,
is_inversed,
vswitch_on_command,
vswitch_off_command,
expected_command_on,
expected_data_on,
expected_state_on,
expected_command_off,
expected_data_off,
expected_state_off,
is_ok,
):
"""Test the initialisation of a UnderlyingSwitch with some personnalisations commands"""
vtherm = MagicMock(spec=ThermostatOverSwitch)
type(vtherm).is_inversed = PropertyMock(return_value=is_inversed)
assert vtherm.is_inversed == is_inversed
try:
under = UnderlyingSwitch(hass, vtherm, "switch.test", 0, 0, vswitch_on_command, vswitch_off_command)
except ValueError as e:
if is_ok:
pytest.fail(f"Initialization failed with ValueError: {e}")
else:
return
if not is_ok:
pytest.fail("There should be a ValueError")
return
assert under.is_inversed == is_inversed
assert under._on_command.get("command") == expected_command_on
assert under._on_command.get("data") == expected_data_on
assert under._on_command.get("state") == expected_state_on
assert under._off_command.get("command") == expected_command_off
assert under._off_command.get("data") == expected_data_off
assert under._off_command.get("state") == expected_state_off
# Calling turn-on
# fmt: off
with patch.object(under, "check_overpowering", return_value=True), \
patch("homeassistant.core.ServiceRegistry.async_call") as mock_service_call:
#fmt: on
await under.turn_on()
mock_service_call.assert_called_once_with("switch", expected_command_on, expected_data_on)
# Calling turn-off
#fmt: off
with patch("homeassistant.core.ServiceRegistry.async_call") as mock_service_call:
#fmt: on
await under.turn_off()
mock_service_call.assert_called_once_with("switch", expected_command_off, expected_data_off)