Add evohome test for setup (#123129)

* allow for different systems

* installation is a load_json_*fixture param

* allow installation to be parameterized

* test setup of various systems

* add more fixtures

* test setup of integration

* tweak test

* tweak const

* add expected state/services

* extend setup test

* tidy up

* tidy up tweaks

* code tweaks

* refactor expected results dicts

* woops

* refatcor serialize

* refactor test

* tweak

* tweak code

* rename symbol

* ensure actual I/O remains blocked

* tweak

* typo

* use constants

* Update conftest.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* change filename

* add config fixture

* config is a fixture

* config is a fixture now 2

* lint

* lint

* refactor

* lint

* lint

* restore email addr

* use const

* use snapshots instead of helper class

* doctweak

* correct snapshot

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
David Bonnes 2024-08-28 21:40:57 +01:00 committed by GitHub
parent 2b20b2a80b
commit ada6b7875c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 1549 additions and 58 deletions

View File

@ -2,8 +2,10 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Any, Final from http import HTTPMethod
from typing import Any
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from aiohttp import ClientSession from aiohttp import ClientSession
@ -16,75 +18,112 @@ from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.util.json import JsonArrayType, JsonObjectType from homeassistant.util.json import JsonArrayType, JsonObjectType
from .const import ACCESS_TOKEN, REFRESH_TOKEN from .const import ACCESS_TOKEN, REFRESH_TOKEN, USERNAME
from tests.common import load_json_array_fixture, load_json_object_fixture from tests.common import load_json_array_fixture, load_json_object_fixture
TEST_CONFIG: Final = {
CONF_USERNAME: "username",
CONF_PASSWORD: "password",
}
def user_account_config_fixture(install: str) -> JsonObjectType:
def user_account_config_fixture() -> JsonObjectType:
"""Load JSON for the config of a user's account.""" """Load JSON for the config of a user's account."""
return load_json_object_fixture("user_account.json", DOMAIN) try:
return load_json_object_fixture(f"{install}/user_account.json", DOMAIN)
except FileNotFoundError:
return load_json_object_fixture("default/user_account.json", DOMAIN)
def user_locations_config_fixture() -> JsonArrayType: def user_locations_config_fixture(install: str) -> JsonArrayType:
"""Load JSON for the config of a user's installation (a list of locations).""" """Load JSON for the config of a user's installation (a list of locations)."""
return load_json_array_fixture("user_locations.json", DOMAIN) return load_json_array_fixture(f"{install}/user_locations.json", DOMAIN)
def location_status_fixture(loc_id: str) -> JsonObjectType: def location_status_fixture(install: str, loc_id: str | None = None) -> JsonObjectType:
"""Load JSON for the status of a specific location.""" """Load JSON for the status of a specific location."""
return load_json_object_fixture(f"status_{loc_id}.json", DOMAIN) if loc_id is None:
_install = load_json_array_fixture(f"{install}/user_locations.json", DOMAIN)
loc_id = _install[0]["locationInfo"]["locationId"] # type: ignore[assignment, call-overload, index]
return load_json_object_fixture(f"{install}/status_{loc_id}.json", DOMAIN)
def dhw_schedule_fixture() -> JsonObjectType: def dhw_schedule_fixture(install: str) -> JsonObjectType:
"""Load JSON for the schedule of a domesticHotWater zone.""" """Load JSON for the schedule of a domesticHotWater zone."""
return load_json_object_fixture("schedule_dhw.json", DOMAIN) try:
return load_json_object_fixture(f"{install}/schedule_dhw.json", DOMAIN)
except FileNotFoundError:
return load_json_object_fixture("default/schedule_dhw.json", DOMAIN)
def zone_schedule_fixture() -> JsonObjectType: def zone_schedule_fixture(install: str) -> JsonObjectType:
"""Load JSON for the schedule of a temperatureZone zone.""" """Load JSON for the schedule of a temperatureZone zone."""
return load_json_object_fixture("schedule_zone.json", DOMAIN) try:
return load_json_object_fixture(f"{install}/schedule_zone.json", DOMAIN)
except FileNotFoundError:
return load_json_object_fixture("default/schedule_zone.json", DOMAIN)
async def mock_get( def mock_get_factory(install: str) -> Callable:
self: Broker, url: str, **kwargs: Any """Return a get method for a specified installation."""
) -> JsonArrayType | JsonObjectType:
"""Return the JSON for a HTTP get of a given URL."""
# a proxy for the behaviour of the real web API async def mock_get(
if self.refresh_token is None: self: Broker, url: str, **kwargs: Any
self.refresh_token = f"new_{REFRESH_TOKEN}" ) -> JsonArrayType | JsonObjectType:
"""Return the JSON for a HTTP get of a given URL."""
if self.access_token_expires is None or self.access_token_expires < datetime.now(): # a proxy for the behaviour of the real web API
self.access_token = f"new_{ACCESS_TOKEN}" if self.refresh_token is None:
self.access_token_expires = datetime.now() + timedelta(minutes=30) self.refresh_token = f"new_{REFRESH_TOKEN}"
# assume a valid GET, and return the JSON for that web API if (
if url == "userAccount": # userAccount self.access_token_expires is None
return user_account_config_fixture() or self.access_token_expires < datetime.now()
):
self.access_token = f"new_{ACCESS_TOKEN}"
self.access_token_expires = datetime.now() + timedelta(minutes=30)
if url.startswith("location"): # assume a valid GET, and return the JSON for that web API
if "installationInfo" in url: # location/installationInfo?userId={id} if url == "userAccount": # userAccount
return user_locations_config_fixture() return user_account_config_fixture(install)
if "location" in url: # location/{id}/status
return location_status_fixture("2738909")
elif "schedule" in url: if url.startswith("location"):
if url.startswith("domesticHotWater"): # domesticHotWater/{id}/schedule if "installationInfo" in url: # location/installationInfo?userId={id}
return dhw_schedule_fixture() return user_locations_config_fixture(install)
if url.startswith("temperatureZone"): # temperatureZone/{id}/schedule if "location" in url: # location/{id}/status
return zone_schedule_fixture() return location_status_fixture(install)
pytest.xfail(f"Unexpected URL: {url}") elif "schedule" in url:
if url.startswith("domesticHotWater"): # domesticHotWater/{id}/schedule
return dhw_schedule_fixture(install)
if url.startswith("temperatureZone"): # temperatureZone/{id}/schedule
return zone_schedule_fixture(install)
pytest.fail(f"Unexpected request: {HTTPMethod.GET} {url}")
return mock_get
@patch("evohomeasync2.broker.Broker.get", mock_get) async def block_request(
async def setup_evohome(hass: HomeAssistant, test_config: dict[str, str]) -> MagicMock: self: Broker, method: HTTPMethod, url: str, **kwargs: Any
) -> None:
"""Fail if the code attempts any actual I/O via aiohttp."""
pytest.fail(f"Unexpected request: {method} {url}")
@pytest.fixture
def evo_config() -> dict[str, str]:
"Return a default/minimal configuration."
return {
CONF_USERNAME: USERNAME,
CONF_PASSWORD: "password",
}
@patch("evohomeasync.broker.Broker._make_request", block_request)
@patch("evohomeasync2.broker.Broker._client", block_request)
async def setup_evohome(
hass: HomeAssistant,
test_config: dict[str, str],
install: str = "default",
) -> MagicMock:
"""Set up the evohome integration and return its client. """Set up the evohome integration and return its client.
The class is mocked here to check the client was instantiated with the correct args. The class is mocked here to check the client was instantiated with the correct args.
@ -93,6 +132,7 @@ async def setup_evohome(hass: HomeAssistant, test_config: dict[str, str]) -> Mag
with ( with (
patch("homeassistant.components.evohome.evo.EvohomeClient") as mock_client, patch("homeassistant.components.evohome.evo.EvohomeClient") as mock_client,
patch("homeassistant.components.evohome.ev1.EvohomeClient", return_value=None), patch("homeassistant.components.evohome.ev1.EvohomeClient", return_value=None),
patch("evohomeasync2.broker.Broker.get", mock_get_factory(install)),
): ):
mock_client.side_effect = EvohomeClient mock_client.side_effect = EvohomeClient

