Cleanup tplink test framework (#135205)

This commit is contained in:
Steven B. 2025-01-13 18:32:22 +00:00 committed by GitHub
parent d986fe7a07
commit ab28115d2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 693 additions and 464 deletions

View File

@ -6,174 +6,36 @@ from datetime import datetime
from typing import Any from typing import Any
from unittest.mock import AsyncMock, MagicMock, patch from unittest.mock import AsyncMock, MagicMock, patch
from kasa import ( from kasa import BaseProtocol, Device, DeviceType, Feature, KasaException, Module
BaseProtocol,
Device,
DeviceConfig,
DeviceConnectionParameters,
DeviceEncryptionType,
DeviceFamily,
DeviceType,
Feature,
KasaException,
Module,
)
from kasa.interfaces import Fan, Light, LightEffect, LightState from kasa.interfaces import Fan, Light, LightEffect, LightState
from kasa.smart.modules.alarm import Alarm from kasa.smart.modules.alarm import Alarm
from kasa.smartcam.modules.camera import LOCAL_STREAMING_PORT, Camera from kasa.smartcam.modules.camera import LOCAL_STREAMING_PORT, Camera
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.automation import DOMAIN as AUTOMATION_DOMAIN from homeassistant.components.automation import DOMAIN as AUTOMATION_DOMAIN
from homeassistant.components.tplink import (
CONF_AES_KEYS,
CONF_ALIAS,
CONF_CAMERA_CREDENTIALS,
CONF_CONNECTION_PARAMETERS,
CONF_CREDENTIALS_HASH,
CONF_HOST,
CONF_LIVE_VIEW,
CONF_MODEL,
CONF_USES_HTTP,
Credentials,
)
from homeassistant.components.tplink.const import DOMAIN from homeassistant.components.tplink.const import DOMAIN
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform from homeassistant.const import CONF_HOST, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.translation import async_get_translations from homeassistant.helpers.translation import async_get_translations
from homeassistant.helpers.typing import UNDEFINED from homeassistant.helpers.typing import UNDEFINED
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from .const import (
ALIAS,
CREDENTIALS_HASH_LEGACY,
DEVICE_CONFIG_LEGACY,
DEVICE_ID,
IP_ADDRESS,
MAC_ADDRESS,
MODEL,
)
from tests.common import MockConfigEntry, load_json_value_fixture from tests.common import MockConfigEntry, load_json_value_fixture
ColorTempRange = namedtuple("ColorTempRange", ["min", "max"]) # noqa: PYI024 ColorTempRange = namedtuple("ColorTempRange", ["min", "max"]) # noqa: PYI024
MODULE = "homeassistant.components.tplink"
MODULE_CONFIG_FLOW = "homeassistant.components.tplink.config_flow"
IP_ADDRESS = "127.0.0.1"
IP_ADDRESS2 = "127.0.0.2"
IP_ADDRESS3 = "127.0.0.3"
ALIAS = "My Bulb"
ALIAS_CAMERA = "My Camera"
MODEL = "HS100"
MODEL_CAMERA = "C210"
MAC_ADDRESS = "aa:bb:cc:dd:ee:ff"
DEVICE_ID = "123456789ABCDEFGH"
DEVICE_ID_MAC = "AA:BB:CC:DD:EE:FF"
DHCP_FORMATTED_MAC_ADDRESS = MAC_ADDRESS.replace(":", "")
MAC_ADDRESS2 = "11:22:33:44:55:66"
MAC_ADDRESS3 = "66:55:44:33:22:11"
DEFAULT_ENTRY_TITLE = f"{ALIAS} {MODEL}"
DEFAULT_ENTRY_TITLE_CAMERA = f"{ALIAS_CAMERA} {MODEL_CAMERA}"
CREDENTIALS_HASH_LEGACY = ""
CONN_PARAMS_LEGACY = DeviceConnectionParameters(
DeviceFamily.IotSmartPlugSwitch, DeviceEncryptionType.Xor
)
DEVICE_CONFIG_LEGACY = DeviceConfig(IP_ADDRESS)
DEVICE_CONFIG_DICT_LEGACY = {
k: v for k, v in DEVICE_CONFIG_LEGACY.to_dict().items() if k != "credentials"
}
CREDENTIALS = Credentials("foo", "bar")
CREDENTIALS_HASH_AES = "AES/abcdefghijklmnopqrstuvabcdefghijklmnopqrstuv=="
CREDENTIALS_HASH_KLAP = "KLAP/abcdefghijklmnopqrstuv=="
CONN_PARAMS_KLAP = DeviceConnectionParameters(
DeviceFamily.SmartTapoPlug, DeviceEncryptionType.Klap
)
DEVICE_CONFIG_KLAP = DeviceConfig(
IP_ADDRESS,
credentials=CREDENTIALS,
connection_type=CONN_PARAMS_KLAP,
uses_http=True,
)
CONN_PARAMS_AES = DeviceConnectionParameters(
DeviceFamily.SmartTapoPlug, DeviceEncryptionType.Aes
)
_test_privkey = (
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKLJKmBWGj6WYo9sewI8vkqar"
"Ed5H1JUr8Jj/LEWLTtV6+Mm4mfyEk6YKFHSmIG4AGgrVsGK/EbEkTZk9CwtixNQpBVc36oN2R"
"vuWWV38YnP4vI63mNxTA/gQonCsahjN4HfwE87pM7O5z39aeunoYm6Be663t33DbJH1ZUbZjm"
"tAgMBAAECgYB1Bn1KaFvRprcQOIJt51E9vNghQbf8rhj0fIEKpdC6mVhNIoUdCO+URNqnh+hP"
"SQIx4QYreUlHbsSeABFxOQSDJm6/kqyQsp59nCVDo/bXTtlvcSJ/sU3riqJNxYqEU1iJ0xMvU"
"N1VKKTmik89J8e5sN9R0AFfUSJIk7MpdOoD2QJBANTbV27nenyvbqee/ul4frdt2rrPGcGpcV"
"QmY87qbbrZgqgL5LMHHD7T/v/I8D1wRog1sBz/AiZGcnv/ox8dHKsCQQDDx8DCGPySSVqKVua"
"yUkBNpglN83wiCXZjyEtWIt+aB1A2n5ektE/o8oHnnOuvMdooxvtid7Mdapi2VLHV7VMHAkAE"
"d0GjWwnv2cJpk+VnQpbuBEkFiFjS/loZWODZM4Pv2qZqHi3DL9AA5XPBLBcWQufH7dBvG06RP"
"QMj5N4oRfUXAkEAuJJkVliqHNvM4OkGewzyFII4+WVYHNqg43dcFuuvtA27AJQ6qYtYXrvp3k"
"phI3yzOIhHTNCea1goepSkR5ODFwJBAJCTRbB+P47aEr/xA51ZFHE6VefDBJG9yg6yK4jcOxg"
"5ficXEpx8442okNtlzwa+QHpm/L3JOFrHwiEeVqXtiqY="
)
_test_pubkey = (
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiySpgVho+lmKPbHsCPL5KmqxHeR9SVK/CY"
"/yxFi07VevjJuJn8hJOmChR0piBuABoK1bBivxGxJE2ZPQsLYsTUKQVXN+qDdkb7llld/GJz+"
"LyOt5jcUwP4EKJwrGoYzeB38BPO6TOzuc9/Wnrp6GJugXuut7d9w2yR9WVG2Y5rQIDAQAB"
)
AES_KEYS = {"private": _test_privkey, "public": _test_pubkey}
DEVICE_CONFIG_AES = DeviceConfig(
IP_ADDRESS2,
credentials=CREDENTIALS,
connection_type=CONN_PARAMS_AES,
uses_http=True,
aes_keys=AES_KEYS,
)
CONN_PARAMS_AES_CAMERA = DeviceConnectionParameters(
DeviceFamily.SmartIpCamera, DeviceEncryptionType.Aes, https=True, login_version=2
)
DEVICE_CONFIG_AES_CAMERA = DeviceConfig(
IP_ADDRESS3,
credentials=CREDENTIALS,
connection_type=CONN_PARAMS_AES_CAMERA,
uses_http=True,
)
DEVICE_CONFIG_DICT_KLAP = {
k: v for k, v in DEVICE_CONFIG_KLAP.to_dict().items() if k != "credentials"
}
DEVICE_CONFIG_DICT_AES = {
k: v for k, v in DEVICE_CONFIG_AES.to_dict().items() if k != "credentials"
}
CREATE_ENTRY_DATA_LEGACY = {
CONF_HOST: IP_ADDRESS,
CONF_ALIAS: ALIAS,
CONF_MODEL: MODEL,
CONF_CONNECTION_PARAMETERS: CONN_PARAMS_LEGACY.to_dict(),
CONF_USES_HTTP: False,
}
CREATE_ENTRY_DATA_KLAP = {
CONF_HOST: IP_ADDRESS,
CONF_ALIAS: ALIAS,
CONF_MODEL: MODEL,
CONF_CREDENTIALS_HASH: CREDENTIALS_HASH_KLAP,
CONF_CONNECTION_PARAMETERS: CONN_PARAMS_KLAP.to_dict(),
CONF_USES_HTTP: True,
}
CREATE_ENTRY_DATA_AES = {
CONF_HOST: IP_ADDRESS2,
CONF_ALIAS: ALIAS,
CONF_MODEL: MODEL,
CONF_CREDENTIALS_HASH: CREDENTIALS_HASH_AES,
CONF_CONNECTION_PARAMETERS: CONN_PARAMS_AES.to_dict(),
CONF_USES_HTTP: True,
CONF_AES_KEYS: AES_KEYS,
}
CREATE_ENTRY_DATA_AES_CAMERA = {
CONF_HOST: IP_ADDRESS3,
CONF_ALIAS: ALIAS_CAMERA,
CONF_MODEL: MODEL_CAMERA,
CONF_CREDENTIALS_HASH: CREDENTIALS_HASH_AES,
CONF_CONNECTION_PARAMETERS: CONN_PARAMS_AES_CAMERA.to_dict(),
CONF_USES_HTTP: True,
CONF_LIVE_VIEW: True,
CONF_CAMERA_CREDENTIALS: {"username": "camuser", "password": "campass"},
}
SMALLEST_VALID_JPEG = (
"ffd8ffe000104a46494600010101004800480000ffdb00430003020202020203020202030303030406040404040408060"
"6050609080a0a090809090a0c0f0c0a0b0e0b09090d110d0e0f101011100a0c12131210130f101010ffc9000b08000100"
"0101011100ffcc000600101005ffda0008010100003f00d2cf20ffd9"
)
SMALLEST_VALID_JPEG_BYTES = bytes.fromhex(SMALLEST_VALID_JPEG)
def _load_feature_fixtures(): def _load_feature_fixtures():
fixtures = load_json_value_fixture("features.json", DOMAIN) fixtures = load_json_value_fixture("features.json", DOMAIN)
@ -201,7 +63,7 @@ async def setup_platform_for_device(
_patch_discovery(device=device), _patch_discovery(device=device),
_patch_connect(device=device), _patch_connect(device=device),
): ):
await async_setup_component(hass, DOMAIN, {DOMAIN: {}}) await hass.config_entries.async_setup(config_entry.entry_id)
# Good practice to wait background tasks in tests see PR #112726 # Good practice to wait background tasks in tests see PR #112726
await hass.async_block_till_done(wait_background_tasks=True) await hass.async_block_till_done(wait_background_tasks=True)

View File

