mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Cleanup tplink test framework (#135205)
This commit is contained in:
parent
d986fe7a07
commit
ab28115d2b
@ -6,174 +6,36 @@ from datetime import datetime
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from kasa import (
|
||||
BaseProtocol,
|
||||
Device,
|
||||
DeviceConfig,
|
||||
DeviceConnectionParameters,
|
||||
DeviceEncryptionType,
|
||||
DeviceFamily,
|
||||
DeviceType,
|
||||
Feature,
|
||||
KasaException,
|
||||
Module,
|
||||
)
|
||||
from kasa import BaseProtocol, Device, DeviceType, Feature, KasaException, Module
|
||||
from kasa.interfaces import Fan, Light, LightEffect, LightState
|
||||
from kasa.smart.modules.alarm import Alarm
|
||||
from kasa.smartcam.modules.camera import LOCAL_STREAMING_PORT, Camera
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
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.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.const import CONF_HOST, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.translation import async_get_translations
|
||||
from homeassistant.helpers.typing import UNDEFINED
|
||||
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
|
||||
|
||||
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():
|
||||
fixtures = load_json_value_fixture("features.json", DOMAIN)
|
||||
@ -201,7 +63,7 @@ async def setup_platform_for_device(
|
||||
_patch_discovery(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
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
|
@ -10,7 +10,8 @@ import pytest
|
||||
from homeassistant.components.tplink import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import (
|
||||
from . import _mocked_device
|
||||
from .const import (
|
||||
ALIAS_CAMERA,
|
||||
CREATE_ENTRY_DATA_AES_CAMERA,
|
||||
CREATE_ENTRY_DATA_LEGACY,
|
||||
@ -26,7 +27,6 @@ from . import (
|
||||
MAC_ADDRESS2,
|
||||
MAC_ADDRESS3,
|
||||
MODEL_CAMERA,
|
||||
_mocked_device,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
@ -115,8 +115,12 @@ def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_init() -> Generator[AsyncMock]:
|
||||
"""Override async_setup_entry."""
|
||||
def mock_init() -> Generator[dict[str, AsyncMock]]:
|
||||
"""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(
|
||||
"homeassistant.components.tplink",
|
||||
async_setup=DEFAULT,
|
||||
|
146
tests/components/tplink/const.py
Normal file
146
tests/components/tplink/const.py
Normal 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)
|
@ -4,18 +4,14 @@ from kasa import Feature
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components import tplink
|
||||
from homeassistant.components.tplink.binary_sensor import BINARY_SENSOR_DESCRIPTIONS
|
||||
from homeassistant.components.tplink.const import DOMAIN
|
||||
from homeassistant.components.tplink.entity import EXCLUDED_FEATURES
|
||||
from homeassistant.const import CONF_HOST, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import (
|
||||
DEVICE_ID,
|
||||
MAC_ADDRESS,
|
||||
_mocked_device,
|
||||
_mocked_feature,
|
||||
_mocked_strip_children,
|
||||
@ -24,6 +20,7 @@ from . import (
|
||||
setup_platform_for_device,
|
||||
snapshot_platform,
|
||||
)
|
||||
from .const import DEVICE_ID, MAC_ADDRESS
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -47,7 +44,7 @@ async def test_states(
|
||||
device_registry: dr.DeviceRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test binary sensor states."""
|
||||
features = {description.key for description in BINARY_SENSOR_DESCRIPTIONS}
|
||||
features.update(EXCLUDED_FEATURES)
|
||||
device = _mocked_device(alias="my_device", features=features)
|
||||
@ -68,7 +65,7 @@ async def test_binary_sensor(
|
||||
entity_registry: er.EntityRegistry,
|
||||
mocked_feature_binary_sensor: Feature,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test binary sensor unique ids."""
|
||||
mocked_feature = mocked_feature_binary_sensor
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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])
|
||||
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()
|
||||
|
||||
# The entity_id is based on standard name from core.
|
||||
@ -93,7 +90,7 @@ async def test_binary_sensor_children(
|
||||
device_registry: dr.DeviceRegistry,
|
||||
mocked_feature_binary_sensor: Feature,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test binary sensor children."""
|
||||
mocked_feature = mocked_feature_binary_sensor
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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]),
|
||||
)
|
||||
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()
|
||||
|
||||
entity_id = "binary_sensor.my_plug_overheated"
|
||||
|
@ -4,7 +4,6 @@ from kasa import Feature
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components import tplink
|
||||
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
||||
from homeassistant.components.tplink.button import BUTTON_DESCRIPTIONS
|
||||
from homeassistant.components.tplink.const import DOMAIN
|
||||
@ -16,11 +15,8 @@ from homeassistant.helpers import (
|
||||
entity_registry as er,
|
||||
issue_registry as ir,
|
||||
)
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import (
|
||||
DEVICE_ID,
|
||||
MAC_ADDRESS,
|
||||
_mocked_device,
|
||||
_mocked_feature,
|
||||
_mocked_strip_children,
|
||||
@ -30,6 +26,7 @@ from . import (
|
||||
setup_platform_for_device,
|
||||
snapshot_platform,
|
||||
)
|
||||
from .const import DEVICE_ID, MAC_ADDRESS
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -83,7 +80,7 @@ def create_deprecated_child_button_entities(
|
||||
|
||||
@pytest.fixture
|
||||
def mocked_feature_button() -> Feature:
|
||||
"""Return mocked tplink binary sensor feature."""
|
||||
"""Return mocked tplink button feature."""
|
||||
return _mocked_feature(
|
||||
"test_alarm",
|
||||
value="<Action>",
|
||||
@ -101,7 +98,7 @@ async def test_states(
|
||||
snapshot: SnapshotAssertion,
|
||||
create_deprecated_button_entities,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test button states."""
|
||||
features = {description.key for description in BUTTON_DESCRIPTIONS}
|
||||
features.update(EXCLUDED_FEATURES)
|
||||
device = _mocked_device(alias="my_device", features=features)
|
||||
@ -118,14 +115,15 @@ async def test_states(
|
||||
async def test_button(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mocked_feature_button: Feature,
|
||||
create_deprecated_button_entities,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test button unique ids."""
|
||||
mocked_feature = mocked_feature_button
|
||||
plug = _mocked_device(alias="my_device", features=[mocked_feature])
|
||||
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()
|
||||
|
||||
# The entity_id is based on standard name from core.
|
||||
@ -139,11 +137,12 @@ async def test_button_children(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mocked_feature_button: Feature,
|
||||
create_deprecated_button_entities,
|
||||
create_deprecated_child_button_entities,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test button children."""
|
||||
mocked_feature = mocked_feature_button
|
||||
plug = _mocked_device(
|
||||
alias="my_device",
|
||||
@ -151,7 +150,7 @@ async def test_button_children(
|
||||
children=_mocked_strip_children(features=[mocked_feature]),
|
||||
)
|
||||
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()
|
||||
|
||||
entity_id = "button.my_device_test_alarm"
|
||||
@ -173,6 +172,7 @@ async def test_button_children(
|
||||
async def test_button_press(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mocked_feature_button: Feature,
|
||||
create_deprecated_button_entities,
|
||||
) -> None:
|
||||
@ -180,7 +180,7 @@ async def test_button_press(
|
||||
mocked_feature = mocked_feature_button
|
||||
plug = _mocked_device(alias="my_device", features=[mocked_feature])
|
||||
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()
|
||||
|
||||
entity_id = "button.my_device_test_alarm"
|
||||
@ -213,7 +213,7 @@ async def test_button_not_exists_with_deprecation(
|
||||
mocked_feature = mocked_feature_button
|
||||
dev = _mocked_device(alias="my_device", features=[mocked_feature])
|
||||
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()
|
||||
|
||||
assert not entity_registry.async_get(entity_id)
|
||||
@ -265,7 +265,7 @@ async def test_button_exists_with_deprecation(
|
||||
mocked_feature = mocked_feature_button
|
||||
dev = _mocked_device(alias="my_device", features=[mocked_feature])
|
||||
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()
|
||||
|
||||
entity = entity_registry.async_get(entity_id)
|
||||
|
@ -11,6 +11,9 @@ from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components import stream
|
||||
from homeassistant.components.camera import (
|
||||
DOMAIN as CAMERA_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
CameraEntityFeature,
|
||||
StreamType,
|
||||
async_get_image,
|
||||
@ -23,15 +26,8 @@ from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant, HomeAssistantError
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
|
||||
from . import (
|
||||
DEVICE_ID,
|
||||
IP_ADDRESS3,
|
||||
MAC_ADDRESS3,
|
||||
SMALLEST_VALID_JPEG_BYTES,
|
||||
_mocked_device,
|
||||
setup_platform_for_device,
|
||||
snapshot_platform,
|
||||
)
|
||||
from . import _mocked_device, setup_platform_for_device, snapshot_platform
|
||||
from .const import DEVICE_ID, IP_ADDRESS3, MAC_ADDRESS3, SMALLEST_VALID_JPEG_BYTES
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
from tests.typing import WebSocketGenerator
|
||||
@ -44,7 +40,7 @@ async def test_states(
|
||||
device_registry: dr.DeviceRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test states."""
|
||||
"""Test camera states."""
|
||||
mock_camera_config_entry.add_to_hass(hass)
|
||||
|
||||
mock_device = _mocked_device(
|
||||
@ -73,6 +69,7 @@ async def test_camera_unique_id(
|
||||
hass: HomeAssistant,
|
||||
mock_camera_config_entry: MockConfigEntry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test camera unique id."""
|
||||
mock_device = _mocked_device(
|
||||
@ -92,14 +89,13 @@ async def test_camera_unique_id(
|
||||
)
|
||||
assert device_entries
|
||||
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"
|
||||
|
||||
|
||||
async def test_handle_mjpeg_stream(
|
||||
hass: HomeAssistant,
|
||||
mock_camera_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test handle_async_mjpeg_stream."""
|
||||
mock_device = _mocked_device(
|
||||
@ -126,7 +122,6 @@ async def test_handle_mjpeg_stream(
|
||||
async def test_handle_mjpeg_stream_not_supported(
|
||||
hass: HomeAssistant,
|
||||
mock_camera_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test handle_async_mjpeg_stream."""
|
||||
mock_device = _mocked_device(
|
||||
@ -216,7 +211,7 @@ async def test_no_camera_image_when_streaming(
|
||||
mock_camera_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test async_get_image."""
|
||||
"""Test no camera image when streaming."""
|
||||
mock_device = _mocked_device(
|
||||
modules=[Module.Camera],
|
||||
alias="my_camera",
|
||||
@ -272,9 +267,8 @@ async def test_no_camera_image_when_streaming(
|
||||
async def test_no_concurrent_camera_image(
|
||||
hass: HomeAssistant,
|
||||
mock_camera_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test async_get_image."""
|
||||
"""Test async_get_image doesn't make concurrent requests."""
|
||||
mock_device = _mocked_device(
|
||||
modules=[Module.Camera],
|
||||
alias="my_camera",
|
||||
@ -321,7 +315,7 @@ async def test_camera_image_auth_error(
|
||||
mock_connect: AsyncMock,
|
||||
mock_discovery: AsyncMock,
|
||||
) -> None:
|
||||
"""Test async_get_image."""
|
||||
"""Test async_get_image auth error."""
|
||||
mock_device = _mocked_device(
|
||||
modules=[Module.Camera],
|
||||
alias="my_camera",
|
||||
@ -367,7 +361,7 @@ async def test_camera_stream_source(
|
||||
mock_camera_config_entry: MockConfigEntry,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
) -> None:
|
||||
"""Test async_get_image.
|
||||
"""Test camera stream source.
|
||||
|
||||
This test would fail if the integration didn't properly
|
||||
put stream in the dependencies.
|
||||
@ -444,16 +438,16 @@ async def test_camera_turn_on_off(
|
||||
assert state is not None
|
||||
|
||||
await hass.services.async_call(
|
||||
"camera",
|
||||
"turn_on",
|
||||
CAMERA_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{"entity_id": "camera.my_camera_live_view"},
|
||||
blocking=True,
|
||||
)
|
||||
mock_camera.set_state.assert_called_with(True)
|
||||
|
||||
await hass.services.async_call(
|
||||
"camera",
|
||||
"turn_off",
|
||||
CAMERA_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{"entity_id": "camera.my_camera_live_view"},
|
||||
blocking=True,
|
||||
)
|
||||
|
@ -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 . import (
|
||||
DEVICE_ID,
|
||||
_mocked_device,
|
||||
_mocked_feature,
|
||||
setup_platform_for_device,
|
||||
snapshot_platform,
|
||||
)
|
||||
from .const import DEVICE_ID
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
|
||||
@ -41,7 +41,7 @@ ENTITY_ID = "climate.thermostat"
|
||||
|
||||
@pytest.fixture
|
||||
async def mocked_hub(hass: HomeAssistant) -> Device:
|
||||
"""Return mocked tplink binary sensor feature."""
|
||||
"""Return mocked tplink hub."""
|
||||
|
||||
features = [
|
||||
_mocked_feature(
|
||||
@ -166,7 +166,8 @@ async def test_set_hvac_mode(
|
||||
)
|
||||
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(
|
||||
CLIMATE_DOMAIN,
|
||||
SERVICE_SET_HVAC_MODE,
|
||||
|
@ -37,7 +37,9 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant
|
||||
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,
|
||||
ALIAS,
|
||||
ALIAS_CAMERA,
|
||||
@ -67,12 +69,7 @@ from . import (
|
||||
MODEL_CAMERA,
|
||||
MODULE,
|
||||
SMALLEST_VALID_JPEG_BYTES,
|
||||
_mocked_device,
|
||||
_patch_connect,
|
||||
_patch_discovery,
|
||||
_patch_single_discovery,
|
||||
)
|
||||
from .conftest import override_side_effect
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -168,8 +165,11 @@ async def test_discovery(
|
||||
assert result2["reason"] == "no_devices_found"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_discovery_camera(
|
||||
hass: HomeAssistant, mock_discovery: AsyncMock, mock_connect: AsyncMock, mock_init
|
||||
hass: HomeAssistant,
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
) -> None:
|
||||
"""Test authenticated discovery for camera with stream."""
|
||||
mock_device = _mocked_device(
|
||||
@ -228,8 +228,11 @@ async def test_discovery_camera(
|
||||
assert result["context"]["unique_id"] == MAC_ADDRESS3
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
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:
|
||||
"""Test authenticated discovery for camera with stream."""
|
||||
mock_device = _mocked_device(
|
||||
@ -293,8 +296,11 @@ async def test_discovery_pick_device_camera(
|
||||
assert result["context"]["unique_id"] == MAC_ADDRESS3
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_discovery_auth(
|
||||
hass: HomeAssistant, mock_discovery: AsyncMock, mock_connect: AsyncMock, mock_init
|
||||
hass: HomeAssistant,
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
) -> None:
|
||||
"""Test authenticated discovery."""
|
||||
mock_device = _mocked_device(
|
||||
@ -336,8 +342,11 @@ async def test_discovery_auth(
|
||||
assert result2["context"]["unique_id"] == MAC_ADDRESS
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
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:
|
||||
"""Test authenticated discovery for camera with stream."""
|
||||
mock_device = _mocked_device(
|
||||
@ -407,13 +416,13 @@ async def test_discovery_auth_camera(
|
||||
],
|
||||
ids=["invalid-auth", "unknown-error"],
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_discovery_auth_errors(
|
||||
hass: HomeAssistant,
|
||||
mock_connect: AsyncMock,
|
||||
mock_init,
|
||||
error_type,
|
||||
errors_msg,
|
||||
error_placement,
|
||||
error_type: Exception,
|
||||
errors_msg: str,
|
||||
error_placement: str,
|
||||
) -> None:
|
||||
"""Test handling of discovery authentication errors.
|
||||
|
||||
@ -465,10 +474,10 @@ async def test_discovery_auth_errors(
|
||||
assert result3["context"]["unique_id"] == MAC_ADDRESS
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_discovery_new_credentials(
|
||||
hass: HomeAssistant,
|
||||
mock_connect: AsyncMock,
|
||||
mock_init,
|
||||
) -> None:
|
||||
"""Test setting up discovery with new credentials."""
|
||||
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
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_discovery_new_credentials_invalid(
|
||||
hass: HomeAssistant,
|
||||
mock_connect: AsyncMock,
|
||||
mock_init,
|
||||
) -> None:
|
||||
"""Test setting up discovery with new invalid credentials."""
|
||||
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
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_manual_auth(
|
||||
hass: HomeAssistant,
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
mock_init,
|
||||
) -> None:
|
||||
"""Test manually setup."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -1083,14 +1092,14 @@ async def test_manual_auth_camera(
|
||||
],
|
||||
ids=["invalid-auth", "unknown-error"],
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_manual_auth_errors(
|
||||
hass: HomeAssistant,
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
mock_init,
|
||||
error_type,
|
||||
errors_msg,
|
||||
error_placement,
|
||||
error_type: Exception,
|
||||
errors_msg: str,
|
||||
error_placement: str,
|
||||
) -> None:
|
||||
"""Test manually setup auth errors."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -1150,9 +1159,9 @@ async def test_manual_port_override(
|
||||
hass: HomeAssistant,
|
||||
mock_connect: AsyncMock,
|
||||
mock_discovery: AsyncMock,
|
||||
host_str,
|
||||
host,
|
||||
port,
|
||||
host_str: str,
|
||||
host: str,
|
||||
port: int,
|
||||
) -> None:
|
||||
"""Test manually setup."""
|
||||
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(
|
||||
hass: HomeAssistant, source, data
|
||||
hass: HomeAssistant, source: str, data: dict
|
||||
) -> None:
|
||||
"""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(
|
||||
hass: HomeAssistant, source, data
|
||||
hass: HomeAssistant, source: str, data: dict
|
||||
) -> None:
|
||||
"""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_connect: AsyncMock,
|
||||
) -> None:
|
||||
"""Test reauth flow."""
|
||||
"""Test integration updates ip address from discovery."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
with (
|
||||
patch("homeassistant.components.tplink.Discover.discover", return_value={}),
|
||||
@ -1670,7 +1679,7 @@ async def test_reauth_camera(
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
) -> None:
|
||||
"""Test async_get_image."""
|
||||
"""Test reauth flow on invalid camera credentials."""
|
||||
mock_device = mock_connect["mock_devices"][IP_ADDRESS3]
|
||||
mock_camera_config_entry.add_to_hass(hass)
|
||||
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["try_connect_all"], lambda *_, **__: None),
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
CONF_USERNAME: "fake_username",
|
||||
@ -1774,7 +1783,23 @@ async def test_reauth_try_connect_all_fail(
|
||||
IP_ADDRESS, credentials=credentials, port=None
|
||||
)
|
||||
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(
|
||||
@ -2025,9 +2050,9 @@ async def test_reauth_errors(
|
||||
mock_added_config_entry: MockConfigEntry,
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
error_type,
|
||||
errors_msg,
|
||||
error_placement,
|
||||
error_type: Exception,
|
||||
errors_msg: str,
|
||||
error_placement: str,
|
||||
) -> None:
|
||||
"""Test reauth errors."""
|
||||
mock_added_config_entry.async_start_reauth(hass)
|
||||
@ -2089,8 +2114,8 @@ async def test_pick_device_errors(
|
||||
hass: HomeAssistant,
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
error_type,
|
||||
expected_flow,
|
||||
error_type: type[Exception],
|
||||
expected_flow: FlowResultType,
|
||||
) -> None:
|
||||
"""Test errors on pick_device."""
|
||||
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
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_discovery_timeout_try_connect_all(
|
||||
hass: HomeAssistant,
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
mock_init,
|
||||
) -> None:
|
||||
"""Test discovery tries legacy connect on timeout."""
|
||||
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
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_discovery_timeout_try_connect_all_needs_creds(
|
||||
hass: HomeAssistant,
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
mock_init,
|
||||
) -> None:
|
||||
"""Test discovery tries legacy connect on timeout."""
|
||||
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
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_init")
|
||||
async def test_discovery_timeout_try_connect_all_fail(
|
||||
hass: HomeAssistant,
|
||||
mock_discovery: AsyncMock,
|
||||
mock_connect: AsyncMock,
|
||||
mock_init,
|
||||
) -> None:
|
||||
"""Test discovery tries legacy connect on timeout."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from kasa import Device, Module
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
@ -11,13 +10,15 @@ from homeassistant.components.fan import (
|
||||
ATTR_PERCENTAGE,
|
||||
DOMAIN as FAN_DOMAIN,
|
||||
SERVICE_SET_PERCENTAGE,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
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
|
||||
|
||||
@ -56,6 +57,7 @@ async def test_fan_unique_id(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test a fan unique id."""
|
||||
fan = _mocked_device(modules=[Module.Fan], alias="my_fan")
|
||||
@ -66,12 +68,16 @@ async def test_fan_unique_id(
|
||||
)
|
||||
assert device_entries
|
||||
entity_id = "fan.my_fan"
|
||||
entity_registry = er.async_get(hass)
|
||||
|
||||
assert entity_registry.async_get(entity_id).unique_id == DEVICE_ID
|
||||
|
||||
|
||||
async def test_fan(hass: HomeAssistant, mock_config_entry: MockConfigEntry) -> None:
|
||||
"""Test a color fan and that all transitions are correctly passed."""
|
||||
async def test_fan(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test fan functionality."""
|
||||
device = _mocked_device(modules=[Module.Fan], alias="my_fan")
|
||||
fan = device.modules[Module.Fan]
|
||||
fan.fan_speed_level = 0
|
||||
@ -83,26 +89,29 @@ async def test_fan(hass: HomeAssistant, mock_config_entry: MockConfigEntry) -> N
|
||||
assert state.state == "off"
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
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)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "on"
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_PERCENTAGE: 50},
|
||||
blocking=True,
|
||||
)
|
||||
|
@ -38,6 +38,14 @@ from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import (
|
||||
_mocked_device,
|
||||
_mocked_feature,
|
||||
_patch_connect,
|
||||
_patch_discovery,
|
||||
_patch_single_discovery,
|
||||
)
|
||||
from .conftest import override_side_effect
|
||||
from .const import (
|
||||
ALIAS,
|
||||
CREATE_ENTRY_DATA_AES,
|
||||
CREATE_ENTRY_DATA_KLAP,
|
||||
@ -53,13 +61,7 @@ from . import (
|
||||
IP_ADDRESS,
|
||||
MAC_ADDRESS,
|
||||
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
|
||||
|
||||
@ -98,7 +100,7 @@ async def test_config_entry_reload(hass: HomeAssistant) -> None:
|
||||
)
|
||||
already_migrated_config_entry.add_to_hass(hass)
|
||||
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()
|
||||
assert already_migrated_config_entry.state is ConfigEntryState.LOADED
|
||||
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_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()
|
||||
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)
|
||||
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()
|
||||
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)
|
||||
device = _mocked_device(alias="my_plug", features=["state"])
|
||||
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()
|
||||
|
||||
entity_id = "switch.my_plug"
|
||||
@ -355,7 +357,7 @@ async def test_update_attrs_fails_in_init(
|
||||
type(light_module).color_temp = p
|
||||
light.__str__ = lambda _: "MockLight"
|
||||
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()
|
||||
|
||||
entity_id = "light.my_light"
|
||||
@ -388,7 +390,7 @@ async def test_update_attrs_fails_on_update(
|
||||
light_module = light.modules[Module.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()
|
||||
|
||||
entity_id = "light.my_light"
|
||||
@ -434,7 +436,7 @@ async def test_feature_no_category(
|
||||
)
|
||||
dev.features["led"].category = Feature.Category.Unset
|
||||
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()
|
||||
|
||||
entity_id = "switch.my_plug_led"
|
||||
|
@ -20,6 +20,11 @@ from kasa.iot import IotDevice
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import tplink
|
||||
from homeassistant.components.homeassistant.scene import (
|
||||
CONF_SCENE_ID,
|
||||
CONF_SNAPSHOT,
|
||||
SERVICE_CREATE,
|
||||
)
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_MODE,
|
||||
@ -35,7 +40,10 @@ from homeassistant.components.light import (
|
||||
ATTR_XY_COLOR,
|
||||
DOMAIN as LIGHT_DOMAIN,
|
||||
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.light import (
|
||||
SERVICE_RANDOM_EFFECT,
|
||||
@ -56,14 +64,13 @@ from homeassistant.setup import async_setup_component
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from . import (
|
||||
DEVICE_ID,
|
||||
MAC_ADDRESS,
|
||||
_mocked_device,
|
||||
_mocked_feature,
|
||||
_patch_connect,
|
||||
_patch_discovery,
|
||||
_patch_single_discovery,
|
||||
)
|
||||
from .const import DEVICE_ID, MAC_ADDRESS
|
||||
|
||||
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.device_type = device_type
|
||||
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()
|
||||
|
||||
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:
|
||||
"""Test a light unique id."""
|
||||
async def test_legacy_dimmer_unique_id(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test dimmer unique id."""
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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
|
||||
|
||||
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()
|
||||
|
||||
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"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("device", "transition"),
|
||||
("device", "extra_data", "expected_transition"),
|
||||
[
|
||||
(
|
||||
_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(
|
||||
@ -148,12 +289,16 @@ async def test_legacy_dimmer_unique_id(hass: HomeAssistant) -> None:
|
||||
),
|
||||
],
|
||||
),
|
||||
{},
|
||||
None,
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_color_light(
|
||||
hass: HomeAssistant, device: MagicMock, transition: float | None
|
||||
async def test_color_light_with_active_effect(
|
||||
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(
|
||||
@ -162,93 +307,84 @@ async def test_color_light(
|
||||
already_migrated_config_entry.add_to_hass(hass)
|
||||
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):
|
||||
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()
|
||||
|
||||
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}
|
||||
if transition:
|
||||
BASE_PAYLOAD[ATTR_TRANSITION] = transition
|
||||
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"]
|
||||
|
||||
# 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"
|
||||
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(
|
||||
LIGHT_DOMAIN, "turn_off", BASE_PAYLOAD, blocking=True
|
||||
LIGHT_DOMAIN, SERVICE_TURN_OFF, BASE_PAYLOAD, blocking=True
|
||||
)
|
||||
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()
|
||||
|
||||
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(
|
||||
LightState(light_on=True, transition=KASA_TRANSITION_VALUE)
|
||||
LightState(light_on=True, transition=expected_transition)
|
||||
)
|
||||
light.set_state.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{**BASE_PAYLOAD, ATTR_BRIGHTNESS: 100},
|
||||
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()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{**BASE_PAYLOAD, ATTR_COLOR_TEMP_KELVIN: 6666},
|
||||
blocking=True,
|
||||
)
|
||||
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()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{**BASE_PAYLOAD, ATTR_COLOR_TEMP_KELVIN: 6666},
|
||||
blocking=True,
|
||||
)
|
||||
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()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{**BASE_PAYLOAD, ATTR_HS_COLOR: (10, 30)},
|
||||
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()
|
||||
|
||||
|
||||
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(
|
||||
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)
|
||||
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()
|
||||
|
||||
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)
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100},
|
||||
blocking=True,
|
||||
)
|
||||
@ -301,7 +437,7 @@ async def test_color_light_no_temp(hass: HomeAssistant) -> None:
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_HS_COLOR: (10, 30)},
|
||||
blocking=True,
|
||||
)
|
||||
@ -309,11 +445,9 @@ async def test_color_light_no_temp(hass: HomeAssistant) -> None:
|
||||
light.set_hsv.reset_mock()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("device", "is_color"),
|
||||
[
|
||||
(
|
||||
_mocked_device(
|
||||
async def test_color_temp_light_color(hass: HomeAssistant) -> None:
|
||||
"""Test a color temp light with color."""
|
||||
device = _mocked_device(
|
||||
modules=[Module.Light],
|
||||
alias="my_light",
|
||||
features=[
|
||||
@ -323,37 +457,16 @@ async def test_color_light_no_temp(hass: HomeAssistant) -> None:
|
||||
"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(
|
||||
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=MAC_ADDRESS
|
||||
)
|
||||
already_migrated_config_entry.add_to_hass(hass)
|
||||
# device = _mocked_device(modules=[Module.Light], alias="my_light")
|
||||
|
||||
light = device.modules[Module.Light]
|
||||
|
||||
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()
|
||||
|
||||
entity_id = "light.my_light"
|
||||
@ -363,29 +476,24 @@ async def test_color_temp_light(
|
||||
attributes = state.attributes
|
||||
assert attributes[ATTR_BRIGHTNESS] == 128
|
||||
assert attributes[ATTR_COLOR_MODE] == "color_temp"
|
||||
if is_color:
|
||||
|
||||
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(
|
||||
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.reset_mock()
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100},
|
||||
blocking=True,
|
||||
)
|
||||
@ -394,7 +502,7 @@ async def test_color_temp_light(
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 6666},
|
||||
blocking=True,
|
||||
)
|
||||
@ -404,7 +512,7 @@ async def test_color_temp_light(
|
||||
# Verify color temp is clamped to the valid range
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 20000},
|
||||
blocking=True,
|
||||
)
|
||||
@ -414,7 +522,94 @@ async def test_color_temp_light(
|
||||
# Verify color temp is clamped to the valid range
|
||||
await hass.services.async_call(
|
||||
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},
|
||||
blocking=True,
|
||||
)
|
||||
@ -423,7 +618,7 @@ async def test_color_temp_light(
|
||||
|
||||
|
||||
async def test_brightness_only_light(hass: HomeAssistant) -> None:
|
||||
"""Test a light."""
|
||||
"""Test a light brightness."""
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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]
|
||||
|
||||
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()
|
||||
|
||||
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"]
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100},
|
||||
blocking=True,
|
||||
)
|
||||
@ -470,7 +665,7 @@ async def test_brightness_only_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(
|
||||
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]
|
||||
|
||||
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()
|
||||
|
||||
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"]
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
|
||||
async def test_off_at_start_light(hass: HomeAssistant) -> None:
|
||||
"""Test a light."""
|
||||
"""Test a light off at startup."""
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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)
|
||||
|
||||
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()
|
||||
|
||||
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:
|
||||
"""Test a light."""
|
||||
"""Test a dimmer turns on without brightness being set."""
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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)
|
||||
|
||||
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()
|
||||
|
||||
entity_id = "light.my_light"
|
||||
@ -546,7 +741,7 @@ async def test_dimmer_turn_on_fix(hass: HomeAssistant) -> None:
|
||||
assert state.state == "off"
|
||||
|
||||
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(
|
||||
LightState(
|
||||
@ -587,7 +782,7 @@ async def test_smart_strip_effects(
|
||||
_patch_single_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()
|
||||
|
||||
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
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP_KELVIN: 4000},
|
||||
blocking=True,
|
||||
)
|
||||
@ -612,7 +807,7 @@ async def test_smart_strip_effects(
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "Effect2"},
|
||||
blocking=True,
|
||||
)
|
||||
@ -629,7 +824,7 @@ async def test_smart_strip_effects(
|
||||
# Test setting light effect off
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "off"},
|
||||
blocking=True,
|
||||
)
|
||||
@ -644,7 +839,7 @@ async def test_smart_strip_effects(
|
||||
caplog.clear()
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "Effect3"},
|
||||
blocking=True,
|
||||
)
|
||||
@ -673,7 +868,7 @@ async def test_smart_strip_effects(
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
@ -703,7 +898,7 @@ async def test_smart_strip_custom_random_effect(hass: HomeAssistant) -> None:
|
||||
light_effect = device.modules[Module.LightEffect]
|
||||
|
||||
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()
|
||||
|
||||
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(
|
||||
DOMAIN,
|
||||
"random_effect",
|
||||
SERVICE_RANDOM_EFFECT,
|
||||
{
|
||||
ATTR_ENTITY_ID: entity_id,
|
||||
"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(
|
||||
DOMAIN,
|
||||
"random_effect",
|
||||
SERVICE_RANDOM_EFFECT,
|
||||
{
|
||||
ATTR_ENTITY_ID: entity_id,
|
||||
"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(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
@ -801,7 +996,7 @@ async def test_smart_strip_custom_random_effect(hass: HomeAssistant) -> None:
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"random_effect",
|
||||
SERVICE_RANDOM_EFFECT,
|
||||
{
|
||||
ATTR_ENTITY_ID: entity_id,
|
||||
"init_states": [340, 20, 50],
|
||||
@ -875,7 +1070,7 @@ async def test_smart_strip_effect_service_error(
|
||||
service_params: dict,
|
||||
expected_extra_params: dict,
|
||||
) -> None:
|
||||
"""Test smart strip custom random effects."""
|
||||
"""Test smart strip effect service errors."""
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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]
|
||||
|
||||
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()
|
||||
|
||||
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.effect = LightEffect.LIGHT_EFFECTS_OFF
|
||||
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()
|
||||
|
||||
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
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
"turn_on",
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
@ -965,7 +1160,7 @@ async def test_smart_strip_custom_sequence_effect(hass: HomeAssistant) -> None:
|
||||
light_effect = device.modules[Module.LightEffect]
|
||||
|
||||
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()
|
||||
|
||||
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(
|
||||
DOMAIN,
|
||||
"sequence_effect",
|
||||
SERVICE_SEQUENCE_EFFECT,
|
||||
{
|
||||
ATTR_ENTITY_ID: entity_id,
|
||||
"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)
|
||||
|
||||
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()
|
||||
|
||||
entity_id = "light.my_light"
|
||||
@ -1051,7 +1246,7 @@ async def test_light_errors_when_turned_on(
|
||||
|
||||
with pytest.raises(HomeAssistantError, match=msg):
|
||||
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()
|
||||
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):
|
||||
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()
|
||||
|
||||
entity_id = "light.my_device"
|
||||
@ -1132,14 +1327,16 @@ async def test_scene_effect_light(
|
||||
light_effect.effect = LightEffect.LIGHT_EFFECTS_OFF
|
||||
|
||||
with _patch_discovery(device=device), _patch_connect(device=device):
|
||||
assert await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
|
||||
assert await async_setup_component(hass, "scene", {})
|
||||
assert await hass.config_entries.async_setup(
|
||||
already_migrated_config_entry.entry_id
|
||||
)
|
||||
assert await async_setup_component(hass, SCENE_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "light.my_light"
|
||||
|
||||
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()
|
||||
freezer.tick(5)
|
||||
@ -1151,9 +1348,9 @@ async def test_scene_effect_light(
|
||||
assert state.attributes["effect"] is EFFECT_OFF
|
||||
|
||||
await hass.services.async_call(
|
||||
"scene",
|
||||
"create",
|
||||
{"scene_id": "effect_off_scene", "snapshot_entities": [entity_id]},
|
||||
SCENE_DOMAIN,
|
||||
SERVICE_CREATE,
|
||||
{CONF_SCENE_ID: "effect_off_scene", CONF_SNAPSHOT: [entity_id]},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
@ -1161,7 +1358,7 @@ async def test_scene_effect_light(
|
||||
assert scene_state.state is STATE_UNKNOWN
|
||||
|
||||
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()
|
||||
freezer.tick(5)
|
||||
@ -1172,10 +1369,10 @@ async def test_scene_effect_light(
|
||||
assert state.state is STATE_OFF
|
||||
|
||||
await hass.services.async_call(
|
||||
"scene",
|
||||
"turn_on",
|
||||
SCENE_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{
|
||||
"entity_id": "scene.effect_off_scene",
|
||||
ATTR_ENTITY_ID: "scene.effect_off_scene",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
@ -3,7 +3,6 @@
|
||||
from kasa import Feature
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components import tplink
|
||||
from homeassistant.components.number import (
|
||||
ATTR_VALUE,
|
||||
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.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import (
|
||||
DEVICE_ID,
|
||||
MAC_ADDRESS,
|
||||
_mocked_device,
|
||||
_mocked_feature,
|
||||
_mocked_strip_children,
|
||||
@ -28,6 +24,7 @@ from . import (
|
||||
setup_platform_for_device,
|
||||
snapshot_platform,
|
||||
)
|
||||
from .const import DEVICE_ID, MAC_ADDRESS
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -39,7 +36,7 @@ async def test_states(
|
||||
device_registry: dr.DeviceRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test a number states."""
|
||||
features = {description.key for description in NUMBER_DESCRIPTIONS}
|
||||
features.update(EXCLUDED_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:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test number unique ids."""
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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])
|
||||
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()
|
||||
|
||||
entity_id = "number.my_plug_temperature_offset"
|
||||
@ -84,7 +81,7 @@ async def test_number_children(
|
||||
entity_registry: er.EntityRegistry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test number children."""
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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]),
|
||||
)
|
||||
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()
|
||||
|
||||
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])
|
||||
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()
|
||||
|
||||
entity_id = "number.my_plug_temperature_offset"
|
||||
|
@ -4,7 +4,6 @@ from kasa import Feature
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components import tplink
|
||||
from homeassistant.components.select import (
|
||||
ATTR_OPTION,
|
||||
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.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import (
|
||||
DEVICE_ID,
|
||||
MAC_ADDRESS,
|
||||
_mocked_device,
|
||||
_mocked_feature,
|
||||
_mocked_strip_children,
|
||||
@ -29,13 +25,14 @@ from . import (
|
||||
setup_platform_for_device,
|
||||
snapshot_platform,
|
||||
)
|
||||
from .const import DEVICE_ID, MAC_ADDRESS
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mocked_feature_select() -> Feature:
|
||||
"""Return mocked tplink binary sensor feature."""
|
||||
"""Return mocked tplink select feature."""
|
||||
return _mocked_feature(
|
||||
"light_preset",
|
||||
value="First choice",
|
||||
@ -53,7 +50,7 @@ async def test_states(
|
||||
device_registry: dr.DeviceRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test select states."""
|
||||
features = {description.key for description in SELECT_DESCRIPTIONS}
|
||||
features.update(EXCLUDED_FEATURES)
|
||||
device = _mocked_device(alias="my_device", features=features)
|
||||
@ -72,7 +69,7 @@ async def test_select(
|
||||
entity_registry: er.EntityRegistry,
|
||||
mocked_feature_select: Feature,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test select unique ids."""
|
||||
mocked_feature = mocked_feature_select
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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])
|
||||
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()
|
||||
|
||||
# The entity_id is based on standard name from core.
|
||||
@ -97,7 +94,7 @@ async def test_select_children(
|
||||
device_registry: dr.DeviceRegistry,
|
||||
mocked_feature_select: Feature,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test select children."""
|
||||
mocked_feature = mocked_feature_select
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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]),
|
||||
)
|
||||
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()
|
||||
|
||||
entity_id = "select.my_plug_light_preset"
|
||||
@ -141,7 +138,7 @@ async def test_select_select(
|
||||
already_migrated_config_entry.add_to_hass(hass)
|
||||
plug = _mocked_device(alias="my_plug", features=[mocked_feature])
|
||||
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()
|
||||
|
||||
entity_id = "select.my_plug_light_preset"
|
||||
|
@ -4,18 +4,14 @@ from kasa import Device, Feature, Module
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components import tplink
|
||||
from homeassistant.components.tplink.const import DOMAIN
|
||||
from homeassistant.components.tplink.entity import EXCLUDED_FEATURES
|
||||
from homeassistant.components.tplink.sensor import SENSOR_DESCRIPTIONS
|
||||
from homeassistant.const import CONF_HOST, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import (
|
||||
DEVICE_ID,
|
||||
MAC_ADDRESS,
|
||||
_mocked_device,
|
||||
_mocked_energy_features,
|
||||
_mocked_feature,
|
||||
@ -25,6 +21,7 @@ from . import (
|
||||
setup_platform_for_device,
|
||||
snapshot_platform,
|
||||
)
|
||||
from .const import DEVICE_ID, MAC_ADDRESS
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -36,7 +33,7 @@ async def test_states(
|
||||
device_registry: dr.DeviceRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test a sensor states."""
|
||||
features = {description.key for description in SENSOR_DESCRIPTIONS}
|
||||
features.update(EXCLUDED_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]
|
||||
)
|
||||
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()
|
||||
|
||||
@ -104,7 +101,7 @@ async def test_plug_with_an_emeter(hass: HomeAssistant) -> None:
|
||||
)
|
||||
plug = _mocked_device(alias="my_plug", features=["state", *emeter_features])
|
||||
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()
|
||||
|
||||
@ -131,7 +128,7 @@ async def test_color_light_no_emeter(hass: HomeAssistant) -> None:
|
||||
bulb = _mocked_device(alias="my_bulb", modules=[Module.Light])
|
||||
|
||||
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()
|
||||
|
||||
@ -167,7 +164,7 @@ async def test_sensor_unique_id(
|
||||
)
|
||||
plug = _mocked_device(alias="my_plug", features=emeter_features)
|
||||
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()
|
||||
|
||||
expected = {
|
||||
@ -202,7 +199,7 @@ async def test_undefined_sensor(
|
||||
)
|
||||
plug = _mocked_device(alias="my_plug", features=[new_feature])
|
||||
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()
|
||||
|
||||
msg = (
|
||||
@ -240,7 +237,7 @@ async def test_sensor_children_on_parent(
|
||||
device_type=Device.Type.WallSwitch,
|
||||
)
|
||||
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()
|
||||
|
||||
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,
|
||||
)
|
||||
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()
|
||||
|
||||
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
|
||||
|
||||
|
||||
@pytest.mark.skip
|
||||
async def test_new_datetime_sensor(
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_datetime_sensor(
|
||||
hass: HomeAssistant, entity_registry: er.EntityRegistry
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
# Skipped temporarily while datetime handling on hold.
|
||||
"""Test a timestamp sensor."""
|
||||
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)
|
||||
plug = _mocked_device(alias="my_plug", features=["on_since"])
|
||||
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()
|
||||
|
||||
entity_id = "sensor.my_plug_on_since"
|
||||
|
@ -9,7 +9,11 @@ import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
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.entity import EXCLUDED_FEATURES
|
||||
from homeassistant.components.tplink.switch import SWITCH_DESCRIPTIONS
|
||||
@ -25,12 +29,9 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
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 . import (
|
||||
DEVICE_ID,
|
||||
MAC_ADDRESS,
|
||||
_mocked_device,
|
||||
_mocked_strip_children,
|
||||
_patch_connect,
|
||||
@ -38,6 +39,7 @@ from . import (
|
||||
setup_platform_for_device,
|
||||
snapshot_platform,
|
||||
)
|
||||
from .const import DEVICE_ID, MAC_ADDRESS
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
|
||||
@ -49,7 +51,7 @@ async def test_states(
|
||||
device_registry: dr.DeviceRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test a sensor unique ids."""
|
||||
"""Test a switch states."""
|
||||
features = {description.key for description in SWITCH_DESCRIPTIONS}
|
||||
features.update(EXCLUDED_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"])
|
||||
feat = plug.features["state"]
|
||||
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()
|
||||
|
||||
entity_id = "switch.my_plug"
|
||||
@ -80,13 +82,13 @@ async def test_plug(hass: HomeAssistant) -> None:
|
||||
assert state.state == STATE_ON
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
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.reset_mock()
|
||||
@ -120,7 +122,7 @@ async def test_led_switch(hass: HomeAssistant, dev: Device, domain: str) -> None
|
||||
feat = dev.features["led"]
|
||||
already_migrated_config_entry.add_to_hass(hass)
|
||||
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()
|
||||
|
||||
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"
|
||||
|
||||
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.reset_mock()
|
||||
|
||||
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.reset_mock()
|
||||
@ -153,7 +155,7 @@ async def test_plug_unique_id(
|
||||
already_migrated_config_entry.add_to_hass(hass)
|
||||
plug = _mocked_device(alias="my_plug", features=["state", "led"])
|
||||
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()
|
||||
|
||||
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)
|
||||
plug = _mocked_device(alias="my_plug", features=["state", "led"])
|
||||
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()
|
||||
|
||||
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[1].features["state"].value = False
|
||||
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()
|
||||
|
||||
entity_id = "switch.my_strip_plug0"
|
||||
@ -205,14 +207,14 @@ async def test_strip(hass: HomeAssistant) -> None:
|
||||
assert state.state == STATE_ON
|
||||
|
||||
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.set_value.assert_called_once()
|
||||
feat.set_value.reset_mock()
|
||||
|
||||
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.reset_mock()
|
||||
@ -222,14 +224,14 @@ async def test_strip(hass: HomeAssistant) -> None:
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
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.set_value.assert_called_once()
|
||||
feat.set_value.reset_mock()
|
||||
|
||||
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.reset_mock()
|
||||
@ -249,7 +251,7 @@ async def test_strip_unique_ids(
|
||||
features=["state", "led"],
|
||||
)
|
||||
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()
|
||||
|
||||
for plug_id in range(2):
|
||||
@ -264,7 +266,7 @@ async def test_strip_blank_alias(
|
||||
entity_registry: er.EntityRegistry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
) -> None:
|
||||
"""Test a strip unique id."""
|
||||
"""Test a strip with blank parent alias."""
|
||||
already_migrated_config_entry = MockConfigEntry(
|
||||
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"],
|
||||
)
|
||||
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()
|
||||
|
||||
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")
|
||||
|
||||
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()
|
||||
|
||||
entity_id = "switch.my_plug"
|
||||
@ -349,7 +351,7 @@ async def test_plug_errors_when_turned_on(
|
||||
|
||||
with pytest.raises(HomeAssistantError, match=msg):
|
||||
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()
|
||||
assert feat.set_value.call_count == 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user