View File

@ -8,3 +8,12 @@ ACCESS_TOKEN: Final = "at_1dc7z657UKzbhKA..."
REFRESH_TOKEN: Final = "rf_jg68ZCKYdxEI3fF..." REFRESH_TOKEN: Final = "rf_jg68ZCKYdxEI3fF..."
SESSION_ID: Final = "F7181186..." SESSION_ID: Final = "F7181186..."
USERNAME: Final = "test_user@gmail.com" USERNAME: Final = "test_user@gmail.com"
# The h-numbers refer to issues in HA's core repo
TEST_INSTALLS: Final = (
"minimal", # evohome (single zone, no DHW)
"default", # evohome (multi-zone, with DHW & ghost zones)
"h032585", # VisionProWifi (no preset_mode for TCS)
"h099625", # RoundThermostat
"system_004", # RoundModulation
)

View File

@ -246,7 +246,7 @@
}, },
{ {
"zoneId": "3450733", "zoneId": "3450733",
"modelType": "xx", "modelType": "xxx",
"setpointCapabilities": { "setpointCapabilities": {
"maxHeatSetpoint": 35.0, "maxHeatSetpoint": 35.0,
"minHeatSetpoint": 5.0, "minHeatSetpoint": 5.0,
@ -268,7 +268,7 @@
"setpointValueResolution": 0.5 "setpointValueResolution": 0.5
}, },
"name": "Spare Room", "name": "Spare Room",
"zoneType": "xx" "zoneType": "xxx"
} }
], ],
"dhw": { "dhw": {

View File

@ -0,0 +1,31 @@
{
"locationId": "111111",
"gateways": [
{
"gatewayId": "222222",
"temperatureControlSystems": [
{
"systemId": "416856",
"zones": [
{
"zoneId": "416856",
"temperatureStatus": {
"temperature": 21.5,
"isAvailable": true
},
"activeFaults": [],
"setpointStatus": {
"targetHeatTemperature": 21.5,
"setpointMode": "FollowSchedule"
},
"name": "THERMOSTAT"
}
],
"activeFaults": [],
"systemModeStatus": { "mode": "Heat", "isPermanent": true }
}
],
"activeFaults": []
}
]
}

View File

@ -0,0 +1,3 @@
{
"416856": 21.5
}

View File

@ -0,0 +1,79 @@
[
{
"locationInfo": {
"locationId": "111111",
"name": "My Home",
"timeZone": {
"timeZoneId": "GMTStandardTime",
"displayName": "(UTC+00:00) Dublin, Edinburgh, Lisbon, London",
"offsetMinutes": 0,
"currentOffsetMinutes": 60,
"supportsDaylightSaving": true
}
},
"gateways": [
{
"gatewayInfo": {
"gatewayId": "222222",
"mac": "00D02DEE0000",
"crc": "1234",
"isWiFi": false
},
"temperatureControlSystems": [
{
"systemId": "416856",
"modelType": "VisionProWifiRetail",
"zones": [
{
"zoneId": "416856",
"modelType": "VisionProWifiRetail",
"setpointCapabilities": {
"vacationHoldCapabilities": {
"isChangeable": true,
"isCancelable": true,
"minDuration": "1.00:00:00",
"maxDuration": "365.23:45:00",
"timingResolution": "00:15:00"
},
"maxHeatSetpoint": 32.0,
"minHeatSetpoint": 4.5,
"valueResolution": 0.5,
"canControlHeat": true,
"canControlCool": false,
"allowedSetpointModes": [
"PermanentOverride",
"FollowSchedule",
"TemporaryOverride",
"VacationHold"
],
"maxDuration": "1.00:00:00",
"timingResolution": "00:15:00"
},
"scheduleCapabilities": {
"maxSwitchpointsPerDay": 4,
"minSwitchpointsPerDay": 0,
"timingResolution": "00:15:00",
"setpointValueResolution": 0.5
},
"name": "THERMOSTAT",
"zoneType": "Thermostat"
}
],
"allowedSystemModes": [
{
"systemMode": "Off",
"canBePermanent": true,
"canBeTemporary": false
},
{
"systemMode": "Heat",
"canBePermanent": true,
"canBeTemporary": false
}
]
}
]
}
]
}
]

View File

@ -0,0 +1,44 @@
{
"locationId": "111111",
"gateways": [
{
"gatewayId": "222222",
"temperatureControlSystems": [
{
"systemId": "8557535",
"zones": [
{
"zoneId": "8557539",
"temperatureStatus": {
"temperature": 21.5,
"isAvailable": true
},
"activeFaults": [],
"setpointStatus": {
"targetHeatTemperature": 21.5,
"setpointMode": "FollowSchedule"
},
"name": "THERMOSTAT"
},
{
"zoneId": "8557541",
"temperatureStatus": {
"temperature": 21.5,
"isAvailable": true
},
"activeFaults": [],
"setpointStatus": {
"targetHeatTemperature": 21.5,
"setpointMode": "FollowSchedule"
},
"name": "THERMOSTAT"
}
],
"activeFaults": [],
"systemModeStatus": { "mode": "Auto", "isPermanent": true }
}
],
"activeFaults": []
}
]
}

View File

@ -0,0 +1,113 @@
[
{
"locationInfo": {
"locationId": "111111",
"name": "My Home",
"timeZone": {
"timeZoneId": "FLEStandardTime",
"displayName": "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius",
"offsetMinutes": 120,
"currentOffsetMinutes": 180,
"supportsDaylightSaving": true
}
},
"gateways": [
{
"gatewayInfo": {
"gatewayId": "222222",
"mac": "00D02DEE0000",
"crc": "1234",
"isWiFi": false
},
"temperatureControlSystems": [
{
"systemId": "8557535",
"modelType": "EvoTouch",
"zones": [
{
"zoneId": "8557539",
"modelType": "RoundWireless",
"setpointCapabilities": {
"maxHeatSetpoint": 35.0,
"minHeatSetpoint": 5.0,
"valueResolution": 0.5,
"canControlHeat": true,
"canControlCool": false,
"allowedSetpointModes": [
"PermanentOverride",
"FollowSchedule",
"TemporaryOverride"
],
"maxDuration": "1.00:00:00",
"timingResolution": "00:10:00"
},
"scheduleCapabilities": {
"maxSwitchpointsPerDay": 6,
"minSwitchpointsPerDay": 0,
"timingResolution": "00:10:00",
"setpointValueResolution": 0.5
},
"name": "Thermostat",
"zoneType": "Thermostat"
},
{
"zoneId": "8557541",
"modelType": "RoundWireless",
"setpointCapabilities": {
"maxHeatSetpoint": 35.0,
"minHeatSetpoint": 5.0,
"valueResolution": 0.5,
"canControlHeat": true,
"canControlCool": false,
"allowedSetpointModes": [
"PermanentOverride",
"FollowSchedule",
"TemporaryOverride"
],
"maxDuration": "1.00:00:00",
"timingResolution": "00:10:00"
},
"scheduleCapabilities": {
"maxSwitchpointsPerDay": 6,
"minSwitchpointsPerDay": 0,
"timingResolution": "00:10:00",
"setpointValueResolution": 0.5
},
"name": "Thermostat 2",
"zoneType": "Thermostat"
}
],
"allowedSystemModes": [
{
"systemMode": "Auto",
"canBePermanent": true,
"canBeTemporary": false
},
{
"systemMode": "AutoWithEco",
"canBePermanent": true,
"canBeTemporary": true,
"maxDuration": "1.00:00:00",
"timingResolution": "01:00:00",
"timingMode": "Duration"
},
{
"systemMode": "Away",
"canBePermanent": true,
"canBeTemporary": true,
"maxDuration": "99.00:00:00",
"timingResolution": "1.00:00:00",
"timingMode": "Period"
},
{
"systemMode": "HeatingOff",
"canBePermanent": true,
"canBeTemporary": false
}
]
}
]
}
]
}
]

View File

@ -0,0 +1,28 @@
{
"locationId": "2738909",
"gateways": [
{
"gatewayId": "2499896",
"temperatureControlSystems": [
{
"systemId": "3432522",
"zones": [
{
"zoneId": "3432576",
"name": "Main Room",
"temperatureStatus": { "temperature": 19.0, "isAvailable": true },
"setpointStatus": {
"targetHeatTemperature": 17.0,
"setpointMode": "FollowSchedule"
},
"activeFaults": []
}
],
"activeFaults": [],
"systemModeStatus": { "mode": "AutoWithEco", "isPermanent": true }
}
],
"activeFaults": []
}
]
}

View File

@ -0,0 +1,120 @@
[
{
"locationInfo": {
"locationId": "2738909",
"name": "My Home",
"streetAddress": "1 Main Street",
"city": "London",
"country": "UnitedKingdom",
"postcode": "E1 1AA",
"locationType": "Residential",
"useDaylightSaveSwitching": true,
"timeZone": {
"timeZoneId": "GMTStandardTime",
"displayName": "(UTC+00:00) Dublin, Edinburgh, Lisbon, London",
"offsetMinutes": 0,
"currentOffsetMinutes": 60,
"supportsDaylightSaving": true
},
"locationOwner": {
"userId": "2263181",
"username": "user_2263181@gmail.com",
"firstname": "John",
"lastname": "Smith"
}
},
"gateways": [
{
"gatewayInfo": {
"gatewayId": "2499896",
"mac": "00D02DEE0000",
"crc": "1234",
"isWiFi": false
},
"temperatureControlSystems": [
{
"systemId": "3432522",
"modelType": "EvoTouch",
"zones": [
{
"zoneId": "3432576",
"modelType": "HeatingZone",
"setpointCapabilities": {
"maxHeatSetpoint": 35.0,
"minHeatSetpoint": 5.0,
"valueResolution": 0.5,
"canControlHeat": true,
"canControlCool": false,
"allowedSetpointModes": [
"PermanentOverride",
"FollowSchedule",
"TemporaryOverride"
],
"maxDuration": "1.00:00:00",
"timingResolution": "00:10:00"
},
"scheduleCapabilities": {
"maxSwitchpointsPerDay": 6,
"minSwitchpointsPerDay": 1,
"timingResolution": "00:10:00",
"setpointValueResolution": 0.5
},
"name": "Main Room",
"zoneType": "RadiatorZone"
}
],
"allowedSystemModes": [
{
"systemMode": "HeatingOff",
"canBePermanent": true,
"canBeTemporary": false
},
{
"systemMode": "Auto",
"canBePermanent": true,
"canBeTemporary": false
},
{
"systemMode": "AutoWithReset",
"canBePermanent": true,
"canBeTemporary": false
},
{
"systemMode": "AutoWithEco",
"canBePermanent": true,
"canBeTemporary": true,
"maxDuration": "1.00:00:00",
"timingResolution": "01:00:00",
"timingMode": "Duration"
},
{
"systemMode": "Away",
"canBePermanent": true,
"canBeTemporary": true,
"maxDuration": "99.00:00:00",
"timingResolution": "1.00:00:00",
"timingMode": "Period"
},
{
"systemMode": "DayOff",
"canBePermanent": true,
"canBeTemporary": true,
"maxDuration": "99.00:00:00",
"timingResolution": "1.00:00:00",
"timingMode": "Period"
},
{
"systemMode": "Custom",
"canBePermanent": true,
"canBeTemporary": true,
"maxDuration": "99.00:00:00",
"timingResolution": "1.00:00:00",
"timingMode": "Period"
}
]
}
]
}
]
}
]

View File

@ -0,0 +1,33 @@
{
"locationId": "3164610",
"gateways": [
{
"gatewayId": "2938388",
"temperatureControlSystems": [
{
"systemId": "4187769",
"zones": [
{
"zoneId": "4187768",
"temperatureStatus": { "temperature": 19.5, "isAvailable": true },
"activeFaults": [],
"setpointStatus": {
"targetHeatTemperature": 15.0,
"setpointMode": "PermanentOverride"
},
"name": "Thermostat"
}
],
"activeFaults": [],
"systemModeStatus": { "mode": "Auto", "isPermanent": true }
}
],
"activeFaults": [
{
"faultType": "GatewayCommunicationLost",
"since": "2023-05-04T18:47:36.7727046"
}
]
}
]
}

View File

@ -0,0 +1,99 @@
[
{
"locationInfo": {
"locationId": "3164610",
"name": "Living room",
"streetAddress": "1 Main Road",
"city": "Boomtown",
"country": "Netherlands",
"postcode": "1234XX",
"locationType": "Residential",
"useDaylightSaveSwitching": true,
"timeZone": {
"timeZoneId": "WEuropeStandardTime",
"displayName": "(UTC+01:00) Amsterdam, Berlijn, Bern, Rome, Stockholm, Wenen",
"offsetMinutes": 60,
"currentOffsetMinutes": 120,
"supportsDaylightSaving": true
},
"locationOwner": {
"userId": "2624305",
"username": "user_2624305@gmail.com",
"firstname": "Chris",
"lastname": "Jones"
}
},
"gateways": [
{
"gatewayInfo": {
"gatewayId": "2938388",
"mac": "00D02D5A7000",
"crc": "1234",
"isWiFi": false
},
"temperatureControlSystems": [
{
"systemId": "4187769",
"modelType": "EvoTouch",
"zones": [
{
"zoneId": "4187768",
"modelType": "RoundModulation",
"setpointCapabilities": {
"maxHeatSetpoint": 35.0,
"minHeatSetpoint": 5.0,
"valueResolution": 0.5,
"canControlHeat": true,
"canControlCool": false,
"allowedSetpointModes": [
"PermanentOverride",
"FollowSchedule",
"TemporaryOverride"
],
"maxDuration": "1.00:00:00",
"timingResolution": "00:10:00"
},
"scheduleCapabilities": {
"maxSwitchpointsPerDay": 6,
"minSwitchpointsPerDay": 0,
"timingResolution": "00:10:00",
"setpointValueResolution": 0.5
},
"name": "Thermostat",
"zoneType": "Thermostat"
}
],
"allowedSystemModes": [
{
"systemMode": "Auto",
"canBePermanent": true,
"canBeTemporary": false
},
{
"systemMode": "AutoWithEco",
"canBePermanent": true,
"canBeTemporary": true,
"maxDuration": "1.00:00:00",
"timingResolution": "01:00:00",
"timingMode": "Duration"
},
{
"systemMode": "Away",
"canBePermanent": true,
"canBeTemporary": true,
"maxDuration": "99.00:00:00",
"timingResolution": "1.00:00:00",
"timingMode": "Period"
},
{
"systemMode": "HeatingOff",
"canBePermanent": true,
"canBeTemporary": false
}
]
}
]
}
]
}
]

View File

@ -0,0 +1,863 @@
# serializer version: 1
# name: test_entities[default]
list([
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 19.7,
'friendly_name': 'My Home',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'icon': 'mdi:thermostat',
'max_temp': 35,
'min_temp': 7,
'preset_mode': 'eco',
'preset_modes': list([
'Reset',
'eco',
'away',
'home',
'Custom',
]),
'status': dict({
'active_system_faults': list([
]),
'system_id': '3432522',
'system_mode_status': dict({
'is_permanent': True,
'mode': 'AutoWithEco',
}),
}),
'supported_features': <ClimateEntityFeature: 400>,
}),
'context': <ANY>,
'entity_id': 'climate.my_home',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': None,
'friendly_name': 'Dead Zone',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 17.0,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': False,
}),
'zone_id': '3432521',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 17.0,
}),
'context': <ANY>,
'entity_id': 'climate.dead_zone',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 19.0,
'friendly_name': 'Main Room',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'permanent',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
dict({
'faultType': 'TempZoneActuatorCommunicationLost',
'since': '2022-03-02T15:56:01',
}),
]),
'setpoint_status': dict({
'setpoint_mode': 'PermanentOverride',
'target_heat_temperature': 17.0,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 19.0,
}),
'zone_id': '3432576',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 17.0,
}),
'context': <ANY>,
'entity_id': 'climate.main_room',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 19.0,
'friendly_name': 'Front Room',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'temporary',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
dict({
'faultType': 'TempZoneActuatorLowBattery',
'since': '2022-03-02T04:50:20',
}),
]),
'setpoint_status': dict({
'setpoint_mode': 'TemporaryOverride',
'target_heat_temperature': 21.0,
'until': '2022-03-07T11:00:00-08:00',
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 19.0,
}),
'zone_id': '3432577',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 21.0,
}),
'context': <ANY>,
'entity_id': 'climate.front_room',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.0,
'friendly_name': 'Kitchen',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 17.0,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 20.0,
}),
'zone_id': '3432578',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 17.0,
}),
'context': <ANY>,
'entity_id': 'climate.kitchen',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 20.0,
'friendly_name': 'Bathroom Dn',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 16.0,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 20.0,
}),
'zone_id': '3432579',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 16.0,
}),
'context': <ANY>,
'entity_id': 'climate.bathroom_dn',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 21.0,
'friendly_name': 'Main Bedroom',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 16.0,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 21.0,
}),
'zone_id': '3432580',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 16.0,
}),
'context': <ANY>,
'entity_id': 'climate.main_bedroom',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 19.5,
'friendly_name': 'Kids Room',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 17.0,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 19.5,
}),
'zone_id': '3449703',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 17.0,
}),
'context': <ANY>,
'entity_id': 'climate.kids_room',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'away_mode': 'on',
'current_temperature': 23,
'friendly_name': 'Domestic Hot Water',
'icon': 'mdi:thermometer-lines',
'max_temp': 60,
'min_temp': 43,
'operation_list': list([
'auto',
'on',
'off',
]),
'operation_mode': 'off',
'status': dict({
'active_faults': list([
]),
'dhw_id': '3933910',
'setpoints': dict({
'next_sp_from': '2024-08-14T22:30:00-07:00',
'next_sp_state': 'On',
'this_sp_from': '2024-08-14T14:30:00-07:00',
'this_sp_state': 'Off',
}),
'state_status': dict({
'mode': 'PermanentOverride',
'state': 'Off',
}),
'temperature_status': dict({
'is_available': True,
'temperature': 23.0,
}),
}),
'supported_features': <WaterHeaterEntityFeature: 6>,
'target_temp_high': None,
'target_temp_low': None,
'temperature': None,
}),
'context': <ANY>,
'entity_id': 'water_heater.domestic_hot_water',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
}),
])
# ---
# name: test_entities[h032585]
list([
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 21.5,
'friendly_name': 'My Home',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'icon': 'mdi:thermostat',
'max_temp': 35,
'min_temp': 7,
'status': dict({
'active_system_faults': list([
]),
'system_id': '416856',
'system_mode_status': dict({
'is_permanent': True,
'mode': 'Heat',
}),
}),
'supported_features': <ClimateEntityFeature: 384>,
}),
'context': <ANY>,
'entity_id': 'climate.my_home',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 21.5,
'friendly_name': 'THERMOSTAT',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 32.0,
'min_temp': 4.5,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 21.5,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 21.5,
}),
'zone_id': '416856',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 21.5,
}),
'context': <ANY>,
'entity_id': 'climate.thermostat',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
])
# ---
# name: test_entities[h099625]
list([
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 21.5,
'friendly_name': 'My Home',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'icon': 'mdi:thermostat',
'max_temp': 35,
'min_temp': 7,
'preset_mode': None,
'preset_modes': list([
'eco',
'away',
]),
'status': dict({
'active_system_faults': list([
]),
'system_id': '8557535',
'system_mode_status': dict({
'is_permanent': True,
'mode': 'Auto',
}),
}),
'supported_features': <ClimateEntityFeature: 400>,
}),
'context': <ANY>,
'entity_id': 'climate.my_home',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 21.5,
'friendly_name': 'THERMOSTAT',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 21.5,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T21:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T13:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 21.5,
}),
'zone_id': '8557539',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 21.5,
}),
'context': <ANY>,
'entity_id': 'climate.thermostat',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 21.5,
'friendly_name': 'THERMOSTAT',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 21.5,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T21:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T13:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 21.5,
}),
'zone_id': '8557541',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 21.5,
}),
'context': <ANY>,
'entity_id': 'climate.thermostat_2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
])
# ---
# name: test_entities[h118169]
list([
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 21.5,
'friendly_name': 'My Home',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'icon': 'mdi:thermostat',
'max_temp': 35,
'min_temp': 7,
'status': dict({
'active_system_faults': list([
]),
'system_id': '333333',
'system_mode_status': dict({
'is_permanent': True,
'mode': 'Heat',
}),
}),
'supported_features': <ClimateEntityFeature: 384>,
}),
'context': <ANY>,
'entity_id': 'climate.my_home',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 21.5,
'friendly_name': 'THERMOSTAT',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 32.0,
'min_temp': 4.5,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 21.5,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 21.5,
}),
'zone_id': '444444',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 21.5,
}),
'context': <ANY>,
'entity_id': 'climate.thermostat',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
])
# ---
# name: test_entities[minimal]
list([
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 19.0,
'friendly_name': 'My Home',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'icon': 'mdi:thermostat',
'max_temp': 35,
'min_temp': 7,
'preset_mode': 'eco',
'preset_modes': list([
'Reset',
'eco',
'away',
'home',
'Custom',
]),
'status': dict({
'active_system_faults': list([
]),
'system_id': '3432522',
'system_mode_status': dict({
'is_permanent': True,
'mode': 'AutoWithEco',
}),
}),
'supported_features': <ClimateEntityFeature: 400>,
}),
'context': <ANY>,
'entity_id': 'climate.my_home',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 19.0,
'friendly_name': 'Main Room',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'none',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'FollowSchedule',
'target_heat_temperature': 17.0,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T23:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T15:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 19.0,
}),
'zone_id': '3432576',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 17.0,
}),
'context': <ANY>,
'entity_id': 'climate.main_room',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
])
# ---
# name: test_entities[system_004]
list([
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 19.5,
'friendly_name': 'Living room',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'icon': 'mdi:thermostat',
'max_temp': 35,
'min_temp': 7,
'preset_mode': None,
'preset_modes': list([
'eco',
'away',
]),
'status': dict({
'active_system_faults': list([
]),
'system_id': '4187769',
'system_mode_status': dict({
'is_permanent': True,
'mode': 'Auto',
}),
}),
'supported_features': <ClimateEntityFeature: 400>,
}),
'context': <ANY>,
'entity_id': 'climate.living_room',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 19.5,
'friendly_name': 'Thermostat',
'hvac_modes': list([
<HVACMode.OFF: 'off'>,
<HVACMode.HEAT: 'heat'>,
]),
'max_temp': 35.0,
'min_temp': 5.0,
'preset_mode': 'permanent',
'preset_modes': list([
'none',
'temporary',
'permanent',
]),
'status': dict({
'active_faults': list([
]),
'setpoint_status': dict({
'setpoint_mode': 'PermanentOverride',
'target_heat_temperature': 15.0,
}),
'setpoints': dict({
'next_sp_from': '2024-08-14T22:00:00-07:00',
'next_sp_temp': 18.1,
'this_sp_from': '2024-08-14T14:00:00-07:00',
'this_sp_temp': 15.9,
}),
'temperature_status': dict({
'is_available': True,
'temperature': 19.5,
}),
'zone_id': '4187768',
}),
'supported_features': <ClimateEntityFeature: 401>,
'temperature': 15.0,
}),
'context': <ANY>,
'entity_id': 'climate.thermostat',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
}),
])
# ---