@ -10,7 +10,8 @@ import pytest
from homeassistant.components.tplink import DOMAIN from homeassistant.components.tplink import DOMAIN
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from . import ( from . import _mocked_device
from .const import (
ALIAS_CAMERA, ALIAS_CAMERA,
CREATE_ENTRY_DATA_AES_CAMERA, CREATE_ENTRY_DATA_AES_CAMERA,
CREATE_ENTRY_DATA_LEGACY, CREATE_ENTRY_DATA_LEGACY,
@ -26,7 +27,6 @@ from . import (
MAC_ADDRESS2, MAC_ADDRESS2,
MAC_ADDRESS3, MAC_ADDRESS3,
MODEL_CAMERA, MODEL_CAMERA,
_mocked_device,
) )
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -115,8 +115,12 @@ def mock_setup_entry() -> Generator[AsyncMock]:
@pytest.fixture @pytest.fixture
def mock_init() -> Generator[AsyncMock]: def mock_init() -> Generator[dict[str, AsyncMock]]:
"""Override async_setup_entry.""" """Override async_setup and async_setup_entry.
This fixture must be declared before the hass fixture to avoid errors
in the logs during teardown of the hass fixture which calls async_unload.
"""
with patch.multiple( with patch.multiple(
"homeassistant.components.tplink", "homeassistant.components.tplink",
async_setup=DEFAULT, async_setup=DEFAULT,

View File

@ -0,0 +1,146 @@
"""Constants for the tplink component tests."""
from kasa import (
DeviceConfig,
DeviceConnectionParameters,
DeviceEncryptionType,
DeviceFamily,
)
from homeassistant.components.tplink import (
CONF_AES_KEYS,
CONF_ALIAS,
CONF_CAMERA_CREDENTIALS,
CONF_CONNECTION_PARAMETERS,
CONF_CREDENTIALS_HASH,
CONF_HOST,
CONF_LIVE_VIEW,
CONF_MODEL,
CONF_USES_HTTP,
Credentials,
)
MODULE = "homeassistant.components.tplink"
MODULE_CONFIG_FLOW = "homeassistant.components.tplink.config_flow"
IP_ADDRESS = "127.0.0.1"
IP_ADDRESS2 = "127.0.0.2"
IP_ADDRESS3 = "127.0.0.3"
ALIAS = "My Bulb"
ALIAS_CAMERA = "My Camera"
MODEL = "HS100"
MODEL_CAMERA = "C210"
MAC_ADDRESS = "aa:bb:cc:dd:ee:ff"
DEVICE_ID = "123456789ABCDEFGH"
DEVICE_ID_MAC = "AA:BB:CC:DD:EE:FF"
DHCP_FORMATTED_MAC_ADDRESS = MAC_ADDRESS.replace(":", "")
MAC_ADDRESS2 = "11:22:33:44:55:66"
MAC_ADDRESS3 = "66:55:44:33:22:11"
DEFAULT_ENTRY_TITLE = f"{ALIAS} {MODEL}"
DEFAULT_ENTRY_TITLE_CAMERA = f"{ALIAS_CAMERA} {MODEL_CAMERA}"
CREDENTIALS_HASH_LEGACY = ""
CONN_PARAMS_LEGACY = DeviceConnectionParameters(
DeviceFamily.IotSmartPlugSwitch, DeviceEncryptionType.Xor
)
DEVICE_CONFIG_LEGACY = DeviceConfig(IP_ADDRESS)
DEVICE_CONFIG_DICT_LEGACY = {
k: v for k, v in DEVICE_CONFIG_LEGACY.to_dict().items() if k != "credentials"
}
CREDENTIALS = Credentials("foo", "bar")
CREDENTIALS_HASH_AES = "AES/abcdefghijklmnopqrstuvabcdefghijklmnopqrstuv=="
CREDENTIALS_HASH_KLAP = "KLAP/abcdefghijklmnopqrstuv=="
CONN_PARAMS_KLAP = DeviceConnectionParameters(
DeviceFamily.SmartTapoPlug, DeviceEncryptionType.Klap
)
DEVICE_CONFIG_KLAP = DeviceConfig(
IP_ADDRESS,
credentials=CREDENTIALS,
connection_type=CONN_PARAMS_KLAP,
uses_http=True,
)
CONN_PARAMS_AES = DeviceConnectionParameters(
DeviceFamily.SmartTapoPlug, DeviceEncryptionType.Aes
)
_test_privkey = (
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKLJKmBWGj6WYo9sewI8vkqar"
"Ed5H1JUr8Jj/LEWLTtV6+Mm4mfyEk6YKFHSmIG4AGgrVsGK/EbEkTZk9CwtixNQpBVc36oN2R"
"vuWWV38YnP4vI63mNxTA/gQonCsahjN4HfwE87pM7O5z39aeunoYm6Be663t33DbJH1ZUbZjm"
"tAgMBAAECgYB1Bn1KaFvRprcQOIJt51E9vNghQbf8rhj0fIEKpdC6mVhNIoUdCO+URNqnh+hP"
"SQIx4QYreUlHbsSeABFxOQSDJm6/kqyQsp59nCVDo/bXTtlvcSJ/sU3riqJNxYqEU1iJ0xMvU"
"N1VKKTmik89J8e5sN9R0AFfUSJIk7MpdOoD2QJBANTbV27nenyvbqee/ul4frdt2rrPGcGpcV"
"QmY87qbbrZgqgL5LMHHD7T/v/I8D1wRog1sBz/AiZGcnv/ox8dHKsCQQDDx8DCGPySSVqKVua"
"yUkBNpglN83wiCXZjyEtWIt+aB1A2n5ektE/o8oHnnOuvMdooxvtid7Mdapi2VLHV7VMHAkAE"
"d0GjWwnv2cJpk+VnQpbuBEkFiFjS/loZWODZM4Pv2qZqHi3DL9AA5XPBLBcWQufH7dBvG06RP"
"QMj5N4oRfUXAkEAuJJkVliqHNvM4OkGewzyFII4+WVYHNqg43dcFuuvtA27AJQ6qYtYXrvp3k"
"phI3yzOIhHTNCea1goepSkR5ODFwJBAJCTRbB+P47aEr/xA51ZFHE6VefDBJG9yg6yK4jcOxg"
"5ficXEpx8442okNtlzwa+QHpm/L3JOFrHwiEeVqXtiqY="
)
_test_pubkey = (
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiySpgVho+lmKPbHsCPL5KmqxHeR9SVK/CY"
"/yxFi07VevjJuJn8hJOmChR0piBuABoK1bBivxGxJE2ZPQsLYsTUKQVXN+qDdkb7llld/GJz+"
"LyOt5jcUwP4EKJwrGoYzeB38BPO6TOzuc9/Wnrp6GJugXuut7d9w2yR9WVG2Y5rQIDAQAB"
)
AES_KEYS = {"private": _test_privkey, "public": _test_pubkey}
DEVICE_CONFIG_AES = DeviceConfig(
IP_ADDRESS2,
credentials=CREDENTIALS,
connection_type=CONN_PARAMS_AES,
uses_http=True,
aes_keys=AES_KEYS,
)
CONN_PARAMS_AES_CAMERA = DeviceConnectionParameters(
DeviceFamily.SmartIpCamera, DeviceEncryptionType.Aes, https=True, login_version=2
)
DEVICE_CONFIG_AES_CAMERA = DeviceConfig(
IP_ADDRESS3,
credentials=CREDENTIALS,
connection_type=CONN_PARAMS_AES_CAMERA,
uses_http=True,
)
DEVICE_CONFIG_DICT_KLAP = {
k: v for k, v in DEVICE_CONFIG_KLAP.to_dict().items() if k != "credentials"
}
DEVICE_CONFIG_DICT_AES = {
k: v for k, v in DEVICE_CONFIG_AES.to_dict().items() if k != "credentials"
}
CREATE_ENTRY_DATA_LEGACY = {
CONF_HOST: IP_ADDRESS,
CONF_ALIAS: ALIAS,
CONF_MODEL: MODEL,
CONF_CONNECTION_PARAMETERS: CONN_PARAMS_LEGACY.to_dict(),
CONF_USES_HTTP: False,
}
CREATE_ENTRY_DATA_KLAP = {
CONF_HOST: IP_ADDRESS,
CONF_ALIAS: ALIAS,
CONF_MODEL: MODEL,
CONF_CREDENTIALS_HASH: CREDENTIALS_HASH_KLAP,
CONF_CONNECTION_PARAMETERS: CONN_PARAMS_KLAP.to_dict(),
CONF_USES_HTTP: True,
}
CREATE_ENTRY_DATA_AES = {
CONF_HOST: IP_ADDRESS2,
CONF_ALIAS: ALIAS,
CONF_MODEL: MODEL,
CONF_CREDENTIALS_HASH: CREDENTIALS_HASH_AES,
CONF_CONNECTION_PARAMETERS: CONN_PARAMS_AES.to_dict(),
CONF_USES_HTTP: True,
CONF_AES_KEYS: AES_KEYS,
}
CREATE_ENTRY_DATA_AES_CAMERA = {
CONF_HOST: IP_ADDRESS3,
CONF_ALIAS: ALIAS_CAMERA,
CONF_MODEL: MODEL_CAMERA,
CONF_CREDENTIALS_HASH: CREDENTIALS_HASH_AES,
CONF_CONNECTION_PARAMETERS: CONN_PARAMS_AES_CAMERA.to_dict(),
CONF_USES_HTTP: True,
CONF_LIVE_VIEW: True,
CONF_CAMERA_CREDENTIALS: {"username": "camuser", "password": "campass"},
}
SMALLEST_VALID_JPEG = (
"ffd8ffe000104a46494600010101004800480000ffdb00430003020202020203020202030303030406040404040408060"
"6050609080a0a090809090a0c0f0c0a0b0e0b09090d110d0e0f101011100a0c12131210130f101010ffc9000b08000100"
"0101011100ffcc000600101005ffda0008010100003f00d2cf20ffd9"
)
SMALLEST_VALID_JPEG_BYTES = bytes.fromhex(SMALLEST_VALID_JPEG)

View File

@ -4,18 +4,14 @@ from kasa import Feature
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
from homeassistant.components import tplink
from homeassistant.components.tplink.binary_sensor import BINARY_SENSOR_DESCRIPTIONS from homeassistant.components.tplink.binary_sensor import BINARY_SENSOR_DESCRIPTIONS
from homeassistant.components.tplink.const import DOMAIN from homeassistant.components.tplink.const import DOMAIN
from homeassistant.components.tplink.entity import EXCLUDED_FEATURES from homeassistant.components.tplink.entity import EXCLUDED_FEATURES
from homeassistant.const import CONF_HOST, Platform from homeassistant.const import CONF_HOST, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from . import ( from . import (
DEVICE_ID,
MAC_ADDRESS,
_mocked_device, _mocked_device,
_mocked_feature, _mocked_feature,
_mocked_strip_children, _mocked_strip_children,
@ -24,6 +20,7 @@ from . import (
setup_platform_for_device, setup_platform_for_device,
snapshot_platform, snapshot_platform,
) )
from .const import DEVICE_ID, MAC_ADDRESS
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -47,7 +44,7 @@ async def test_states(
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test binary sensor states."""
features = {description.key for description in BINARY_SENSOR_DESCRIPTIONS} features = {description.key for description in BINARY_SENSOR_DESCRIPTIONS}
features.update(EXCLUDED_FEATURES) features.update(EXCLUDED_FEATURES)
device = _mocked_device(alias="my_device", features=features) device = _mocked_device(alias="my_device", features=features)
@ -68,7 +65,7 @@ async def test_binary_sensor(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
mocked_feature_binary_sensor: Feature, mocked_feature_binary_sensor: Feature,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test binary sensor unique ids."""
mocked_feature = mocked_feature_binary_sensor mocked_feature = mocked_feature_binary_sensor
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
@ -77,7 +74,7 @@ async def test_binary_sensor(
plug = _mocked_device(alias="my_plug", features=[mocked_feature]) plug = _mocked_device(alias="my_plug", features=[mocked_feature])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
# The entity_id is based on standard name from core. # The entity_id is based on standard name from core.
@ -93,7 +90,7 @@ async def test_binary_sensor_children(
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
mocked_feature_binary_sensor: Feature, mocked_feature_binary_sensor: Feature,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test binary sensor children."""
mocked_feature = mocked_feature_binary_sensor mocked_feature = mocked_feature_binary_sensor
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
@ -105,7 +102,7 @@ async def test_binary_sensor_children(
children=_mocked_strip_children(features=[mocked_feature]), children=_mocked_strip_children(features=[mocked_feature]),
) )
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "binary_sensor.my_plug_overheated" entity_id = "binary_sensor.my_plug_overheated"

View File

@ -4,7 +4,6 @@ from kasa import Feature
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
from homeassistant.components import tplink
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
from homeassistant.components.tplink.button import BUTTON_DESCRIPTIONS from homeassistant.components.tplink.button import BUTTON_DESCRIPTIONS
from homeassistant.components.tplink.const import DOMAIN from homeassistant.components.tplink.const import DOMAIN
@ -16,11 +15,8 @@ from homeassistant.helpers import (
entity_registry as er, entity_registry as er,
issue_registry as ir, issue_registry as ir,
) )
from homeassistant.setup import async_setup_component
from . import ( from . import (
DEVICE_ID,
MAC_ADDRESS,
_mocked_device, _mocked_device,
_mocked_feature, _mocked_feature,
_mocked_strip_children, _mocked_strip_children,
@ -30,6 +26,7 @@ from . import (
setup_platform_for_device, setup_platform_for_device,
snapshot_platform, snapshot_platform,
) )
from .const import DEVICE_ID, MAC_ADDRESS
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -83,7 +80,7 @@ def create_deprecated_child_button_entities(
@pytest.fixture @pytest.fixture
def mocked_feature_button() -> Feature: def mocked_feature_button() -> Feature:
"""Return mocked tplink binary sensor feature.""" """Return mocked tplink button feature."""
return _mocked_feature( return _mocked_feature(
"test_alarm", "test_alarm",
value="<Action>", value="<Action>",
@ -101,7 +98,7 @@ async def test_states(
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
create_deprecated_button_entities, create_deprecated_button_entities,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test button states."""
features = {description.key for description in BUTTON_DESCRIPTIONS} features = {description.key for description in BUTTON_DESCRIPTIONS}
features.update(EXCLUDED_FEATURES) features.update(EXCLUDED_FEATURES)
device = _mocked_device(alias="my_device", features=features) device = _mocked_device(alias="my_device", features=features)
@ -118,14 +115,15 @@ async def test_states(
async def test_button( async def test_button(
hass: HomeAssistant, hass: HomeAssistant,
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
mock_config_entry: MockConfigEntry,
mocked_feature_button: Feature, mocked_feature_button: Feature,
create_deprecated_button_entities, create_deprecated_button_entities,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test button unique ids."""
mocked_feature = mocked_feature_button mocked_feature = mocked_feature_button
plug = _mocked_device(alias="my_device", features=[mocked_feature]) plug = _mocked_device(alias="my_device", features=[mocked_feature])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
# The entity_id is based on standard name from core. # The entity_id is based on standard name from core.
@ -139,11 +137,12 @@ async def test_button_children(
hass: HomeAssistant, hass: HomeAssistant,
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
mock_config_entry: MockConfigEntry,
mocked_feature_button: Feature, mocked_feature_button: Feature,
create_deprecated_button_entities, create_deprecated_button_entities,
create_deprecated_child_button_entities, create_deprecated_child_button_entities,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test button children."""
mocked_feature = mocked_feature_button mocked_feature = mocked_feature_button
plug = _mocked_device( plug = _mocked_device(
alias="my_device", alias="my_device",
@ -151,7 +150,7 @@ async def test_button_children(
children=_mocked_strip_children(features=[mocked_feature]), children=_mocked_strip_children(features=[mocked_feature]),
) )
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "button.my_device_test_alarm" entity_id = "button.my_device_test_alarm"
@ -173,6 +172,7 @@ async def test_button_children(
async def test_button_press( async def test_button_press(
hass: HomeAssistant, hass: HomeAssistant,
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
mock_config_entry: MockConfigEntry,
mocked_feature_button: Feature, mocked_feature_button: Feature,
create_deprecated_button_entities, create_deprecated_button_entities,
) -> None: ) -> None:
@ -180,7 +180,7 @@ async def test_button_press(
mocked_feature = mocked_feature_button mocked_feature = mocked_feature_button
plug = _mocked_device(alias="my_device", features=[mocked_feature]) plug = _mocked_device(alias="my_device", features=[mocked_feature])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "button.my_device_test_alarm" entity_id = "button.my_device_test_alarm"
@ -213,7 +213,7 @@ async def test_button_not_exists_with_deprecation(
mocked_feature = mocked_feature_button mocked_feature = mocked_feature_button
dev = _mocked_device(alias="my_device", features=[mocked_feature]) dev = _mocked_device(alias="my_device", features=[mocked_feature])
with _patch_discovery(device=dev), _patch_connect(device=dev): with _patch_discovery(device=dev), _patch_connect(device=dev):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
assert not entity_registry.async_get(entity_id) assert not entity_registry.async_get(entity_id)
@ -265,7 +265,7 @@ async def test_button_exists_with_deprecation(
mocked_feature = mocked_feature_button mocked_feature = mocked_feature_button
dev = _mocked_device(alias="my_device", features=[mocked_feature]) dev = _mocked_device(alias="my_device", features=[mocked_feature])
with _patch_discovery(device=dev), _patch_connect(device=dev): with _patch_discovery(device=dev), _patch_connect(device=dev):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity = entity_registry.async_get(entity_id) entity = entity_registry.async_get(entity_id)

View File

@ -11,6 +11,9 @@ from syrupy.assertion import SnapshotAssertion
from homeassistant.components import stream from homeassistant.components import stream
from homeassistant.components.camera import ( from homeassistant.components.camera import (
DOMAIN as CAMERA_DOMAIN,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
CameraEntityFeature, CameraEntityFeature,
StreamType, StreamType,
async_get_image, async_get_image,
@ -23,15 +26,8 @@ from homeassistant.const import Platform
from homeassistant.core import HomeAssistant, HomeAssistantError from homeassistant.core import HomeAssistant, HomeAssistantError
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from . import ( from . import _mocked_device, setup_platform_for_device, snapshot_platform
DEVICE_ID, from .const import DEVICE_ID, IP_ADDRESS3, MAC_ADDRESS3, SMALLEST_VALID_JPEG_BYTES
IP_ADDRESS3,
MAC_ADDRESS3,
SMALLEST_VALID_JPEG_BYTES,
_mocked_device,
setup_platform_for_device,
snapshot_platform,
)
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
from tests.typing import WebSocketGenerator from tests.typing import WebSocketGenerator
@ -44,7 +40,7 @@ async def test_states(
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test states.""" """Test camera states."""
mock_camera_config_entry.add_to_hass(hass) mock_camera_config_entry.add_to_hass(hass)
mock_device = _mocked_device( mock_device = _mocked_device(
@ -73,6 +69,7 @@ async def test_camera_unique_id(
hass: HomeAssistant, hass: HomeAssistant,
mock_camera_config_entry: MockConfigEntry, mock_camera_config_entry: MockConfigEntry,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test camera unique id.""" """Test camera unique id."""
mock_device = _mocked_device( mock_device = _mocked_device(
@ -92,14 +89,13 @@ async def test_camera_unique_id(
) )
assert device_entries assert device_entries
entity_id = "camera.my_camera_live_view" entity_id = "camera.my_camera_live_view"
entity_registry = er.async_get(hass)
assert entity_registry.async_get(entity_id).unique_id == f"{DEVICE_ID}-live_view" assert entity_registry.async_get(entity_id).unique_id == f"{DEVICE_ID}-live_view"
async def test_handle_mjpeg_stream( async def test_handle_mjpeg_stream(
hass: HomeAssistant, hass: HomeAssistant,
mock_camera_config_entry: MockConfigEntry, mock_camera_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None: ) -> None:
"""Test handle_async_mjpeg_stream.""" """Test handle_async_mjpeg_stream."""
mock_device = _mocked_device( mock_device = _mocked_device(
@ -126,7 +122,6 @@ async def test_handle_mjpeg_stream(
async def test_handle_mjpeg_stream_not_supported( async def test_handle_mjpeg_stream_not_supported(
hass: HomeAssistant, hass: HomeAssistant,
mock_camera_config_entry: MockConfigEntry, mock_camera_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None: ) -> None:
"""Test handle_async_mjpeg_stream.""" """Test handle_async_mjpeg_stream."""
mock_device = _mocked_device( mock_device = _mocked_device(
@ -216,7 +211,7 @@ async def test_no_camera_image_when_streaming(
mock_camera_config_entry: MockConfigEntry, mock_camera_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory, freezer: FrozenDateTimeFactory,
) -> None: ) -> None:
"""Test async_get_image.""" """Test no camera image when streaming."""
mock_device = _mocked_device( mock_device = _mocked_device(
modules=[Module.Camera], modules=[Module.Camera],
alias="my_camera", alias="my_camera",
@ -272,9 +267,8 @@ async def test_no_camera_image_when_streaming(
async def test_no_concurrent_camera_image( async def test_no_concurrent_camera_image(
hass: HomeAssistant, hass: HomeAssistant,
mock_camera_config_entry: MockConfigEntry, mock_camera_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None: ) -> None:
"""Test async_get_image.""" """Test async_get_image doesn't make concurrent requests."""
mock_device = _mocked_device( mock_device = _mocked_device(
modules=[Module.Camera], modules=[Module.Camera],
alias="my_camera", alias="my_camera",
@ -321,7 +315,7 @@ async def test_camera_image_auth_error(
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
) -> None: ) -> None:
"""Test async_get_image.""" """Test async_get_image auth error."""
mock_device = _mocked_device( mock_device = _mocked_device(
modules=[Module.Camera], modules=[Module.Camera],
alias="my_camera", alias="my_camera",
@ -367,7 +361,7 @@ async def test_camera_stream_source(
mock_camera_config_entry: MockConfigEntry, mock_camera_config_entry: MockConfigEntry,
hass_ws_client: WebSocketGenerator, hass_ws_client: WebSocketGenerator,
) -> None: ) -> None:
"""Test async_get_image. """Test camera stream source.
This test would fail if the integration didn't properly This test would fail if the integration didn't properly
put stream in the dependencies. put stream in the dependencies.
@ -444,16 +438,16 @@ async def test_camera_turn_on_off(
assert state is not None assert state is not None
await hass.services.async_call( await hass.services.async_call(
"camera", CAMERA_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{"entity_id": "camera.my_camera_live_view"}, {"entity_id": "camera.my_camera_live_view"},
blocking=True, blocking=True,
) )
mock_camera.set_state.assert_called_with(True) mock_camera.set_state.assert_called_with(True)
await hass.services.async_call( await hass.services.async_call(
"camera", CAMERA_DOMAIN,
"turn_off", SERVICE_TURN_OFF,
{"entity_id": "camera.my_camera_live_view"}, {"entity_id": "camera.my_camera_live_view"},
blocking=True, blocking=True,
) )

View File

@ -27,12 +27,12 @@ from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from . import ( from . import (
DEVICE_ID,
_mocked_device, _mocked_device,
_mocked_feature, _mocked_feature,
setup_platform_for_device, setup_platform_for_device,
snapshot_platform, snapshot_platform,
) )
from .const import DEVICE_ID
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
@ -41,7 +41,7 @@ ENTITY_ID = "climate.thermostat"
@pytest.fixture @pytest.fixture
async def mocked_hub(hass: HomeAssistant) -> Device: async def mocked_hub(hass: HomeAssistant) -> Device:
"""Return mocked tplink binary sensor feature.""" """Return mocked tplink hub."""
features = [ features = [
_mocked_feature( _mocked_feature(
@ -166,7 +166,8 @@ async def test_set_hvac_mode(
) )
mocked_state.set_value.assert_called_with(True) mocked_state.set_value.assert_called_with(True)
with pytest.raises(ServiceValidationError): msg = "Tried to set unsupported mode: dry"
with pytest.raises(ServiceValidationError, match=msg):
await hass.services.async_call( await hass.services.async_call(
CLIMATE_DOMAIN, CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE, SERVICE_SET_HVAC_MODE,

View File

@ -37,7 +37,9 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from . import ( from . import _mocked_device, _patch_connect, _patch_discovery, _patch_single_discovery
from .conftest import override_side_effect
from .const import (
AES_KEYS, AES_KEYS,
ALIAS, ALIAS,
ALIAS_CAMERA, ALIAS_CAMERA,
@ -67,12 +69,7 @@ from . import (
MODEL_CAMERA, MODEL_CAMERA,
MODULE, MODULE,
SMALLEST_VALID_JPEG_BYTES, SMALLEST_VALID_JPEG_BYTES,
_mocked_device,
_patch_connect,
_patch_discovery,
_patch_single_discovery,
) )
from .conftest import override_side_effect
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -168,8 +165,11 @@ async def test_discovery(
assert result2["reason"] == "no_devices_found" assert result2["reason"] == "no_devices_found"
@pytest.mark.usefixtures("mock_init")
async def test_discovery_camera( async def test_discovery_camera(
hass: HomeAssistant, mock_discovery: AsyncMock, mock_connect: AsyncMock, mock_init hass: HomeAssistant,
mock_discovery: AsyncMock,
mock_connect: AsyncMock,
) -> None: ) -> None:
"""Test authenticated discovery for camera with stream.""" """Test authenticated discovery for camera with stream."""
mock_device = _mocked_device( mock_device = _mocked_device(
@ -228,8 +228,11 @@ async def test_discovery_camera(
assert result["context"]["unique_id"] == MAC_ADDRESS3 assert result["context"]["unique_id"] == MAC_ADDRESS3
@pytest.mark.usefixtures("mock_init")
async def test_discovery_pick_device_camera( async def test_discovery_pick_device_camera(
hass: HomeAssistant, mock_discovery: AsyncMock, mock_connect: AsyncMock, mock_init hass: HomeAssistant,
mock_discovery: AsyncMock,
mock_connect: AsyncMock,
) -> None: ) -> None:
"""Test authenticated discovery for camera with stream.""" """Test authenticated discovery for camera with stream."""
mock_device = _mocked_device( mock_device = _mocked_device(
@ -293,8 +296,11 @@ async def test_discovery_pick_device_camera(
assert result["context"]["unique_id"] == MAC_ADDRESS3 assert result["context"]["unique_id"] == MAC_ADDRESS3
@pytest.mark.usefixtures("mock_init")
async def test_discovery_auth( async def test_discovery_auth(
hass: HomeAssistant, mock_discovery: AsyncMock, mock_connect: AsyncMock, mock_init hass: HomeAssistant,
mock_discovery: AsyncMock,
mock_connect: AsyncMock,
) -> None: ) -> None:
"""Test authenticated discovery.""" """Test authenticated discovery."""
mock_device = _mocked_device( mock_device = _mocked_device(
@ -336,8 +342,11 @@ async def test_discovery_auth(
assert result2["context"]["unique_id"] == MAC_ADDRESS assert result2["context"]["unique_id"] == MAC_ADDRESS
@pytest.mark.usefixtures("mock_init")
async def test_discovery_auth_camera( async def test_discovery_auth_camera(
hass: HomeAssistant, mock_discovery: AsyncMock, mock_connect: AsyncMock, mock_init hass: HomeAssistant,
mock_discovery: AsyncMock,
mock_connect: AsyncMock,
) -> None: ) -> None:
"""Test authenticated discovery for camera with stream.""" """Test authenticated discovery for camera with stream."""
mock_device = _mocked_device( mock_device = _mocked_device(
@ -407,13 +416,13 @@ async def test_discovery_auth_camera(
], ],
ids=["invalid-auth", "unknown-error"], ids=["invalid-auth", "unknown-error"],
) )
@pytest.mark.usefixtures("mock_init")
async def test_discovery_auth_errors( async def test_discovery_auth_errors(
hass: HomeAssistant, hass: HomeAssistant,
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_init, error_type: Exception,
error_type, errors_msg: str,
errors_msg, error_placement: str,
error_placement,
) -> None: ) -> None:
"""Test handling of discovery authentication errors. """Test handling of discovery authentication errors.
@ -465,10 +474,10 @@ async def test_discovery_auth_errors(
assert result3["context"]["unique_id"] == MAC_ADDRESS assert result3["context"]["unique_id"] == MAC_ADDRESS
@pytest.mark.usefixtures("mock_init")
async def test_discovery_new_credentials( async def test_discovery_new_credentials(
hass: HomeAssistant, hass: HomeAssistant,
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_init,
) -> None: ) -> None:
"""Test setting up discovery with new credentials.""" """Test setting up discovery with new credentials."""
mock_device = mock_connect["mock_devices"][IP_ADDRESS] mock_device = mock_connect["mock_devices"][IP_ADDRESS]
@ -514,10 +523,10 @@ async def test_discovery_new_credentials(
assert result3["context"]["unique_id"] == MAC_ADDRESS assert result3["context"]["unique_id"] == MAC_ADDRESS
@pytest.mark.usefixtures("mock_init")
async def test_discovery_new_credentials_invalid( async def test_discovery_new_credentials_invalid(
hass: HomeAssistant, hass: HomeAssistant,
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_init,
) -> None: ) -> None:
"""Test setting up discovery with new invalid credentials.""" """Test setting up discovery with new invalid credentials."""
mock_device = mock_connect["mock_devices"][IP_ADDRESS] mock_device = mock_connect["mock_devices"][IP_ADDRESS]
@ -977,11 +986,11 @@ async def test_manual_no_capabilities(hass: HomeAssistant) -> None:
assert result["context"]["unique_id"] == MAC_ADDRESS assert result["context"]["unique_id"] == MAC_ADDRESS
@pytest.mark.usefixtures("mock_init")
async def test_manual_auth( async def test_manual_auth(
hass: HomeAssistant, hass: HomeAssistant,
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_init,
) -> None: ) -> None:
"""Test manually setup.""" """Test manually setup."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -1083,14 +1092,14 @@ async def test_manual_auth_camera(
], ],
ids=["invalid-auth", "unknown-error"], ids=["invalid-auth", "unknown-error"],
) )
@pytest.mark.usefixtures("mock_init")
async def test_manual_auth_errors( async def test_manual_auth_errors(
hass: HomeAssistant, hass: HomeAssistant,
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_init, error_type: Exception,
error_type, errors_msg: str,
errors_msg, error_placement: str,
error_placement,
) -> None: ) -> None:
"""Test manually setup auth errors.""" """Test manually setup auth errors."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -1150,9 +1159,9 @@ async def test_manual_port_override(
hass: HomeAssistant, hass: HomeAssistant,
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
host_str, host_str: str,
host, host: str,
port, port: int,
) -> None: ) -> None:
"""Test manually setup.""" """Test manually setup."""
config = DeviceConfig( config = DeviceConfig(
@ -1342,7 +1351,7 @@ async def test_discovered_by_discovery_and_dhcp(hass: HomeAssistant) -> None:
], ],
) )
async def test_discovered_by_dhcp_or_discovery( async def test_discovered_by_dhcp_or_discovery(
hass: HomeAssistant, source, data hass: HomeAssistant, source: str, data: dict
) -> None: ) -> None:
"""Test we can setup when discovered from dhcp or discovery.""" """Test we can setup when discovered from dhcp or discovery."""
@ -1396,7 +1405,7 @@ async def test_discovered_by_dhcp_or_discovery(
], ],
) )
async def test_discovered_by_dhcp_or_discovery_failed_to_get_device( async def test_discovered_by_dhcp_or_discovery_failed_to_get_device(
hass: HomeAssistant, source, data hass: HomeAssistant, source: str, data: dict
) -> None: ) -> None:
"""Test we abort if we cannot get the unique id when discovered from dhcp.""" """Test we abort if we cannot get the unique id when discovered from dhcp."""
@ -1419,7 +1428,7 @@ async def test_integration_discovery_with_ip_change(
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
mock_connect: AsyncMock, mock_connect: AsyncMock,
) -> None: ) -> None:
"""Test reauth flow.""" """Test integration updates ip address from discovery."""
mock_config_entry.add_to_hass(hass) mock_config_entry.add_to_hass(hass)
with ( with (
patch("homeassistant.components.tplink.Discover.discover", return_value={}), patch("homeassistant.components.tplink.Discover.discover", return_value={}),
@ -1670,7 +1679,7 @@ async def test_reauth_camera(
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
mock_connect: AsyncMock, mock_connect: AsyncMock,
) -> None: ) -> None:
"""Test async_get_image.""" """Test reauth flow on invalid camera credentials."""
mock_device = mock_connect["mock_devices"][IP_ADDRESS3] mock_device = mock_connect["mock_devices"][IP_ADDRESS3]
mock_camera_config_entry.add_to_hass(hass) mock_camera_config_entry.add_to_hass(hass)
mock_camera_config_entry.async_start_reauth( mock_camera_config_entry.async_start_reauth(
@ -1762,7 +1771,7 @@ async def test_reauth_try_connect_all_fail(
override_side_effect(mock_discovery["discover_single"], TimeoutError), override_side_effect(mock_discovery["discover_single"], TimeoutError),
override_side_effect(mock_discovery["try_connect_all"], lambda *_, **__: None), override_side_effect(mock_discovery["try_connect_all"], lambda *_, **__: None),
): ):
result2 = await hass.config_entries.flow.async_configure( result = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
user_input={ user_input={
CONF_USERNAME: "fake_username", CONF_USERNAME: "fake_username",
@ -1774,7 +1783,23 @@ async def test_reauth_try_connect_all_fail(
IP_ADDRESS, credentials=credentials, port=None IP_ADDRESS, credentials=credentials, port=None
) )
mock_discovery["try_connect_all"].assert_called_once() mock_discovery["try_connect_all"].assert_called_once()
assert result2["errors"] == {"base": "cannot_connect"} assert result["errors"] == {"base": "cannot_connect"}
mock_discovery["try_connect_all"].reset_mock()
with (
override_side_effect(mock_discovery["discover_single"], TimeoutError),
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_USERNAME: "fake_username",
CONF_PASSWORD: "fake_password",
},
)
mock_discovery["try_connect_all"].assert_called_once()
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reauth_successful"
async def test_reauth_update_with_encryption_change( async def test_reauth_update_with_encryption_change(
@ -2025,9 +2050,9 @@ async def test_reauth_errors(
mock_added_config_entry: MockConfigEntry, mock_added_config_entry: MockConfigEntry,
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
mock_connect: AsyncMock, mock_connect: AsyncMock,
error_type, error_type: Exception,
errors_msg, errors_msg: str,
error_placement, error_placement: str,
) -> None: ) -> None:
"""Test reauth errors.""" """Test reauth errors."""
mock_added_config_entry.async_start_reauth(hass) mock_added_config_entry.async_start_reauth(hass)
@ -2089,8 +2114,8 @@ async def test_pick_device_errors(
hass: HomeAssistant, hass: HomeAssistant,
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
mock_connect: AsyncMock, mock_connect: AsyncMock,
error_type, error_type: type[Exception],
expected_flow, expected_flow: FlowResultType,
) -> None: ) -> None:
"""Test errors on pick_device.""" """Test errors on pick_device."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -2127,11 +2152,11 @@ async def test_pick_device_errors(
assert result4["context"]["unique_id"] == MAC_ADDRESS assert result4["context"]["unique_id"] == MAC_ADDRESS
@pytest.mark.usefixtures("mock_init")
async def test_discovery_timeout_try_connect_all( async def test_discovery_timeout_try_connect_all(
hass: HomeAssistant, hass: HomeAssistant,
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_init,
) -> None: ) -> None:
"""Test discovery tries legacy connect on timeout.""" """Test discovery tries legacy connect on timeout."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -2153,11 +2178,11 @@ async def test_discovery_timeout_try_connect_all(
assert mock_connect["connect"].call_count == 1 assert mock_connect["connect"].call_count == 1
@pytest.mark.usefixtures("mock_init")
async def test_discovery_timeout_try_connect_all_needs_creds( async def test_discovery_timeout_try_connect_all_needs_creds(
hass: HomeAssistant, hass: HomeAssistant,
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_init,
) -> None: ) -> None:
"""Test discovery tries legacy connect on timeout.""" """Test discovery tries legacy connect on timeout."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
@ -2191,11 +2216,11 @@ async def test_discovery_timeout_try_connect_all_needs_creds(
assert mock_connect["connect"].call_count == 1 assert mock_connect["connect"].call_count == 1
@pytest.mark.usefixtures("mock_init")
async def test_discovery_timeout_try_connect_all_fail( async def test_discovery_timeout_try_connect_all_fail(
hass: HomeAssistant, hass: HomeAssistant,
mock_discovery: AsyncMock, mock_discovery: AsyncMock,
mock_connect: AsyncMock, mock_connect: AsyncMock,
mock_init,
) -> None: ) -> None:
"""Test discovery tries legacy connect on timeout.""" """Test discovery tries legacy connect on timeout."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(

View File

@ -2,8 +2,7 @@
from __future__ import annotations from __future__ import annotations
from datetime import timedelta from freezegun.api import FrozenDateTimeFactory
from kasa import Device, Module from kasa import Device, Module
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
@ -11,13 +10,15 @@ from homeassistant.components.fan import (
ATTR_PERCENTAGE, ATTR_PERCENTAGE,
DOMAIN as FAN_DOMAIN, DOMAIN as FAN_DOMAIN,
SERVICE_SET_PERCENTAGE, SERVICE_SET_PERCENTAGE,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
) )
from homeassistant.const import ATTR_ENTITY_ID, Platform from homeassistant.const import ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
import homeassistant.util.dt as dt_util
from . import DEVICE_ID, _mocked_device, setup_platform_for_device, snapshot_platform from . import _mocked_device, setup_platform_for_device, snapshot_platform
from .const import DEVICE_ID
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
@ -56,6 +57,7 @@ async def test_fan_unique_id(
hass: HomeAssistant, hass: HomeAssistant,
mock_config_entry: MockConfigEntry, mock_config_entry: MockConfigEntry,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test a fan unique id.""" """Test a fan unique id."""
fan = _mocked_device(modules=[Module.Fan], alias="my_fan") fan = _mocked_device(modules=[Module.Fan], alias="my_fan")
@ -66,12 +68,16 @@ async def test_fan_unique_id(
) )
assert device_entries assert device_entries
entity_id = "fan.my_fan" entity_id = "fan.my_fan"
entity_registry = er.async_get(hass)
assert entity_registry.async_get(entity_id).unique_id == DEVICE_ID assert entity_registry.async_get(entity_id).unique_id == DEVICE_ID
async def test_fan(hass: HomeAssistant, mock_config_entry: MockConfigEntry) -> None: async def test_fan(
"""Test a color fan and that all transitions are correctly passed.""" hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test fan functionality."""
device = _mocked_device(modules=[Module.Fan], alias="my_fan") device = _mocked_device(modules=[Module.Fan], alias="my_fan")
fan = device.modules[Module.Fan] fan = device.modules[Module.Fan]
fan.fan_speed_level = 0 fan.fan_speed_level = 0
@ -83,26 +89,29 @@ async def test_fan(hass: HomeAssistant, mock_config_entry: MockConfigEntry) -> N
assert state.state == "off" assert state.state == "off"
await hass.services.async_call( await hass.services.async_call(
FAN_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True FAN_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
fan.set_fan_speed_level.assert_called_once_with(4) fan.set_fan_speed_level.assert_called_once_with(4)
fan.set_fan_speed_level.reset_mock() fan.set_fan_speed_level.reset_mock()
fan.fan_speed_level = 4 fan.fan_speed_level = 4
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
freezer.tick(10)
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True) await hass.async_block_till_done(wait_background_tasks=True)
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state.state == "on" assert state.state == "on"
await hass.services.async_call( await hass.services.async_call(
FAN_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True FAN_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
fan.set_fan_speed_level.assert_called_once_with(0) fan.set_fan_speed_level.assert_called_once_with(0)
fan.set_fan_speed_level.reset_mock() fan.set_fan_speed_level.reset_mock()
await hass.services.async_call( await hass.services.async_call(
FAN_DOMAIN, FAN_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_PERCENTAGE: 50}, {ATTR_ENTITY_ID: entity_id, ATTR_PERCENTAGE: 50},
blocking=True, blocking=True,
) )

View File

@ -38,6 +38,14 @@ from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from . import ( from . import (
_mocked_device,
_mocked_feature,
_patch_connect,
_patch_discovery,
_patch_single_discovery,
)
from .conftest import override_side_effect
from .const import (
ALIAS, ALIAS,
CREATE_ENTRY_DATA_AES, CREATE_ENTRY_DATA_AES,
CREATE_ENTRY_DATA_KLAP, CREATE_ENTRY_DATA_KLAP,
@ -53,13 +61,7 @@ from . import (
IP_ADDRESS, IP_ADDRESS,
MAC_ADDRESS, MAC_ADDRESS,
MODEL, MODEL,
_mocked_device,
_mocked_feature,
_patch_connect,
_patch_discovery,
_patch_single_discovery,
) )
from .conftest import override_side_effect
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
@ -98,7 +100,7 @@ async def test_config_entry_reload(hass: HomeAssistant) -> None:
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
with _patch_discovery(), _patch_single_discovery(), _patch_connect(): with _patch_discovery(), _patch_single_discovery(), _patch_connect():
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
assert already_migrated_config_entry.state is ConfigEntryState.LOADED assert already_migrated_config_entry.state is ConfigEntryState.LOADED
await hass.config_entries.async_unload(already_migrated_config_entry.entry_id) await hass.config_entries.async_unload(already_migrated_config_entry.entry_id)
@ -117,7 +119,7 @@ async def test_config_entry_retry(hass: HomeAssistant) -> None:
_patch_single_discovery(no_device=True), _patch_single_discovery(no_device=True),
_patch_connect(no_device=True), _patch_connect(no_device=True),
): ):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
assert already_migrated_config_entry.state is ConfigEntryState.SETUP_RETRY assert already_migrated_config_entry.state is ConfigEntryState.SETUP_RETRY
@ -175,7 +177,7 @@ async def test_config_entry_wrong_mac_Address(
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
with _patch_discovery(), _patch_single_discovery(), _patch_connect(): with _patch_discovery(), _patch_single_discovery(), _patch_connect():
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
assert already_migrated_config_entry.state is ConfigEntryState.SETUP_RETRY assert already_migrated_config_entry.state is ConfigEntryState.SETUP_RETRY
@ -309,7 +311,7 @@ async def test_plug_auth_fails(hass: HomeAssistant) -> None:
config_entry.add_to_hass(hass) config_entry.add_to_hass(hass)
device = _mocked_device(alias="my_plug", features=["state"]) device = _mocked_device(alias="my_plug", features=["state"])
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "switch.my_plug" entity_id = "switch.my_plug"
@ -355,7 +357,7 @@ async def test_update_attrs_fails_in_init(
type(light_module).color_temp = p type(light_module).color_temp = p
light.__str__ = lambda _: "MockLight" light.__str__ = lambda _: "MockLight"
with _patch_discovery(device=light), _patch_connect(device=light): with _patch_discovery(device=light), _patch_connect(device=light):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -388,7 +390,7 @@ async def test_update_attrs_fails_on_update(
light_module = light.modules[Module.Light] light_module = light.modules[Module.Light]
with _patch_discovery(device=light), _patch_connect(device=light): with _patch_discovery(device=light), _patch_connect(device=light):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -434,7 +436,7 @@ async def test_feature_no_category(
) )
dev.features["led"].category = Feature.Category.Unset dev.features["led"].category = Feature.Category.Unset
with _patch_discovery(device=dev), _patch_connect(device=dev): with _patch_discovery(device=dev), _patch_connect(device=dev):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "switch.my_plug_led" entity_id = "switch.my_plug_led"

View File

@ -20,6 +20,11 @@ from kasa.iot import IotDevice
import pytest import pytest
from homeassistant.components import tplink from homeassistant.components import tplink
from homeassistant.components.homeassistant.scene import (
CONF_SCENE_ID,
CONF_SNAPSHOT,
SERVICE_CREATE,
)
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_BRIGHTNESS,
ATTR_COLOR_MODE, ATTR_COLOR_MODE,
@ -35,7 +40,10 @@ from homeassistant.components.light import (
ATTR_XY_COLOR, ATTR_XY_COLOR,
DOMAIN as LIGHT_DOMAIN, DOMAIN as LIGHT_DOMAIN,
EFFECT_OFF, EFFECT_OFF,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
) )
from homeassistant.components.scene import DOMAIN as SCENE_DOMAIN
from homeassistant.components.tplink.const import DOMAIN from homeassistant.components.tplink.const import DOMAIN
from homeassistant.components.tplink.light import ( from homeassistant.components.tplink.light import (
SERVICE_RANDOM_EFFECT, SERVICE_RANDOM_EFFECT,
@ -56,14 +64,13 @@ from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from . import ( from . import (
DEVICE_ID,
MAC_ADDRESS,
_mocked_device, _mocked_device,
_mocked_feature, _mocked_feature,
_patch_connect, _patch_connect,
_patch_discovery, _patch_discovery,
_patch_single_discovery, _patch_single_discovery,
) )
from .const import DEVICE_ID, MAC_ADDRESS
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
@ -88,7 +95,7 @@ async def test_light_unique_id(
light = _mocked_device(modules=[Module.Light], alias="my_light") light = _mocked_device(modules=[Module.Light], alias="my_light")
light.device_type = device_type light.device_type = device_type
with _patch_discovery(device=light), _patch_connect(device=light): with _patch_discovery(device=light), _patch_connect(device=light):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -98,8 +105,11 @@ async def test_light_unique_id(
) )
async def test_legacy_dimmer_unique_id(hass: HomeAssistant) -> None: async def test_legacy_dimmer_unique_id(
"""Test a light unique id.""" hass: HomeAssistant,
entity_registry: er.EntityRegistry,
) -> None:
"""Test dimmer unique id."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -113,16 +123,16 @@ async def test_legacy_dimmer_unique_id(hass: HomeAssistant) -> None:
light.device_type = DeviceType.Dimmer light.device_type = DeviceType.Dimmer
with _patch_discovery(device=light), _patch_connect(device=light): with _patch_discovery(device=light), _patch_connect(device=light):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
entity_registry = er.async_get(hass)
assert entity_registry.async_get(entity_id).unique_id == "aa:bb:cc:dd:ee:ff" assert entity_registry.async_get(entity_id).unique_id == "aa:bb:cc:dd:ee:ff"
@pytest.mark.parametrize( @pytest.mark.parametrize(
("device", "transition"), ("device", "extra_data", "expected_transition"),
[ [
( (
_mocked_device( _mocked_device(
@ -135,7 +145,138 @@ async def test_legacy_dimmer_unique_id(hass: HomeAssistant) -> None:
), ),
], ],
), ),
2.0, {ATTR_TRANSITION: 2.0},
2.0 * 1_000,
),
(
_mocked_device(
modules=[Module.Light],
features=[
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
],
),
{},
None,
),
],
)
async def test_color_light(
hass: HomeAssistant,
device: MagicMock,
extra_data: dict,
expected_transition: float | None,
) -> None:
"""Test a color light and that all transitions are correctly passed."""
already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
)
already_migrated_config_entry.add_to_hass(hass)
light = device.modules[Module.Light]
# Setting color_temp to None emulates a device without color temp
light.color_temp = None
with _patch_discovery(device=device), _patch_connect(device=device):
await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done()
entity_id = "light.my_bulb"
BASE_PAYLOAD = {ATTR_ENTITY_ID: entity_id}
BASE_PAYLOAD |= extra_data
state = hass.states.get(entity_id)
assert state.state == "on"
attributes = state.attributes
assert attributes[ATTR_BRIGHTNESS] == 128
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp", "hs"]
assert attributes.get(ATTR_EFFECT) is None
assert attributes[ATTR_COLOR_MODE] == "hs"
assert attributes[ATTR_MIN_COLOR_TEMP_KELVIN] == 4000
assert attributes[ATTR_MAX_COLOR_TEMP_KELVIN] == 9000
assert attributes[ATTR_HS_COLOR] == (10, 30)
assert attributes[ATTR_RGB_COLOR] == (255, 191, 178)
assert attributes[ATTR_XY_COLOR] == (0.42, 0.336)
await hass.services.async_call(
LIGHT_DOMAIN, SERVICE_TURN_OFF, BASE_PAYLOAD, blocking=True
)
light.set_state.assert_called_once_with(
LightState(light_on=False, transition=expected_transition)
)
light.set_state.reset_mock()
await hass.services.async_call(
LIGHT_DOMAIN, SERVICE_TURN_ON, BASE_PAYLOAD, blocking=True
)
light.set_state.assert_called_once_with(
LightState(light_on=True, transition=expected_transition)
)
light.set_state.reset_mock()
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{**BASE_PAYLOAD, ATTR_BRIGHTNESS: 100},
blocking=True,
)
light.set_brightness.assert_called_with(39, transition=expected_transition)
light.set_brightness.reset_mock()
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{**BASE_PAYLOAD, ATTR_COLOR_TEMP_KELVIN: 6666},
blocking=True,
)
light.set_color_temp.assert_called_with(
6666, brightness=None, transition=expected_transition
)
light.set_color_temp.reset_mock()
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{**BASE_PAYLOAD, ATTR_COLOR_TEMP_KELVIN: 6666},
blocking=True,
)
light.set_color_temp.assert_called_with(
6666, brightness=None, transition=expected_transition
)
light.set_color_temp.reset_mock()
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{**BASE_PAYLOAD, ATTR_HS_COLOR: (10, 30)},
blocking=True,
)
light.set_hsv.assert_called_with(10, 30, None, transition=expected_transition)
light.set_hsv.reset_mock()
@pytest.mark.parametrize(
("device", "extra_data", "expected_transition"),
[
(
_mocked_device(
modules=[Module.Light, Module.LightEffect],
features=[
_mocked_feature("brightness", value=50),
_mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
],
),
{ATTR_TRANSITION: 2.0},
2.0 * 1_000,
), ),
( (
_mocked_device( _mocked_device(
@ -148,12 +289,16 @@ async def test_legacy_dimmer_unique_id(hass: HomeAssistant) -> None:
), ),
], ],
), ),
{},
None, None,
), ),
], ],
) )
async def test_color_light( async def test_color_light_with_active_effect(
hass: HomeAssistant, device: MagicMock, transition: float | None hass: HomeAssistant,
device: MagicMock,
extra_data: dict,
expected_transition: float | None,
) -> None: ) -> None:
"""Test a color light and that all transitions are correctly passed.""" """Test a color light and that all transitions are correctly passed."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
@ -162,93 +307,84 @@ async def test_color_light(
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
light = device.modules[Module.Light] light = device.modules[Module.Light]
# Setting color_temp to None emulates a device with active effects
light.color_temp = None
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_bulb" entity_id = "light.my_bulb"
KASA_TRANSITION_VALUE = transition * 1_000 if transition is not None else None
BASE_PAYLOAD = {ATTR_ENTITY_ID: entity_id} BASE_PAYLOAD = {ATTR_ENTITY_ID: entity_id}
if transition: BASE_PAYLOAD |= extra_data
BASE_PAYLOAD[ATTR_TRANSITION] = transition
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state.state == "on" assert state.state == "on"
attributes = state.attributes attributes = state.attributes
assert attributes[ATTR_BRIGHTNESS] == 128 assert attributes[ATTR_BRIGHTNESS] == 128
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp", "hs"] assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp", "hs"]
# If effect is active, only the brightness can be controlled # If effect is active, only the brightness can be controlled
if attributes.get(ATTR_EFFECT) is not None: assert attributes.get(ATTR_EFFECT) is not None
assert attributes[ATTR_COLOR_MODE] == "brightness" assert attributes[ATTR_COLOR_MODE] == "brightness"
else:
assert attributes[ATTR_COLOR_MODE] == "hs"
assert attributes[ATTR_MIN_COLOR_TEMP_KELVIN] == 4000
assert attributes[ATTR_MAX_COLOR_TEMP_KELVIN] == 9000
assert attributes[ATTR_HS_COLOR] == (10, 30)
assert attributes[ATTR_RGB_COLOR] == (255, 191, 178)
assert attributes[ATTR_XY_COLOR] == (0.42, 0.336)
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_off", BASE_PAYLOAD, blocking=True LIGHT_DOMAIN, SERVICE_TURN_OFF, BASE_PAYLOAD, blocking=True
) )
light.set_state.assert_called_once_with( light.set_state.assert_called_once_with(
LightState(light_on=False, transition=KASA_TRANSITION_VALUE) LightState(light_on=False, transition=expected_transition)
) )
light.set_state.reset_mock() light.set_state.reset_mock()
await hass.services.async_call(LIGHT_DOMAIN, "turn_on", BASE_PAYLOAD, blocking=True) await hass.services.async_call(
LIGHT_DOMAIN, SERVICE_TURN_ON, BASE_PAYLOAD, blocking=True
)
light.set_state.assert_called_once_with( light.set_state.assert_called_once_with(
LightState(light_on=True, transition=KASA_TRANSITION_VALUE) LightState(light_on=True, transition=expected_transition)
) )
light.set_state.reset_mock() light.set_state.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{**BASE_PAYLOAD, ATTR_BRIGHTNESS: 100}, {**BASE_PAYLOAD, ATTR_BRIGHTNESS: 100},
blocking=True, blocking=True,
) )
light.set_brightness.assert_called_with(39, transition=KASA_TRANSITION_VALUE) light.set_brightness.assert_called_with(39, transition=expected_transition)
light.set_brightness.reset_mock() light.set_brightness.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{**BASE_PAYLOAD, ATTR_COLOR_TEMP_KELVIN: 6666}, {**BASE_PAYLOAD, ATTR_COLOR_TEMP_KELVIN: 6666},
blocking=True, blocking=True,
) )
light.set_color_temp.assert_called_with( light.set_color_temp.assert_called_with(
6666, brightness=None, transition=KASA_TRANSITION_VALUE 6666, brightness=None, transition=expected_transition
) )
light.set_color_temp.reset_mock() light.set_color_temp.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{**BASE_PAYLOAD, ATTR_COLOR_TEMP_KELVIN: 6666}, {**BASE_PAYLOAD, ATTR_COLOR_TEMP_KELVIN: 6666},
blocking=True, blocking=True,
) )
light.set_color_temp.assert_called_with( light.set_color_temp.assert_called_with(
6666, brightness=None, transition=KASA_TRANSITION_VALUE 6666, brightness=None, transition=expected_transition
) )
light.set_color_temp.reset_mock() light.set_color_temp.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{**BASE_PAYLOAD, ATTR_HS_COLOR: (10, 30)}, {**BASE_PAYLOAD, ATTR_HS_COLOR: (10, 30)},
blocking=True, blocking=True,
) )
light.set_hsv.assert_called_with(10, 30, None, transition=KASA_TRANSITION_VALUE) light.set_hsv.assert_called_with(10, 30, None, transition=expected_transition)
light.set_hsv.reset_mock() light.set_hsv.reset_mock()
async def test_color_light_no_temp(hass: HomeAssistant) -> None: async def test_color_light_no_temp(hass: HomeAssistant) -> None:
"""Test a light.""" """Test a color light with no color temp."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -263,7 +399,7 @@ async def test_color_light_no_temp(hass: HomeAssistant) -> None:
type(light).color_temp = PropertyMock(side_effect=Exception) type(light).color_temp = PropertyMock(side_effect=Exception)
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -279,20 +415,20 @@ async def test_color_light_no_temp(hass: HomeAssistant) -> None:
assert attributes[ATTR_XY_COLOR] == (0.42, 0.336) assert attributes[ATTR_XY_COLOR] == (0.42, 0.336)
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
light.set_state.assert_called_once() light.set_state.assert_called_once()
light.set_state.reset_mock() light.set_state.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
light.set_state.assert_called_once() light.set_state.assert_called_once()
light.set_state.reset_mock() light.set_state.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100}, {ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100},
blocking=True, blocking=True,
) )
@ -301,7 +437,7 @@ async def test_color_light_no_temp(hass: HomeAssistant) -> None:
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_HS_COLOR: (10, 30)}, {ATTR_ENTITY_ID: entity_id, ATTR_HS_COLOR: (10, 30)},
blocking=True, blocking=True,
) )
@ -309,51 +445,28 @@ async def test_color_light_no_temp(hass: HomeAssistant) -> None:
light.set_hsv.reset_mock() light.set_hsv.reset_mock()
@pytest.mark.parametrize( async def test_color_temp_light_color(hass: HomeAssistant) -> None:
("device", "is_color"), """Test a color temp light with color."""
[ device = _mocked_device(
( modules=[Module.Light],
_mocked_device( alias="my_light",
modules=[Module.Light], features=[
alias="my_light", _mocked_feature("brightness", value=50),
features=[ _mocked_feature("hsv", value=(10, 30, 5)),
_mocked_feature("brightness", value=50), _mocked_feature(
_mocked_feature("hsv", value=(10, 30, 5)), "color_temp", value=4000, minimum_value=4000, maximum_value=9000
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
],
), ),
True, ],
), )
(
_mocked_device(
modules=[Module.Light],
alias="my_light",
features=[
_mocked_feature("brightness", value=50),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
],
),
False,
),
],
)
async def test_color_temp_light(
hass: HomeAssistant, device: MagicMock, is_color: bool
) -> None:
"""Test a light."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
# device = _mocked_device(modules=[Module.Light], alias="my_light")
light = device.modules[Module.Light] light = device.modules[Module.Light]
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -363,29 +476,24 @@ async def test_color_temp_light(
attributes = state.attributes attributes = state.attributes
assert attributes[ATTR_BRIGHTNESS] == 128 assert attributes[ATTR_BRIGHTNESS] == 128
assert attributes[ATTR_COLOR_MODE] == "color_temp" assert attributes[ATTR_COLOR_MODE] == "color_temp"
if is_color:
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp", "hs"] assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp", "hs"]
else:
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp"]
assert attributes[ATTR_MAX_COLOR_TEMP_KELVIN] == 9000
assert attributes[ATTR_MIN_COLOR_TEMP_KELVIN] == 4000
assert attributes[ATTR_COLOR_TEMP_KELVIN] == 4000
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
light.set_state.assert_called_once() light.set_state.assert_called_once()
light.set_state.reset_mock() light.set_state.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
light.set_state.assert_called_once() light.set_state.assert_called_once()
light.set_state.reset_mock() light.set_state.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100}, {ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100},
blocking=True, blocking=True,
) )
@ -394,7 +502,7 @@ async def test_color_temp_light(
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 6666}, {ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 6666},
blocking=True, blocking=True,
) )
@ -404,7 +512,7 @@ async def test_color_temp_light(
# Verify color temp is clamped to the valid range # Verify color temp is clamped to the valid range
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 20000}, {ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 20000},
blocking=True, blocking=True,
) )
@ -414,7 +522,94 @@ async def test_color_temp_light(
# Verify color temp is clamped to the valid range # Verify color temp is clamped to the valid range
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 1},
blocking=True,
)
light.set_color_temp.assert_called_with(4000, brightness=None, transition=None)
light.set_color_temp.reset_mock()
async def test_color_temp_light_no_color(hass: HomeAssistant) -> None:
"""Test a color temp light with no color."""
device = _mocked_device(
modules=[Module.Light],
alias="my_light",
features=[
_mocked_feature("brightness", value=50),
_mocked_feature(
"color_temp", value=4000, minimum_value=4000, maximum_value=9000
),
],
)
already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
)
already_migrated_config_entry.add_to_hass(hass)
light = device.modules[Module.Light]
with _patch_discovery(device=device), _patch_connect(device=device):
await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done()
entity_id = "light.my_light"
state = hass.states.get(entity_id)
assert state.state == "on"
attributes = state.attributes
assert attributes[ATTR_BRIGHTNESS] == 128
assert attributes[ATTR_COLOR_MODE] == "color_temp"
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["color_temp"]
assert attributes[ATTR_MAX_COLOR_TEMP_KELVIN] == 9000
assert attributes[ATTR_MIN_COLOR_TEMP_KELVIN] == 4000
assert attributes[ATTR_COLOR_TEMP_KELVIN] == 4000
await hass.services.async_call(
LIGHT_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
)
light.set_state.assert_called_once()
light.set_state.reset_mock()
await hass.services.async_call(
LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
)
light.set_state.assert_called_once()
light.set_state.reset_mock()
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100},
blocking=True,
)
light.set_brightness.assert_called_with(39, transition=None)
light.set_brightness.reset_mock()
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 6666},
blocking=True,
)
light.set_color_temp.assert_called_with(6666, brightness=None, transition=None)
light.set_color_temp.reset_mock()
# Verify color temp is clamped to the valid range
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 20000},
blocking=True,
)
light.set_color_temp.assert_called_with(9000, brightness=None, transition=None)
light.set_color_temp.reset_mock()
# Verify color temp is clamped to the valid range
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 1}, {ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 1},
blocking=True, blocking=True,
) )
@ -423,7 +618,7 @@ async def test_color_temp_light(
async def test_brightness_only_light(hass: HomeAssistant) -> None: async def test_brightness_only_light(hass: HomeAssistant) -> None:
"""Test a light.""" """Test a light brightness."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -435,7 +630,7 @@ async def test_brightness_only_light(hass: HomeAssistant) -> None:
light = device.modules[Module.Light] light = device.modules[Module.Light]
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -448,20 +643,20 @@ async def test_brightness_only_light(hass: HomeAssistant) -> None:
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["brightness"] assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["brightness"]
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
light.set_state.assert_called_once() light.set_state.assert_called_once()
light.set_state.reset_mock() light.set_state.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
light.set_state.assert_called_once() light.set_state.assert_called_once()
light.set_state.reset_mock() light.set_state.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100}, {ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100},
blocking=True, blocking=True,
) )
@ -470,7 +665,7 @@ async def test_brightness_only_light(hass: HomeAssistant) -> None:
async def test_on_off_light(hass: HomeAssistant) -> None: async def test_on_off_light(hass: HomeAssistant) -> None:
"""Test a light.""" """Test a light turns on and off."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -479,7 +674,7 @@ async def test_on_off_light(hass: HomeAssistant) -> None:
light = device.modules[Module.Light] light = device.modules[Module.Light]
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -490,20 +685,20 @@ async def test_on_off_light(hass: HomeAssistant) -> None:
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["onoff"] assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["onoff"]
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
light.set_state.assert_called_once() light.set_state.assert_called_once()
light.set_state.reset_mock() light.set_state.reset_mock()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
light.set_state.assert_called_once() light.set_state.assert_called_once()
light.set_state.reset_mock() light.set_state.reset_mock()
async def test_off_at_start_light(hass: HomeAssistant) -> None: async def test_off_at_start_light(hass: HomeAssistant) -> None:
"""Test a light.""" """Test a light off at startup."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -514,7 +709,7 @@ async def test_off_at_start_light(hass: HomeAssistant) -> None:
light.state = LightState(light_on=False) light.state = LightState(light_on=False)
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -526,7 +721,7 @@ async def test_off_at_start_light(hass: HomeAssistant) -> None:
async def test_dimmer_turn_on_fix(hass: HomeAssistant) -> None: async def test_dimmer_turn_on_fix(hass: HomeAssistant) -> None:
"""Test a light.""" """Test a dimmer turns on without brightness being set."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -537,7 +732,7 @@ async def test_dimmer_turn_on_fix(hass: HomeAssistant) -> None:
light.state = LightState(light_on=False) light.state = LightState(light_on=False)
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -546,7 +741,7 @@ async def test_dimmer_turn_on_fix(hass: HomeAssistant) -> None:
assert state.state == "off" assert state.state == "off"
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
light.set_state.assert_called_once_with( light.set_state.assert_called_once_with(
LightState( LightState(
@ -587,7 +782,7 @@ async def test_smart_strip_effects(
_patch_single_discovery(device=device), _patch_single_discovery(device=device),
_patch_connect(device=device), _patch_connect(device=device),
): ):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -601,7 +796,7 @@ async def test_smart_strip_effects(
# is in progress calls set_effect to clear the effect # is in progress calls set_effect to clear the effect
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 4000}, {ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 4000},
blocking=True, blocking=True,
) )
@ -612,7 +807,7 @@ async def test_smart_strip_effects(
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "Effect2"}, {ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "Effect2"},
blocking=True, blocking=True,
) )
@ -629,7 +824,7 @@ async def test_smart_strip_effects(
# Test setting light effect off # Test setting light effect off
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "off"}, {ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "off"},
blocking=True, blocking=True,
) )
@ -644,7 +839,7 @@ async def test_smart_strip_effects(
caplog.clear() caplog.clear()
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "Effect3"}, {ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "Effect3"},
blocking=True, blocking=True,
) )
@ -673,7 +868,7 @@ async def test_smart_strip_effects(
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id}, {ATTR_ENTITY_ID: entity_id},
blocking=True, blocking=True,
) )
@ -703,7 +898,7 @@ async def test_smart_strip_custom_random_effect(hass: HomeAssistant) -> None:
light_effect = device.modules[Module.LightEffect] light_effect = device.modules[Module.LightEffect]
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -713,7 +908,7 @@ async def test_smart_strip_custom_random_effect(hass: HomeAssistant) -> None:
await hass.services.async_call( await hass.services.async_call(
DOMAIN, DOMAIN,
"random_effect", SERVICE_RANDOM_EFFECT,
{ {
ATTR_ENTITY_ID: entity_id, ATTR_ENTITY_ID: entity_id,
"init_states": [340, 20, 50], "init_states": [340, 20, 50],
@ -742,7 +937,7 @@ async def test_smart_strip_custom_random_effect(hass: HomeAssistant) -> None:
await hass.services.async_call( await hass.services.async_call(
DOMAIN, DOMAIN,
"random_effect", SERVICE_RANDOM_EFFECT,
{ {
ATTR_ENTITY_ID: entity_id, ATTR_ENTITY_ID: entity_id,
"init_states": [340, 20, 50], "init_states": [340, 20, 50],
@ -792,7 +987,7 @@ async def test_smart_strip_custom_random_effect(hass: HomeAssistant) -> None:
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id}, {ATTR_ENTITY_ID: entity_id},
blocking=True, blocking=True,
) )
@ -801,7 +996,7 @@ async def test_smart_strip_custom_random_effect(hass: HomeAssistant) -> None:
await hass.services.async_call( await hass.services.async_call(
DOMAIN, DOMAIN,
"random_effect", SERVICE_RANDOM_EFFECT,
{ {
ATTR_ENTITY_ID: entity_id, ATTR_ENTITY_ID: entity_id,
"init_states": [340, 20, 50], "init_states": [340, 20, 50],
@ -875,7 +1070,7 @@ async def test_smart_strip_effect_service_error(
service_params: dict, service_params: dict,
expected_extra_params: dict, expected_extra_params: dict,
) -> None: ) -> None:
"""Test smart strip custom random effects.""" """Test smart strip effect service errors."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -886,7 +1081,7 @@ async def test_smart_strip_effect_service_error(
light_effect = device.modules[Module.LightEffect] light_effect = device.modules[Module.LightEffect]
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -935,7 +1130,7 @@ async def test_smart_strip_custom_random_effect_at_start(hass: HomeAssistant) ->
light_effect = device.modules[Module.LightEffect] light_effect = device.modules[Module.LightEffect]
light_effect.effect = LightEffect.LIGHT_EFFECTS_OFF light_effect.effect = LightEffect.LIGHT_EFFECTS_OFF
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -945,7 +1140,7 @@ async def test_smart_strip_custom_random_effect_at_start(hass: HomeAssistant) ->
# fallback to set HSV when custom effect is not known so it does turn back on # fallback to set HSV when custom effect is not known so it does turn back on
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity_id}, {ATTR_ENTITY_ID: entity_id},
blocking=True, blocking=True,
) )
@ -965,7 +1160,7 @@ async def test_smart_strip_custom_sequence_effect(hass: HomeAssistant) -> None:
light_effect = device.modules[Module.LightEffect] light_effect = device.modules[Module.LightEffect]
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -975,7 +1170,7 @@ async def test_smart_strip_custom_sequence_effect(hass: HomeAssistant) -> None:
await hass.services.async_call( await hass.services.async_call(
DOMAIN, DOMAIN,
"sequence_effect", SERVICE_SEQUENCE_EFFECT,
{ {
ATTR_ENTITY_ID: entity_id, ATTR_ENTITY_ID: entity_id,
"sequence": [[340, 20, 50], [20, 50, 50], [0, 100, 50]], "sequence": [[340, 20, 50], [20, 50, 50], [0, 100, 50]],
@ -1040,7 +1235,7 @@ async def test_light_errors_when_turned_on(
light.set_state.side_effect = exception_type(msg) light.set_state.side_effect = exception_type(msg)
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
@ -1051,7 +1246,7 @@ async def test_light_errors_when_turned_on(
with pytest.raises(HomeAssistantError, match=msg): with pytest.raises(HomeAssistantError, match=msg):
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert light.set_state.call_count == 1 assert light.set_state.call_count == 1
@ -1091,7 +1286,7 @@ async def test_light_child(
) )
with _patch_discovery(device=parent_device), _patch_connect(device=parent_device): with _patch_discovery(device=parent_device), _patch_connect(device=parent_device):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_device" entity_id = "light.my_device"
@ -1132,14 +1327,16 @@ async def test_scene_effect_light(
light_effect.effect = LightEffect.LIGHT_EFFECTS_OFF light_effect.effect = LightEffect.LIGHT_EFFECTS_OFF
with _patch_discovery(device=device), _patch_connect(device=device): with _patch_discovery(device=device), _patch_connect(device=device):
assert await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) assert await hass.config_entries.async_setup(
assert await async_setup_component(hass, "scene", {}) already_migrated_config_entry.entry_id
)
assert await async_setup_component(hass, SCENE_DOMAIN, {})
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "light.my_light" entity_id = "light.my_light"
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
await hass.async_block_till_done() await hass.async_block_till_done()
freezer.tick(5) freezer.tick(5)
@ -1151,9 +1348,9 @@ async def test_scene_effect_light(
assert state.attributes["effect"] is EFFECT_OFF assert state.attributes["effect"] is EFFECT_OFF
await hass.services.async_call( await hass.services.async_call(
"scene", SCENE_DOMAIN,
"create", SERVICE_CREATE,
{"scene_id": "effect_off_scene", "snapshot_entities": [entity_id]}, {CONF_SCENE_ID: "effect_off_scene", CONF_SNAPSHOT: [entity_id]},
blocking=True, blocking=True,
) )
await hass.async_block_till_done() await hass.async_block_till_done()
@ -1161,7 +1358,7 @@ async def test_scene_effect_light(
assert scene_state.state is STATE_UNKNOWN assert scene_state.state is STATE_UNKNOWN
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True LIGHT_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
await hass.async_block_till_done() await hass.async_block_till_done()
freezer.tick(5) freezer.tick(5)
@ -1172,10 +1369,10 @@ async def test_scene_effect_light(
assert state.state is STATE_OFF assert state.state is STATE_OFF
await hass.services.async_call( await hass.services.async_call(
"scene", SCENE_DOMAIN,
"turn_on", SERVICE_TURN_ON,
{ {
"entity_id": "scene.effect_off_scene", ATTR_ENTITY_ID: "scene.effect_off_scene",
}, },
blocking=True, blocking=True,
) )

View File

@ -3,7 +3,6 @@
from kasa import Feature from kasa import Feature
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
from homeassistant.components import tplink
from homeassistant.components.number import ( from homeassistant.components.number import (
ATTR_VALUE, ATTR_VALUE,
DOMAIN as NUMBER_DOMAIN, DOMAIN as NUMBER_DOMAIN,
@ -15,11 +14,8 @@ from homeassistant.components.tplink.number import NUMBER_DESCRIPTIONS
from homeassistant.const import ATTR_ENTITY_ID, CONF_HOST, Platform from homeassistant.const import ATTR_ENTITY_ID, CONF_HOST, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from . import ( from . import (
DEVICE_ID,
MAC_ADDRESS,
_mocked_device, _mocked_device,
_mocked_feature, _mocked_feature,
_mocked_strip_children, _mocked_strip_children,
@ -28,6 +24,7 @@ from . import (
setup_platform_for_device, setup_platform_for_device,
snapshot_platform, snapshot_platform,
) )
from .const import DEVICE_ID, MAC_ADDRESS
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -39,7 +36,7 @@ async def test_states(
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test a number states."""
features = {description.key for description in NUMBER_DESCRIPTIONS} features = {description.key for description in NUMBER_DESCRIPTIONS}
features.update(EXCLUDED_FEATURES) features.update(EXCLUDED_FEATURES)
device = _mocked_device(alias="my_device", features=features) device = _mocked_device(alias="my_device", features=features)
@ -54,7 +51,7 @@ async def test_states(
async def test_number(hass: HomeAssistant, entity_registry: er.EntityRegistry) -> None: async def test_number(hass: HomeAssistant, entity_registry: er.EntityRegistry) -> None:
"""Test a sensor unique ids.""" """Test number unique ids."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -70,7 +67,7 @@ async def test_number(hass: HomeAssistant, entity_registry: er.EntityRegistry) -
) )
plug = _mocked_device(alias="my_plug", features=[new_feature]) plug = _mocked_device(alias="my_plug", features=[new_feature])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "number.my_plug_temperature_offset" entity_id = "number.my_plug_temperature_offset"
@ -84,7 +81,7 @@ async def test_number_children(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test number children."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -104,7 +101,7 @@ async def test_number_children(
children=_mocked_strip_children(features=[new_feature]), children=_mocked_strip_children(features=[new_feature]),
) )
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "number.my_plug_temperature_offset" entity_id = "number.my_plug_temperature_offset"
@ -142,7 +139,7 @@ async def test_number_set(
) )
plug = _mocked_device(alias="my_plug", features=[new_feature]) plug = _mocked_device(alias="my_plug", features=[new_feature])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "number.my_plug_temperature_offset" entity_id = "number.my_plug_temperature_offset"

View File

@ -4,7 +4,6 @@ from kasa import Feature
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
from homeassistant.components import tplink
from homeassistant.components.select import ( from homeassistant.components.select import (
ATTR_OPTION, ATTR_OPTION,
DOMAIN as SELECT_DOMAIN, DOMAIN as SELECT_DOMAIN,
@ -16,11 +15,8 @@ from homeassistant.components.tplink.select import SELECT_DESCRIPTIONS
from homeassistant.const import ATTR_ENTITY_ID, CONF_HOST, Platform from homeassistant.const import ATTR_ENTITY_ID, CONF_HOST, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from . import ( from . import (
DEVICE_ID,
MAC_ADDRESS,
_mocked_device, _mocked_device,
_mocked_feature, _mocked_feature,
_mocked_strip_children, _mocked_strip_children,
@ -29,13 +25,14 @@ from . import (
setup_platform_for_device, setup_platform_for_device,
snapshot_platform, snapshot_platform,
) )
from .const import DEVICE_ID, MAC_ADDRESS
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@pytest.fixture @pytest.fixture
def mocked_feature_select() -> Feature: def mocked_feature_select() -> Feature:
"""Return mocked tplink binary sensor feature.""" """Return mocked tplink select feature."""
return _mocked_feature( return _mocked_feature(
"light_preset", "light_preset",
value="First choice", value="First choice",
@ -53,7 +50,7 @@ async def test_states(
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test select states."""
features = {description.key for description in SELECT_DESCRIPTIONS} features = {description.key for description in SELECT_DESCRIPTIONS}
features.update(EXCLUDED_FEATURES) features.update(EXCLUDED_FEATURES)
device = _mocked_device(alias="my_device", features=features) device = _mocked_device(alias="my_device", features=features)
@ -72,7 +69,7 @@ async def test_select(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
mocked_feature_select: Feature, mocked_feature_select: Feature,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test select unique ids."""
mocked_feature = mocked_feature_select mocked_feature = mocked_feature_select
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
@ -81,7 +78,7 @@ async def test_select(
plug = _mocked_device(alias="my_plug", features=[mocked_feature]) plug = _mocked_device(alias="my_plug", features=[mocked_feature])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
# The entity_id is based on standard name from core. # The entity_id is based on standard name from core.
@ -97,7 +94,7 @@ async def test_select_children(
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
mocked_feature_select: Feature, mocked_feature_select: Feature,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test select children."""
mocked_feature = mocked_feature_select mocked_feature = mocked_feature_select
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
@ -109,7 +106,7 @@ async def test_select_children(
children=_mocked_strip_children(features=[mocked_feature]), children=_mocked_strip_children(features=[mocked_feature]),
) )
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "select.my_plug_light_preset" entity_id = "select.my_plug_light_preset"
@ -141,7 +138,7 @@ async def test_select_select(
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
plug = _mocked_device(alias="my_plug", features=[mocked_feature]) plug = _mocked_device(alias="my_plug", features=[mocked_feature])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "select.my_plug_light_preset" entity_id = "select.my_plug_light_preset"

View File

@ -4,18 +4,14 @@ from kasa import Device, Feature, Module
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
from homeassistant.components import tplink
from homeassistant.components.tplink.const import DOMAIN from homeassistant.components.tplink.const import DOMAIN
from homeassistant.components.tplink.entity import EXCLUDED_FEATURES from homeassistant.components.tplink.entity import EXCLUDED_FEATURES
from homeassistant.components.tplink.sensor import SENSOR_DESCRIPTIONS from homeassistant.components.tplink.sensor import SENSOR_DESCRIPTIONS
from homeassistant.const import CONF_HOST, Platform from homeassistant.const import CONF_HOST, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from . import ( from . import (
DEVICE_ID,
MAC_ADDRESS,
_mocked_device, _mocked_device,
_mocked_energy_features, _mocked_energy_features,
_mocked_feature, _mocked_feature,
@ -25,6 +21,7 @@ from . import (
setup_platform_for_device, setup_platform_for_device,
snapshot_platform, snapshot_platform,
) )
from .const import DEVICE_ID, MAC_ADDRESS
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -36,7 +33,7 @@ async def test_states(
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test a sensor states."""
features = {description.key for description in SENSOR_DESCRIPTIONS} features = {description.key for description in SENSOR_DESCRIPTIONS}
features.update(EXCLUDED_FEATURES) features.update(EXCLUDED_FEATURES)
device = _mocked_device(alias="my_device", features=features) device = _mocked_device(alias="my_device", features=features)
@ -67,7 +64,7 @@ async def test_color_light_with_an_emeter(hass: HomeAssistant) -> None:
alias="my_bulb", modules=[Module.Light], features=["state", *emeter_features] alias="my_bulb", modules=[Module.Light], features=["state", *emeter_features]
) )
with _patch_discovery(device=bulb), _patch_connect(device=bulb): with _patch_discovery(device=bulb), _patch_connect(device=bulb):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() await hass.async_block_till_done()
@ -104,7 +101,7 @@ async def test_plug_with_an_emeter(hass: HomeAssistant) -> None:
) )
plug = _mocked_device(alias="my_plug", features=["state", *emeter_features]) plug = _mocked_device(alias="my_plug", features=["state", *emeter_features])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() await hass.async_block_till_done()
@ -131,7 +128,7 @@ async def test_color_light_no_emeter(hass: HomeAssistant) -> None:
bulb = _mocked_device(alias="my_bulb", modules=[Module.Light]) bulb = _mocked_device(alias="my_bulb", modules=[Module.Light])
with _patch_discovery(device=bulb), _patch_connect(device=bulb): with _patch_discovery(device=bulb), _patch_connect(device=bulb):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() await hass.async_block_till_done()
@ -167,7 +164,7 @@ async def test_sensor_unique_id(
) )
plug = _mocked_device(alias="my_plug", features=emeter_features) plug = _mocked_device(alias="my_plug", features=emeter_features)
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
expected = { expected = {
@ -202,7 +199,7 @@ async def test_undefined_sensor(
) )
plug = _mocked_device(alias="my_plug", features=[new_feature]) plug = _mocked_device(alias="my_plug", features=[new_feature])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
msg = ( msg = (
@ -240,7 +237,7 @@ async def test_sensor_children_on_parent(
device_type=Device.Type.WallSwitch, device_type=Device.Type.WallSwitch,
) )
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "sensor.my_plug_this_month_s_consumption" entity_id = "sensor.my_plug_this_month_s_consumption"
@ -288,7 +285,7 @@ async def test_sensor_children_on_child(
device_type=Device.Type.Strip, device_type=Device.Type.Strip,
) )
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "sensor.my_plug_this_month_s_consumption" entity_id = "sensor.my_plug_this_month_s_consumption"
@ -308,19 +305,18 @@ async def test_sensor_children_on_child(
assert child_device.via_device_id == device.id assert child_device.via_device_id == device.id
@pytest.mark.skip @pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_new_datetime_sensor( async def test_datetime_sensor(
hass: HomeAssistant, entity_registry: er.EntityRegistry hass: HomeAssistant, entity_registry: er.EntityRegistry
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test a timestamp sensor."""
# Skipped temporarily while datetime handling on hold.
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
plug = _mocked_device(alias="my_plug", features=["on_since"]) plug = _mocked_device(alias="my_plug", features=["on_since"])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "sensor.my_plug_on_since" entity_id = "sensor.my_plug_on_since"

View File

@ -9,7 +9,11 @@ import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
from homeassistant.components import tplink from homeassistant.components import tplink
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN from homeassistant.components.switch import (
DOMAIN as SWITCH_DOMAIN,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
)
from homeassistant.components.tplink.const import DOMAIN from homeassistant.components.tplink.const import DOMAIN
from homeassistant.components.tplink.entity import EXCLUDED_FEATURES from homeassistant.components.tplink.entity import EXCLUDED_FEATURES
from homeassistant.components.tplink.switch import SWITCH_DESCRIPTIONS from homeassistant.components.tplink.switch import SWITCH_DESCRIPTIONS
@ -25,12 +29,9 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util, slugify from homeassistant.util import dt as dt_util, slugify
from . import ( from . import (
DEVICE_ID,
MAC_ADDRESS,
_mocked_device, _mocked_device,
_mocked_strip_children, _mocked_strip_children,
_patch_connect, _patch_connect,
@ -38,6 +39,7 @@ from . import (
setup_platform_for_device, setup_platform_for_device,
snapshot_platform, snapshot_platform,
) )
from .const import DEVICE_ID, MAC_ADDRESS
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
@ -49,7 +51,7 @@ async def test_states(
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test a sensor unique ids.""" """Test a switch states."""
features = {description.key for description in SWITCH_DESCRIPTIONS} features = {description.key for description in SWITCH_DESCRIPTIONS}
features.update(EXCLUDED_FEATURES) features.update(EXCLUDED_FEATURES)
device = _mocked_device(alias="my_device", features=features) device = _mocked_device(alias="my_device", features=features)
@ -72,7 +74,7 @@ async def test_plug(hass: HomeAssistant) -> None:
plug = _mocked_device(alias="my_plug", features=["state"]) plug = _mocked_device(alias="my_plug", features=["state"])
feat = plug.features["state"] feat = plug.features["state"]
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "switch.my_plug" entity_id = "switch.my_plug"
@ -80,13 +82,13 @@ async def test_plug(hass: HomeAssistant) -> None:
assert state.state == STATE_ON assert state.state == STATE_ON
await hass.services.async_call( await hass.services.async_call(
SWITCH_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True SWITCH_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
feat.set_value.assert_called_once() feat.set_value.assert_called_once()
feat.set_value.reset_mock() feat.set_value.reset_mock()
await hass.services.async_call( await hass.services.async_call(
SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
feat.set_value.assert_called_once() feat.set_value.assert_called_once()
feat.set_value.reset_mock() feat.set_value.reset_mock()
@ -120,7 +122,7 @@ async def test_led_switch(hass: HomeAssistant, dev: Device, domain: str) -> None
feat = dev.features["led"] feat = dev.features["led"]
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
with _patch_discovery(device=dev), _patch_connect(device=dev): with _patch_discovery(device=dev), _patch_connect(device=dev):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_name = slugify(dev.alias) entity_name = slugify(dev.alias)
@ -131,13 +133,13 @@ async def test_led_switch(hass: HomeAssistant, dev: Device, domain: str) -> None
assert led_state.name == f"{dev.alias} LED" assert led_state.name == f"{dev.alias} LED"
await hass.services.async_call( await hass.services.async_call(
SWITCH_DOMAIN, "turn_off", {ATTR_ENTITY_ID: led_entity_id}, blocking=True SWITCH_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: led_entity_id}, blocking=True
) )
feat.set_value.assert_called_once_with(False) feat.set_value.assert_called_once_with(False)
feat.set_value.reset_mock() feat.set_value.reset_mock()
await hass.services.async_call( await hass.services.async_call(
SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: led_entity_id}, blocking=True SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: led_entity_id}, blocking=True
) )
feat.set_value.assert_called_once_with(True) feat.set_value.assert_called_once_with(True)
feat.set_value.reset_mock() feat.set_value.reset_mock()
@ -153,7 +155,7 @@ async def test_plug_unique_id(
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
plug = _mocked_device(alias="my_plug", features=["state", "led"]) plug = _mocked_device(alias="my_plug", features=["state", "led"])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "switch.my_plug" entity_id = "switch.my_plug"
@ -168,7 +170,7 @@ async def test_plug_update_fails(hass: HomeAssistant) -> None:
already_migrated_config_entry.add_to_hass(hass) already_migrated_config_entry.add_to_hass(hass)
plug = _mocked_device(alias="my_plug", features=["state", "led"]) plug = _mocked_device(alias="my_plug", features=["state", "led"])
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "switch.my_plug" entity_id = "switch.my_plug"
@ -197,7 +199,7 @@ async def test_strip(hass: HomeAssistant) -> None:
strip.children[0].features["state"].value = True strip.children[0].features["state"].value = True
strip.children[1].features["state"].value = False strip.children[1].features["state"].value = False
with _patch_discovery(device=strip), _patch_connect(device=strip): with _patch_discovery(device=strip), _patch_connect(device=strip):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "switch.my_strip_plug0" entity_id = "switch.my_strip_plug0"
@ -205,14 +207,14 @@ async def test_strip(hass: HomeAssistant) -> None:
assert state.state == STATE_ON assert state.state == STATE_ON
await hass.services.async_call( await hass.services.async_call(
SWITCH_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True SWITCH_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
feat = strip.children[0].features["state"] feat = strip.children[0].features["state"]
feat.set_value.assert_called_once() feat.set_value.assert_called_once()
feat.set_value.reset_mock() feat.set_value.reset_mock()
await hass.services.async_call( await hass.services.async_call(
SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
feat.set_value.assert_called_once() feat.set_value.assert_called_once()
feat.set_value.reset_mock() feat.set_value.reset_mock()
@ -222,14 +224,14 @@ async def test_strip(hass: HomeAssistant) -> None:
assert state.state == STATE_OFF assert state.state == STATE_OFF
await hass.services.async_call( await hass.services.async_call(
SWITCH_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True SWITCH_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
feat = strip.children[1].features["state"] feat = strip.children[1].features["state"]
feat.set_value.assert_called_once() feat.set_value.assert_called_once()
feat.set_value.reset_mock() feat.set_value.reset_mock()
await hass.services.async_call( await hass.services.async_call(
SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
feat.set_value.assert_called_once() feat.set_value.assert_called_once()
feat.set_value.reset_mock() feat.set_value.reset_mock()
@ -249,7 +251,7 @@ async def test_strip_unique_ids(
features=["state", "led"], features=["state", "led"],
) )
with _patch_discovery(device=strip), _patch_connect(device=strip): with _patch_discovery(device=strip), _patch_connect(device=strip):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
for plug_id in range(2): for plug_id in range(2):
@ -264,7 +266,7 @@ async def test_strip_blank_alias(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry, device_registry: dr.DeviceRegistry,
) -> None: ) -> None:
"""Test a strip unique id.""" """Test a strip with blank parent alias."""
already_migrated_config_entry = MockConfigEntry( already_migrated_config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
) )
@ -276,7 +278,7 @@ async def test_strip_blank_alias(
features=["state", "led"], features=["state", "led"],
) )
with _patch_discovery(device=strip), _patch_connect(device=strip): with _patch_discovery(device=strip), _patch_connect(device=strip):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
strip_entity_id = "switch.unnamed_ks123" strip_entity_id = "switch.unnamed_ks123"
@ -338,7 +340,7 @@ async def test_plug_errors_when_turned_on(
feat.set_value.side_effect = exception_type("test error") feat.set_value.side_effect = exception_type("test error")
with _patch_discovery(device=plug), _patch_connect(device=plug): with _patch_discovery(device=plug), _patch_connect(device=plug):
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.config_entries.async_setup(already_migrated_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
entity_id = "switch.my_plug" entity_id = "switch.my_plug"
@ -349,7 +351,7 @@ async def test_plug_errors_when_turned_on(
with pytest.raises(HomeAssistantError, match=msg): with pytest.raises(HomeAssistantError, match=msg):
await hass.services.async_call( await hass.services.async_call(
SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert feat.set_value.call_count == 1 assert feat.set_value.call_count == 1