View File

@ -0,0 +1,25 @@
"""The tests for evohome."""
from __future__ import annotations
import pytest
from syrupy import SnapshotAssertion
from homeassistant.core import HomeAssistant
from .conftest import setup_evohome
from .const import TEST_INSTALLS
@pytest.mark.parametrize("install", TEST_INSTALLS)
async def test_entities(
hass: HomeAssistant,
evo_config: dict[str, str],
install: str,
snapshot: SnapshotAssertion,
) -> None:
"""Test entities and state after setup of a Honeywell TCC-compatible system."""
await setup_evohome(hass, evo_config, install=install)
assert hass.states.async_all() == snapshot

View File

@ -8,7 +8,6 @@ from typing import Any, Final, NotRequired, TypedDict
import pytest import pytest
from homeassistant.components.evohome import ( from homeassistant.components.evohome import (
CONF_PASSWORD,
CONF_USERNAME, CONF_USERNAME,
DOMAIN, DOMAIN,
STORAGE_KEY, STORAGE_KEY,
@ -56,11 +55,6 @@ ACCESS_TOKEN_EXP_DTM, ACCESS_TOKEN_EXP_STR = dt_pair(dt_util.now() + timedelta(h
USERNAME_DIFF: Final = f"not_{USERNAME}" USERNAME_DIFF: Final = f"not_{USERNAME}"
USERNAME_SAME: Final = USERNAME USERNAME_SAME: Final = USERNAME
TEST_CONFIG: Final = {
CONF_USERNAME: USERNAME_SAME,
CONF_PASSWORD: "password",
}
TEST_DATA: Final[dict[str, _TokenStoreT]] = { TEST_DATA: Final[dict[str, _TokenStoreT]] = {
"sans_session_id": { "sans_session_id": {
SZ_USERNAME: USERNAME_SAME, SZ_USERNAME: USERNAME_SAME,
@ -93,13 +87,14 @@ DOMAIN_STORAGE_BASE: Final = {
async def test_auth_tokens_null( async def test_auth_tokens_null(
hass: HomeAssistant, hass: HomeAssistant,
hass_storage: dict[str, Any], hass_storage: dict[str, Any],
evo_config: dict[str, str],
idx: str, idx: str,
) -> None: ) -> None:
"""Test loading/saving authentication tokens when no cached tokens in the store.""" """Test loading/saving authentication tokens when no cached tokens in the store."""
hass_storage[DOMAIN] = DOMAIN_STORAGE_BASE | {"data": TEST_DATA_NULL[idx]} hass_storage[DOMAIN] = DOMAIN_STORAGE_BASE | {"data": TEST_DATA_NULL[idx]}
mock_client = await setup_evohome(hass, TEST_CONFIG) mock_client = await setup_evohome(hass, evo_config, install="minimal")
# Confirm client was instantiated without tokens, as cache was empty... # Confirm client was instantiated without tokens, as cache was empty...
assert SZ_REFRESH_TOKEN not in mock_client.call_args.kwargs assert SZ_REFRESH_TOKEN not in mock_client.call_args.kwargs
@ -120,13 +115,16 @@ async def test_auth_tokens_null(
@pytest.mark.parametrize("idx", TEST_DATA) @pytest.mark.parametrize("idx", TEST_DATA)
async def test_auth_tokens_same( async def test_auth_tokens_same(
hass: HomeAssistant, hass_storage: dict[str, Any], idx: str hass: HomeAssistant,
hass_storage: dict[str, Any],
evo_config: dict[str, str],
idx: str,
) -> None: ) -> None:
"""Test loading/saving authentication tokens when matching username.""" """Test loading/saving authentication tokens when matching username."""
hass_storage[DOMAIN] = DOMAIN_STORAGE_BASE | {"data": TEST_DATA[idx]} hass_storage[DOMAIN] = DOMAIN_STORAGE_BASE | {"data": TEST_DATA[idx]}
mock_client = await setup_evohome(hass, TEST_CONFIG) mock_client = await setup_evohome(hass, evo_config, install="minimal")
# Confirm client was instantiated with the cached tokens... # Confirm client was instantiated with the cached tokens...
assert mock_client.call_args.kwargs[SZ_REFRESH_TOKEN] == REFRESH_TOKEN assert mock_client.call_args.kwargs[SZ_REFRESH_TOKEN] == REFRESH_TOKEN
@ -146,7 +144,10 @@ async def test_auth_tokens_same(
@pytest.mark.parametrize("idx", TEST_DATA) @pytest.mark.parametrize("idx", TEST_DATA)
async def test_auth_tokens_past( async def test_auth_tokens_past(
hass: HomeAssistant, hass_storage: dict[str, Any], idx: str hass: HomeAssistant,
hass_storage: dict[str, Any],
evo_config: dict[str, str],
idx: str,
) -> None: ) -> None:
"""Test loading/saving authentication tokens with matching username, but expired.""" """Test loading/saving authentication tokens with matching username, but expired."""
@ -158,7 +159,7 @@ async def test_auth_tokens_past(
hass_storage[DOMAIN] = DOMAIN_STORAGE_BASE | {"data": test_data} hass_storage[DOMAIN] = DOMAIN_STORAGE_BASE | {"data": test_data}
mock_client = await setup_evohome(hass, TEST_CONFIG) mock_client = await setup_evohome(hass, evo_config, install="minimal")
# Confirm client was instantiated with the cached tokens... # Confirm client was instantiated with the cached tokens...
assert mock_client.call_args.kwargs[SZ_REFRESH_TOKEN] == REFRESH_TOKEN assert mock_client.call_args.kwargs[SZ_REFRESH_TOKEN] == REFRESH_TOKEN
@ -181,14 +182,17 @@ async def test_auth_tokens_past(
@pytest.mark.parametrize("idx", TEST_DATA) @pytest.mark.parametrize("idx", TEST_DATA)
async def test_auth_tokens_diff( async def test_auth_tokens_diff(
hass: HomeAssistant, hass_storage: dict[str, Any], idx: str hass: HomeAssistant,
hass_storage: dict[str, Any],
evo_config: dict[str, str],
idx: str,
) -> None: ) -> None:
"""Test loading/saving authentication tokens when unmatched username.""" """Test loading/saving authentication tokens when unmatched username."""
hass_storage[DOMAIN] = DOMAIN_STORAGE_BASE | {"data": TEST_DATA[idx]} hass_storage[DOMAIN] = DOMAIN_STORAGE_BASE | {"data": TEST_DATA[idx]}
mock_client = await setup_evohome( mock_client = await setup_evohome(
hass, TEST_CONFIG | {CONF_USERNAME: USERNAME_DIFF} hass, evo_config | {CONF_USERNAME: USERNAME_DIFF}, install="minimal"
) )
# Confirm client was instantiated without tokens, as username was different... # Confirm client was instantiated without tokens, as username was different...