mirror of
https://github.com/python-kasa/python-kasa.git
synced 2026-07-08 06:41:59 +00:00
tests: add type annotations to Smart tests (#1686)
Some checks are pending
CI / Perform Lint Checks (3.14) (push) Waiting to run
CI / Python 3.11 on macos-latest (push) Blocked by required conditions
CI / Python 3.12 on macos-latest (push) Blocked by required conditions
CI / Python 3.13 on macos-latest (push) Blocked by required conditions
CI / Python 3.14 on macos-latest (push) Blocked by required conditions
CI / Python 3.11 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.12 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.13 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.14 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.11 on windows-latest (push) Blocked by required conditions
CI / Python 3.12 on windows-latest (push) Blocked by required conditions
CI / Python 3.13 on windows-latest (push) Blocked by required conditions
CI / Python 3.14 on windows-latest (push) Blocked by required conditions
CodeQL Checks / Analyze (python) (push) Waiting to run
Some checks are pending
CI / Perform Lint Checks (3.14) (push) Waiting to run
CI / Python 3.11 on macos-latest (push) Blocked by required conditions
CI / Python 3.12 on macos-latest (push) Blocked by required conditions
CI / Python 3.13 on macos-latest (push) Blocked by required conditions
CI / Python 3.14 on macos-latest (push) Blocked by required conditions
CI / Python 3.11 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.12 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.13 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.14 on ubuntu-latest (push) Blocked by required conditions
CI / Python 3.11 on windows-latest (push) Blocked by required conditions
CI / Python 3.12 on windows-latest (push) Blocked by required conditions
CI / Python 3.13 on windows-latest (push) Blocked by required conditions
CI / Python 3.14 on windows-latest (push) Blocked by required conditions
CodeQL Checks / Analyze (python) (push) Waiting to run
Add type annotations across all 'smart' tests, enabling mypy to check test function bodies, catching type errors that were previously hidden.
This commit is contained in:
@@ -9,7 +9,7 @@ brightness = parametrize("brightness smart", component_filter="brightness")
|
||||
|
||||
|
||||
@brightness
|
||||
async def test_brightness_component(dev: SmartDevice):
|
||||
async def test_brightness_component(dev: SmartDevice) -> None:
|
||||
"""Test brightness feature."""
|
||||
brightness = next(get_parent_and_child_modules(dev, "Brightness"))
|
||||
assert brightness
|
||||
@@ -35,7 +35,7 @@ async def test_brightness_component(dev: SmartDevice):
|
||||
|
||||
|
||||
@dimmable_iot
|
||||
async def test_brightness_dimmable(dev: IotDevice):
|
||||
async def test_brightness_dimmable(dev: IotDevice) -> None:
|
||||
"""Test brightness feature."""
|
||||
assert isinstance(dev, IotDevice)
|
||||
assert "brightness" in dev.sys_info or bool(dev.sys_info["is_dimmable"])
|
||||
|
||||
@@ -6,7 +6,7 @@ from ...conftest import variable_temp_smart
|
||||
|
||||
|
||||
@variable_temp_smart
|
||||
async def test_colortemp_component(dev: SmartDevice):
|
||||
async def test_colortemp_component(dev: SmartDevice) -> None:
|
||||
"""Test brightness feature."""
|
||||
assert isinstance(dev, SmartDevice)
|
||||
assert "color_temperature" in dev._components
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TypedDict
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from kasa import Module
|
||||
from kasa.smart import SmartDevice
|
||||
from kasa.smart.modules import Alarm
|
||||
from kasa.smart.modules.alarm import AlarmVolume
|
||||
|
||||
from ...device_fixtures import get_parent_and_child_modules, parametrize
|
||||
|
||||
alarm = parametrize("has alarm", component_filter="alarm", protocol_filter={"SMART"})
|
||||
|
||||
|
||||
class PlayAlarmKwargs(TypedDict, total=False):
|
||||
duration: int
|
||||
volume: AlarmVolume | int
|
||||
sound: str
|
||||
|
||||
|
||||
class PlayAlarmRequestParams(TypedDict, total=False):
|
||||
alarm_duration: int
|
||||
alarm_volume: AlarmVolume
|
||||
alarm_type: str
|
||||
|
||||
|
||||
@alarm
|
||||
@pytest.mark.parametrize(
|
||||
("feature", "prop_name", "type"),
|
||||
@@ -23,7 +38,9 @@ alarm = parametrize("has alarm", component_filter="alarm", protocol_filter={"SMA
|
||||
("alarm_volume_level", "alarm_volume", int),
|
||||
],
|
||||
)
|
||||
async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: type):
|
||||
async def test_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
alarm = next(get_parent_and_child_modules(dev, Module.Alarm))
|
||||
assert alarm is not None
|
||||
@@ -37,7 +54,7 @@ async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: ty
|
||||
|
||||
|
||||
@alarm
|
||||
async def test_volume_feature(dev: SmartDevice):
|
||||
async def test_volume_feature(dev: SmartDevice) -> None:
|
||||
"""Test that volume features have correct choices and range."""
|
||||
alarm = next(get_parent_and_child_modules(dev, Module.Alarm))
|
||||
assert alarm is not None
|
||||
@@ -64,7 +81,12 @@ async def test_volume_feature(dev: SmartDevice):
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_play(dev: SmartDevice, kwargs, request_params, mocker: MockerFixture):
|
||||
async def test_play(
|
||||
dev: SmartDevice,
|
||||
kwargs: PlayAlarmKwargs,
|
||||
request_params: PlayAlarmRequestParams,
|
||||
mocker: MockerFixture,
|
||||
) -> None:
|
||||
"""Test that play parameters are handled correctly."""
|
||||
alarm: Alarm = next(get_parent_and_child_modules(dev, Module.Alarm))
|
||||
call_spy = mocker.spy(alarm, "call")
|
||||
@@ -86,7 +108,7 @@ async def test_play(dev: SmartDevice, kwargs, request_params, mocker: MockerFixt
|
||||
|
||||
|
||||
@alarm
|
||||
async def test_stop(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_stop(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test that stop creates the correct call."""
|
||||
alarm: Alarm = next(get_parent_and_child_modules(dev, Module.Alarm))
|
||||
call_spy = mocker.spy(alarm, "call")
|
||||
@@ -112,7 +134,7 @@ async def test_set_alarm_configure(
|
||||
method: str,
|
||||
value: str | int,
|
||||
target_key: str,
|
||||
):
|
||||
) -> None:
|
||||
"""Test that set_alarm_sound creates the correct call."""
|
||||
alarm: Alarm = next(get_parent_and_child_modules(dev, Module.Alarm))
|
||||
call_spy = mocker.spy(alarm, "call")
|
||||
|
||||
@@ -26,7 +26,7 @@ autooff = parametrize(
|
||||
)
|
||||
async def test_autooff_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
):
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
autooff = next(get_parent_and_child_modules(dev, Module.AutoOff))
|
||||
assert autooff is not None
|
||||
@@ -40,7 +40,7 @@ async def test_autooff_features(
|
||||
|
||||
|
||||
@autooff
|
||||
async def test_settings(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_settings(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test autooff settings."""
|
||||
autooff = next(get_parent_and_child_modules(dev, Module.AutoOff))
|
||||
assert autooff
|
||||
@@ -79,7 +79,7 @@ async def test_settings(dev: SmartDevice, mocker: MockerFixture):
|
||||
@pytest.mark.parametrize("is_timer_active", [True, False])
|
||||
async def test_auto_off_at(
|
||||
dev: SmartDevice, mocker: MockerFixture, is_timer_active: bool
|
||||
):
|
||||
) -> None:
|
||||
"""Test auto-off at sensor."""
|
||||
autooff = next(get_parent_and_child_modules(dev, Module.AutoOff))
|
||||
assert autooff
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from kasa import Module
|
||||
from kasa.smart.modules import ChildLock
|
||||
from kasa.smart import SmartDevice
|
||||
|
||||
from ...device_fixtures import parametrize
|
||||
|
||||
@@ -19,9 +19,11 @@ childlock = parametrize(
|
||||
("child_lock", "enabled", bool),
|
||||
],
|
||||
)
|
||||
async def test_features(dev, feature, prop_name, type):
|
||||
async def test_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
protect: ChildLock = dev.modules[Module.ChildLock]
|
||||
protect = dev.modules[Module.ChildLock]
|
||||
assert protect is not None
|
||||
|
||||
prop = getattr(protect, prop_name)
|
||||
@@ -33,9 +35,9 @@ async def test_features(dev, feature, prop_name, type):
|
||||
|
||||
|
||||
@childlock
|
||||
async def test_enabled(dev):
|
||||
async def test_enabled(dev: SmartDevice) -> None:
|
||||
"""Test the API."""
|
||||
protect: ChildLock = dev.modules[Module.ChildLock]
|
||||
protect = dev.modules[Module.ChildLock]
|
||||
assert protect is not None
|
||||
|
||||
assert isinstance(protect.enabled, bool)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from kasa import Module
|
||||
from kasa.smart.modules import ChildProtection
|
||||
from kasa.smart import SmartDevice
|
||||
|
||||
from ...device_fixtures import parametrize
|
||||
|
||||
@@ -19,9 +19,11 @@ child_protection = parametrize(
|
||||
("child_lock", "enabled", bool),
|
||||
],
|
||||
)
|
||||
async def test_features(dev, feature, prop_name, type):
|
||||
async def test_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
protect: ChildProtection = dev.modules[Module.ChildProtection]
|
||||
protect = dev.modules[Module.ChildProtection]
|
||||
assert protect is not None
|
||||
|
||||
prop = getattr(protect, prop_name)
|
||||
@@ -33,9 +35,9 @@ async def test_features(dev, feature, prop_name, type):
|
||||
|
||||
|
||||
@child_protection
|
||||
async def test_enabled(dev):
|
||||
async def test_enabled(dev: SmartDevice) -> None:
|
||||
"""Test the API."""
|
||||
protect: ChildProtection = dev.modules[Module.ChildProtection]
|
||||
protect = dev.modules[Module.ChildProtection]
|
||||
assert protect is not None
|
||||
|
||||
assert isinstance(protect.enabled, bool)
|
||||
|
||||
@@ -15,7 +15,7 @@ childsetup = parametrize(
|
||||
|
||||
|
||||
@childsetup
|
||||
async def test_childsetup_features(dev: Device):
|
||||
async def test_childsetup_features(dev: Device) -> None:
|
||||
"""Test the exposed features."""
|
||||
cs = dev.modules.get(Module.ChildSetup)
|
||||
assert cs
|
||||
@@ -28,7 +28,7 @@ async def test_childsetup_features(dev: Device):
|
||||
@childsetup
|
||||
async def test_childsetup_pair(
|
||||
dev: Device, mocker: MockerFixture, caplog: pytest.LogCaptureFixture
|
||||
):
|
||||
) -> None:
|
||||
"""Test device pairing."""
|
||||
caplog.set_level(logging.INFO)
|
||||
mock_query_helper = mocker.spy(dev, "_query_helper")
|
||||
@@ -52,7 +52,7 @@ async def test_childsetup_pair(
|
||||
@childsetup
|
||||
async def test_childsetup_unpair(
|
||||
dev: Device, mocker: MockerFixture, caplog: pytest.LogCaptureFixture
|
||||
):
|
||||
) -> None:
|
||||
"""Test unpair."""
|
||||
mock_query_helper = mocker.spy(dev, "_query_helper")
|
||||
DUMMY_ID = "dummy_id"
|
||||
|
||||
@@ -25,7 +25,9 @@ clean = parametrize("clean module", component_filter="clean", protocol_filter={"
|
||||
("battery_level", "battery", int),
|
||||
],
|
||||
)
|
||||
async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: type):
|
||||
async def test_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
clean = next(get_parent_and_child_modules(dev, Module.Clean))
|
||||
assert clean is not None
|
||||
@@ -94,7 +96,7 @@ async def test_actions(
|
||||
value: str | int,
|
||||
method: str,
|
||||
params: dict,
|
||||
):
|
||||
) -> None:
|
||||
"""Test the clean actions."""
|
||||
clean = next(get_parent_and_child_modules(dev, Module.Clean))
|
||||
call = mocker.spy(clean, "call")
|
||||
@@ -130,7 +132,7 @@ async def test_post_update_hook(
|
||||
error: ErrorCode,
|
||||
warning_msg: str | None,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
):
|
||||
) -> None:
|
||||
"""Test that post update hook sets error states correctly."""
|
||||
clean = next(get_parent_and_child_modules(dev, Module.Clean))
|
||||
assert clean
|
||||
@@ -160,7 +162,7 @@ async def test_post_update_hook(
|
||||
|
||||
|
||||
@clean
|
||||
async def test_resume(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_resume(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test that start calls resume if the state is paused."""
|
||||
clean = next(get_parent_and_child_modules(dev, Module.Clean))
|
||||
|
||||
@@ -182,7 +184,7 @@ async def test_resume(dev: SmartDevice, mocker: MockerFixture):
|
||||
@clean
|
||||
async def test_unknown_status(
|
||||
dev: SmartDevice, mocker: MockerFixture, caplog: pytest.LogCaptureFixture
|
||||
):
|
||||
) -> None:
|
||||
"""Test that unknown status is logged."""
|
||||
clean = next(get_parent_and_child_modules(dev, Module.Clean))
|
||||
|
||||
@@ -227,7 +229,7 @@ async def test_invalid_settings(
|
||||
value: str,
|
||||
exc: type[Exception],
|
||||
exc_message: str,
|
||||
):
|
||||
) -> None:
|
||||
"""Test invalid settings."""
|
||||
clean = next(get_parent_and_child_modules(dev, Module.Clean))
|
||||
|
||||
|
||||
@@ -27,7 +27,9 @@ cleanrecords = parametrize(
|
||||
("last_clean_timestamp", "last_clean_timestamp", datetime),
|
||||
],
|
||||
)
|
||||
async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: type):
|
||||
async def test_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
records = next(get_parent_and_child_modules(dev, Module.CleanRecords))
|
||||
assert records is not None
|
||||
@@ -41,7 +43,7 @@ async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: ty
|
||||
|
||||
|
||||
@cleanrecords
|
||||
async def test_timezone(dev: SmartDevice):
|
||||
async def test_timezone(dev: SmartDevice) -> None:
|
||||
"""Test that timezone is added to timestamps."""
|
||||
clean_records = next(get_parent_and_child_modules(dev, Module.CleanRecords))
|
||||
assert clean_records is not None
|
||||
|
||||
@@ -21,7 +21,7 @@ consumables = parametrize(
|
||||
"consumable_name", [consumable.id for consumable in CONSUMABLE_METAS]
|
||||
)
|
||||
@pytest.mark.parametrize("postfix", ["used", "remaining"])
|
||||
async def test_features(dev: SmartDevice, consumable_name: str, postfix: str):
|
||||
async def test_features(dev: SmartDevice, consumable_name: str, postfix: str) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
consumables = next(get_parent_and_child_modules(dev, Module.Consumables))
|
||||
assert consumables is not None
|
||||
@@ -39,7 +39,7 @@ async def test_features(dev: SmartDevice, consumable_name: str, postfix: str):
|
||||
)
|
||||
async def test_erase(
|
||||
dev: SmartDevice, mocker: MockerFixture, consumable_name: str, data_key: str
|
||||
):
|
||||
) -> None:
|
||||
"""Test autocollection switch."""
|
||||
consumables = next(get_parent_and_child_modules(dev, Module.Consumables))
|
||||
call = mocker.spy(consumables, "call")
|
||||
|
||||
@@ -16,7 +16,7 @@ contact = parametrize(
|
||||
("is_open", bool),
|
||||
],
|
||||
)
|
||||
async def test_contact_features(dev: Device, feature, type):
|
||||
async def test_contact_features(dev: Device, feature: str, type: type) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
contact = dev.modules.get(Module.ContactSensor)
|
||||
assert contact is not None
|
||||
|
||||
@@ -22,7 +22,9 @@ dustbin = parametrize(
|
||||
("dustbin_mode", "mode", str),
|
||||
],
|
||||
)
|
||||
async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: type):
|
||||
async def test_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
dustbin = next(get_parent_and_child_modules(dev, Module.Dustbin))
|
||||
assert dustbin is not None
|
||||
@@ -36,7 +38,7 @@ async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: ty
|
||||
|
||||
|
||||
@dustbin
|
||||
async def test_dustbin_mode(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_dustbin_mode(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test dust mode."""
|
||||
dustbin = next(get_parent_and_child_modules(dev, Module.Dustbin))
|
||||
call = mocker.spy(dustbin, "call")
|
||||
@@ -61,7 +63,7 @@ async def test_dustbin_mode(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dustbin
|
||||
async def test_dustbin_mode_off(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_dustbin_mode_off(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test dustbin_mode == Off."""
|
||||
dustbin = next(get_parent_and_child_modules(dev, Module.Dustbin))
|
||||
call = mocker.spy(dustbin, "call")
|
||||
@@ -80,7 +82,7 @@ async def test_dustbin_mode_off(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dustbin
|
||||
async def test_autocollection(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_autocollection(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test autocollection switch."""
|
||||
dustbin = next(get_parent_and_child_modules(dev, Module.Dustbin))
|
||||
call = mocker.spy(dustbin, "call")
|
||||
@@ -101,7 +103,7 @@ async def test_autocollection(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dustbin
|
||||
async def test_empty_dustbin(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_empty_dustbin(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test the empty dustbin feature."""
|
||||
dustbin = next(get_parent_and_child_modules(dev, Module.Dustbin))
|
||||
call = mocker.spy(dustbin, "call")
|
||||
|
||||
@@ -14,7 +14,7 @@ from tests.conftest import has_emeter_smart
|
||||
|
||||
|
||||
@has_emeter_smart
|
||||
async def test_supported(dev: SmartDevice):
|
||||
async def test_supported(dev: SmartDevice) -> None:
|
||||
energy_module = dev.modules.get(Module.Energy)
|
||||
if not energy_module:
|
||||
pytest.skip(f"Energy module not supported for {dev}.")
|
||||
@@ -31,7 +31,7 @@ async def test_supported(dev: SmartDevice):
|
||||
@has_emeter_smart
|
||||
async def test_get_energy_usage_error(
|
||||
dev: SmartDevice, caplog: pytest.LogCaptureFixture
|
||||
):
|
||||
) -> None:
|
||||
"""Test errors on get_energy_usage."""
|
||||
caplog.set_level(logging.DEBUG)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ fan = parametrize("has fan", component_filter="fan_control", protocol_filter={"S
|
||||
|
||||
|
||||
@fan
|
||||
async def test_fan_speed(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_fan_speed(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test fan speed feature."""
|
||||
fan = next(get_parent_and_child_modules(dev, Module.Fan))
|
||||
assert fan
|
||||
@@ -35,7 +35,7 @@ async def test_fan_speed(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@fan
|
||||
async def test_sleep_mode(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_sleep_mode(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test sleep mode feature."""
|
||||
fan = next(get_parent_and_child_modules(dev, Module.Fan))
|
||||
assert fan
|
||||
@@ -53,7 +53,7 @@ async def test_sleep_mode(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@fan
|
||||
async def test_fan_module(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_fan_module(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test fan speed on device interface."""
|
||||
assert isinstance(dev, SmartDevice)
|
||||
fan = next(get_parent_and_child_modules(dev, Module.Fan))
|
||||
@@ -89,7 +89,7 @@ async def test_fan_module(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@fan
|
||||
async def test_fan_features(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_fan_features(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test fan speed on device interface."""
|
||||
assert isinstance(dev, SmartDevice)
|
||||
fan = next(get_parent_and_child_modules(dev, Module.Fan))
|
||||
|
||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from contextlib import nullcontext
|
||||
from contextlib import AbstractContextManager, nullcontext
|
||||
from datetime import date
|
||||
from typing import TypedDict
|
||||
|
||||
@@ -31,9 +31,14 @@ firmware = parametrize(
|
||||
],
|
||||
)
|
||||
async def test_firmware_features(
|
||||
dev: SmartDevice, feature, prop_name, type, required_version, mocker: MockerFixture
|
||||
):
|
||||
"""Test light effect."""
|
||||
dev: SmartDevice,
|
||||
feature: str,
|
||||
prop_name: str,
|
||||
type: type,
|
||||
required_version: int,
|
||||
mocker: MockerFixture,
|
||||
) -> None:
|
||||
"""Test firmware features."""
|
||||
fw = dev.modules.get(Module.Firmware)
|
||||
assert fw
|
||||
assert fw.firmware_update_info is None
|
||||
@@ -54,7 +59,7 @@ async def test_firmware_features(
|
||||
|
||||
|
||||
@firmware
|
||||
async def test_firmware_update_info(dev: SmartDevice):
|
||||
async def test_firmware_update_info(dev: SmartDevice) -> None:
|
||||
"""Test that the firmware UpdateInfo object deserializes correctly."""
|
||||
fw = dev.modules.get(Module.Firmware)
|
||||
assert fw
|
||||
@@ -68,7 +73,7 @@ async def test_firmware_update_info(dev: SmartDevice):
|
||||
|
||||
|
||||
@firmware
|
||||
async def test_update_available_without_cloud(dev: SmartDevice):
|
||||
async def test_update_available_without_cloud(dev: SmartDevice) -> None:
|
||||
"""Test that update_available returns None when disconnected."""
|
||||
fw = dev.modules.get(Module.Firmware)
|
||||
assert fw
|
||||
@@ -95,9 +100,9 @@ async def test_firmware_update(
|
||||
dev: SmartDevice,
|
||||
mocker: MockerFixture,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
update_available,
|
||||
expected_result,
|
||||
):
|
||||
update_available: bool,
|
||||
expected_result: AbstractContextManager,
|
||||
) -> None:
|
||||
"""Test updating firmware."""
|
||||
caplog.set_level(logging.INFO)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ homekit = parametrize(
|
||||
|
||||
|
||||
@homekit
|
||||
async def test_info(dev: SmartDevice):
|
||||
async def test_info(dev: SmartDevice) -> None:
|
||||
"""Test homekit info."""
|
||||
homekit = dev.modules.get(Module.HomeKit)
|
||||
assert homekit
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from kasa.smart.modules import HumiditySensor
|
||||
from kasa import Module
|
||||
from kasa.smart import SmartDevice
|
||||
|
||||
from ...device_fixtures import parametrize
|
||||
|
||||
@@ -17,9 +18,9 @@ humidity = parametrize(
|
||||
("humidity_warning", bool),
|
||||
],
|
||||
)
|
||||
async def test_humidity_features(dev, feature, type):
|
||||
async def test_humidity_features(dev: SmartDevice, feature: str, type: type) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
humidity: HumiditySensor = dev.modules["HumiditySensor"]
|
||||
humidity = dev.modules[Module.HumiditySensor]
|
||||
|
||||
prop = getattr(humidity, feature)
|
||||
assert isinstance(prop, type)
|
||||
|
||||
@@ -16,7 +16,7 @@ light_effect = parametrize(
|
||||
|
||||
|
||||
@light_effect
|
||||
async def test_light_effect(dev: Device, mocker: MockerFixture):
|
||||
async def test_light_effect(dev: Device, mocker: MockerFixture) -> None:
|
||||
"""Test light effect."""
|
||||
light_effect = dev.modules.get(Module.LightEffect)
|
||||
assert isinstance(light_effect, LightEffect)
|
||||
@@ -46,7 +46,7 @@ async def test_light_effect(dev: Device, mocker: MockerFixture):
|
||||
@pytest.mark.parametrize("effect_active", [True, False])
|
||||
async def test_light_effect_brightness(
|
||||
dev: Device, effect_active: bool, mocker: MockerFixture
|
||||
):
|
||||
) -> None:
|
||||
"""Test that light module uses light_effect for brightness when active."""
|
||||
light_module = dev.modules[Module.Light]
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ light_strip_effect = parametrize(
|
||||
|
||||
|
||||
@light_strip_effect
|
||||
async def test_light_strip_effect(dev: Device, mocker: MockerFixture):
|
||||
async def test_light_strip_effect(dev: Device, mocker: MockerFixture) -> None:
|
||||
"""Test light strip effect."""
|
||||
light_effect = dev.modules.get(Module.LightEffect)
|
||||
|
||||
@@ -63,7 +63,7 @@ async def test_light_strip_effect(dev: Device, mocker: MockerFixture):
|
||||
@pytest.mark.parametrize("effect_active", [True, False])
|
||||
async def test_light_effect_brightness(
|
||||
dev: Device, effect_active: bool, mocker: MockerFixture
|
||||
):
|
||||
) -> None:
|
||||
"""Test that light module uses light_effect for brightness when active."""
|
||||
light_module = dev.modules[Module.Light]
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ light_transition_gt_v1 = parametrize(
|
||||
|
||||
|
||||
@light_transition_v1
|
||||
async def test_module_v1(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_module_v1(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test light transition module."""
|
||||
assert isinstance(dev, SmartDevice)
|
||||
light_transition = next(get_parent_and_child_modules(dev, Module.LightTransition))
|
||||
@@ -42,7 +42,7 @@ async def test_module_v1(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@light_transition_gt_v1
|
||||
async def test_module_gt_v1(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_module_gt_v1(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test light transition module."""
|
||||
assert isinstance(dev, SmartDevice)
|
||||
light_transition = next(get_parent_and_child_modules(dev, Module.LightTransition))
|
||||
|
||||
@@ -9,7 +9,7 @@ matter = parametrize(
|
||||
|
||||
|
||||
@matter
|
||||
async def test_info(dev: SmartDevice):
|
||||
async def test_info(dev: SmartDevice) -> None:
|
||||
"""Test matter info."""
|
||||
matter = dev.modules.get(Module.Matter)
|
||||
assert matter
|
||||
|
||||
@@ -20,7 +20,9 @@ mop = parametrize("has mop", component_filter="mop", protocol_filter={"SMART"})
|
||||
("mop_waterlevel", "waterlevel", str),
|
||||
],
|
||||
)
|
||||
async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: type):
|
||||
async def test_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
mod = next(get_parent_and_child_modules(dev, Module.Mop))
|
||||
assert mod is not None
|
||||
@@ -34,7 +36,7 @@ async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: ty
|
||||
|
||||
|
||||
@mop
|
||||
async def test_mop_waterlevel(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_mop_waterlevel(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test dust mode."""
|
||||
mop_module = next(get_parent_and_child_modules(dev, Module.Mop))
|
||||
call = mocker.spy(mop_module, "call")
|
||||
|
||||
@@ -16,7 +16,7 @@ motion = parametrize(
|
||||
("motion_detected", bool),
|
||||
],
|
||||
)
|
||||
async def test_motion_features(dev: Device, feature, type):
|
||||
async def test_motion_features(dev: Device, feature: str, type: type) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
motion = dev.modules.get(Module.MotionSensor)
|
||||
assert motion is not None
|
||||
|
||||
@@ -2,6 +2,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from kasa import Device, Module
|
||||
from kasa.smart import SmartDevice
|
||||
|
||||
from ...device_fixtures import get_parent_and_child_modules, parametrize
|
||||
|
||||
@@ -20,7 +21,9 @@ powerprotection = parametrize(
|
||||
("power_protection_threshold", "protection_threshold", int),
|
||||
],
|
||||
)
|
||||
async def test_features(dev, feature, prop_name, type):
|
||||
async def test_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
powerprot = next(get_parent_and_child_modules(dev, Module.PowerProtection))
|
||||
assert powerprot
|
||||
@@ -35,7 +38,7 @@ async def test_features(dev, feature, prop_name, type):
|
||||
|
||||
|
||||
@powerprotection
|
||||
async def test_set_enable(dev: Device, mocker: MockerFixture):
|
||||
async def test_set_enable(dev: Device, mocker: MockerFixture) -> None:
|
||||
"""Test enable."""
|
||||
powerprot = next(get_parent_and_child_modules(dev, Module.PowerProtection))
|
||||
assert powerprot
|
||||
@@ -88,7 +91,7 @@ async def test_set_enable(dev: Device, mocker: MockerFixture):
|
||||
|
||||
|
||||
@powerprotection
|
||||
async def test_set_threshold(dev: Device, mocker: MockerFixture):
|
||||
async def test_set_threshold(dev: Device, mocker: MockerFixture) -> None:
|
||||
"""Test enable."""
|
||||
powerprot = next(get_parent_and_child_modules(dev, Module.PowerProtection))
|
||||
assert powerprot
|
||||
|
||||
@@ -20,7 +20,9 @@ speaker = parametrize(
|
||||
("volume", "volume", int),
|
||||
],
|
||||
)
|
||||
async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: type):
|
||||
async def test_features(
|
||||
dev: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
speaker = next(get_parent_and_child_modules(dev, Module.Speaker))
|
||||
assert speaker is not None
|
||||
@@ -34,7 +36,7 @@ async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: ty
|
||||
|
||||
|
||||
@speaker
|
||||
async def test_set_volume(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_set_volume(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test speaker settings."""
|
||||
speaker = next(get_parent_and_child_modules(dev, Module.Speaker))
|
||||
assert speaker is not None
|
||||
@@ -61,7 +63,7 @@ async def test_set_volume(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@speaker
|
||||
async def test_locate(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_locate(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test the locate method."""
|
||||
speaker = next(get_parent_and_child_modules(dev, Module.Speaker))
|
||||
call = mocker.spy(speaker, "call")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from kasa.smart.modules import TemperatureSensor
|
||||
from kasa import Module
|
||||
from kasa.smart import SmartDevice
|
||||
|
||||
from ...device_fixtures import parametrize
|
||||
|
||||
@@ -23,9 +24,9 @@ temperature_warning = parametrize(
|
||||
("temperature_unit", str),
|
||||
],
|
||||
)
|
||||
async def test_temperature_features(dev, feature, type):
|
||||
async def test_temperature_features(dev: SmartDevice, feature: str, type: type) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
temp_module: TemperatureSensor = dev.modules["TemperatureSensor"]
|
||||
temp_module = dev.modules[Module.TemperatureSensor]
|
||||
|
||||
prop = getattr(temp_module, feature)
|
||||
assert isinstance(prop, type)
|
||||
@@ -36,9 +37,9 @@ async def test_temperature_features(dev, feature, type):
|
||||
|
||||
|
||||
@temperature_warning
|
||||
async def test_temperature_warning(dev):
|
||||
async def test_temperature_warning(dev: SmartDevice) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
temp_module: TemperatureSensor = dev.modules["TemperatureSensor"]
|
||||
temp_module = dev.modules[Module.TemperatureSensor]
|
||||
|
||||
assert hasattr(temp_module, "temperature_warning")
|
||||
assert isinstance(temp_module.temperature_warning, bool)
|
||||
|
||||
@@ -3,7 +3,8 @@ import re
|
||||
|
||||
import pytest
|
||||
|
||||
from kasa.smart.modules import TemperatureControl
|
||||
from kasa import Module
|
||||
from kasa.smart import SmartDevice
|
||||
from kasa.smart.modules.temperaturecontrol import ThermostatState
|
||||
|
||||
from ...device_fixtures import parametrize, thermostats_smart
|
||||
@@ -23,9 +24,11 @@ temperature = parametrize(
|
||||
("temperature_offset", int),
|
||||
],
|
||||
)
|
||||
async def test_temperature_control_features(dev, feature, type):
|
||||
async def test_temperature_control_features(
|
||||
dev: SmartDevice, feature: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
|
||||
temp_module = dev.modules[Module.TemperatureControl]
|
||||
|
||||
prop = getattr(temp_module, feature)
|
||||
assert isinstance(prop, type)
|
||||
@@ -40,9 +43,9 @@ async def test_temperature_control_features(dev, feature, type):
|
||||
|
||||
|
||||
@thermostats_smart
|
||||
async def test_set_temperature_turns_heating_on(dev):
|
||||
async def test_set_temperature_turns_heating_on(dev: SmartDevice) -> None:
|
||||
"""Test that set_temperature turns heating on."""
|
||||
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
|
||||
temp_module = dev.modules[Module.TemperatureControl]
|
||||
|
||||
await temp_module.set_state(False)
|
||||
await dev.update()
|
||||
@@ -57,9 +60,9 @@ async def test_set_temperature_turns_heating_on(dev):
|
||||
|
||||
|
||||
@thermostats_smart
|
||||
async def test_set_temperature_invalid_values(dev):
|
||||
async def test_set_temperature_invalid_values(dev: SmartDevice) -> None:
|
||||
"""Test that out-of-bounds temperature values raise errors."""
|
||||
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
|
||||
temp_module = dev.modules[Module.TemperatureControl]
|
||||
|
||||
with pytest.raises(
|
||||
ValueError, match="Invalid target temperature -1, must be in range"
|
||||
@@ -73,9 +76,9 @@ async def test_set_temperature_invalid_values(dev):
|
||||
|
||||
|
||||
@thermostats_smart
|
||||
async def test_temperature_offset(dev):
|
||||
async def test_temperature_offset(dev: SmartDevice) -> None:
|
||||
"""Test the temperature offset API."""
|
||||
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
|
||||
temp_module = dev.modules[Module.TemperatureControl]
|
||||
with pytest.raises(
|
||||
ValueError, match=re.escape("Temperature offset must be [-10, 10]")
|
||||
):
|
||||
@@ -111,9 +114,11 @@ async def test_temperature_offset(dev):
|
||||
pytest.param(ThermostatState.Unknown, ["invalid"], False, id="unknown state"),
|
||||
],
|
||||
)
|
||||
async def test_thermostat_mode(dev, mode, states, frost_protection):
|
||||
async def test_thermostat_mode(
|
||||
dev: SmartDevice, mode: ThermostatState, states: list[str], frost_protection: bool
|
||||
) -> None:
|
||||
"""Test different thermostat modes."""
|
||||
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
|
||||
temp_module = dev.modules[Module.TemperatureControl]
|
||||
|
||||
temp_module.data["frost_protection_on"] = frost_protection
|
||||
temp_module.data["trv_states"] = states
|
||||
@@ -138,9 +143,15 @@ async def test_thermostat_mode(dev, mode, states, frost_protection):
|
||||
],
|
||||
)
|
||||
@pytest.mark.xdist_group(name="caplog")
|
||||
async def test_thermostat_mode_warnings(dev, mode, states, msg, caplog):
|
||||
async def test_thermostat_mode_warnings(
|
||||
dev: SmartDevice,
|
||||
mode: ThermostatState,
|
||||
states: list[str],
|
||||
msg: str,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Test thermostat modes that should log a warning."""
|
||||
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
|
||||
temp_module = dev.modules[Module.TemperatureControl]
|
||||
caplog.set_level(logging.WARNING)
|
||||
|
||||
temp_module.data["trv_states"] = states
|
||||
@@ -149,17 +160,19 @@ async def test_thermostat_mode_warnings(dev, mode, states, msg, caplog):
|
||||
|
||||
|
||||
@thermostats_smart
|
||||
async def test_thermostat_heating_with_low_battery(dev):
|
||||
async def test_thermostat_heating_with_low_battery(dev: SmartDevice) -> None:
|
||||
"""Test that mode is reported correctly with extra states."""
|
||||
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
|
||||
temp_module = dev.modules[Module.TemperatureControl]
|
||||
temp_module.data["trv_states"] = ["low_battery", "heating"]
|
||||
assert temp_module.mode is ThermostatState.Heating
|
||||
|
||||
|
||||
@thermostats_smart
|
||||
async def test_thermostat_idle_with_low_battery(dev, caplog):
|
||||
async def test_thermostat_idle_with_low_battery(
|
||||
dev: SmartDevice, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test that mode is reported correctly with extra states."""
|
||||
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
|
||||
temp_module = dev.modules[Module.TemperatureControl]
|
||||
temp_module.data["trv_states"] = ["low_battery"]
|
||||
with caplog.at_level(logging.WARNING):
|
||||
assert temp_module.mode is ThermostatState.Idle
|
||||
|
||||
@@ -10,7 +10,7 @@ triggerlogs = parametrize(
|
||||
|
||||
|
||||
@triggerlogs
|
||||
async def test_trigger_logs(dev: Device):
|
||||
async def test_trigger_logs(dev: Device) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
triggerlogs = dev.modules.get(Module.TriggerLogs)
|
||||
assert triggerlogs is not None
|
||||
|
||||
@@ -3,7 +3,8 @@ from enum import Enum
|
||||
|
||||
import pytest
|
||||
|
||||
from kasa.smart.modules import WaterleakSensor
|
||||
from kasa import Module
|
||||
from kasa.smart import SmartDevice
|
||||
|
||||
from ...conftest import get_device_for_fixture_protocol
|
||||
from ...device_fixtures import parametrize
|
||||
@@ -28,10 +29,12 @@ async def parent(request):
|
||||
("water_leak", "status", Enum),
|
||||
],
|
||||
)
|
||||
async def test_waterleak_properties(dev, parent, feature, prop_name, type):
|
||||
async def test_waterleak_properties(
|
||||
dev: SmartDevice, parent: SmartDevice, feature: str, prop_name: str, type: type
|
||||
) -> None:
|
||||
"""Test that features are registered and work as expected."""
|
||||
dev._parent = parent
|
||||
waterleak: WaterleakSensor = dev.modules["WaterleakSensor"]
|
||||
waterleak = dev.modules[Module.WaterleakSensor]
|
||||
|
||||
prop = getattr(waterleak, prop_name)
|
||||
assert isinstance(prop, type)
|
||||
@@ -42,10 +45,10 @@ async def test_waterleak_properties(dev, parent, feature, prop_name, type):
|
||||
|
||||
|
||||
@waterleak
|
||||
async def test_waterleak_features(dev, parent):
|
||||
async def test_waterleak_features(dev: SmartDevice, parent: SmartDevice) -> None:
|
||||
"""Test waterleak features."""
|
||||
dev._parent = parent
|
||||
waterleak: WaterleakSensor = dev.modules["WaterleakSensor"]
|
||||
waterleak = dev.modules[Module.WaterleakSensor]
|
||||
|
||||
assert "water_leak" in dev.features
|
||||
assert dev.features["water_leak"].value == waterleak.status
|
||||
|
||||
@@ -44,7 +44,9 @@ hub_all = parametrize_combine([hubs_smart, hub_smartcam])
|
||||
@device_smart
|
||||
@pytest.mark.requires_dummy
|
||||
@pytest.mark.xdist_group(name="caplog")
|
||||
async def test_try_get_response(dev: SmartDevice, caplog):
|
||||
async def test_try_get_response(
|
||||
dev: SmartDevice, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
mock_response: dict = {
|
||||
"get_device_info": SmartErrorCode.PARAMS_ERROR,
|
||||
}
|
||||
@@ -56,7 +58,7 @@ async def test_try_get_response(dev: SmartDevice, caplog):
|
||||
|
||||
@device_smart
|
||||
@pytest.mark.requires_dummy
|
||||
async def test_update_no_device_info(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_update_no_device_info(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
mock_response: dict = {
|
||||
"get_device_usage": {},
|
||||
"get_device_time": {},
|
||||
@@ -68,7 +70,9 @@ async def test_update_no_device_info(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@smart_discovery
|
||||
async def test_device_type_no_update(discovery_mock, caplog: pytest.LogCaptureFixture):
|
||||
async def test_device_type_no_update(
|
||||
discovery_mock, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test device type and repr when device not updated."""
|
||||
dev = SmartDevice(DISCOVERY_MOCK_IP)
|
||||
assert dev.device_type is DeviceType.Unknown
|
||||
@@ -96,7 +100,7 @@ async def test_device_type_no_update(discovery_mock, caplog: pytest.LogCaptureFi
|
||||
|
||||
|
||||
@device_smart
|
||||
async def test_initial_update(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_initial_update(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test the initial update cycle."""
|
||||
# As the fixture data is already initialized, we reset the state for testing
|
||||
dev._components_raw = None
|
||||
@@ -124,7 +128,7 @@ async def test_initial_update(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@device_smart
|
||||
async def test_negotiate(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_negotiate(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test that the initial negotiation performs expected steps."""
|
||||
# As the fixture data is already initialized, we reset the state for testing
|
||||
dev._components_raw = None
|
||||
@@ -158,7 +162,7 @@ async def test_negotiate(dev: SmartDevice, mocker: MockerFixture):
|
||||
|
||||
|
||||
@device_smart
|
||||
async def test_update_module_queries(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_update_module_queries(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Test that the regular update uses queries from all supported modules."""
|
||||
# We need to have some modules initialized by now
|
||||
assert dev._modules
|
||||
@@ -195,7 +199,7 @@ async def test_update_module_update_delays(
|
||||
mocker: MockerFixture,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
):
|
||||
) -> None:
|
||||
"""Test that modules with minimum delays delay."""
|
||||
# We need to have some modules initialized by now
|
||||
assert dev._modules
|
||||
@@ -253,7 +257,7 @@ async def test_hub_children_update_delays(
|
||||
mocker: MockerFixture,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
):
|
||||
) -> None:
|
||||
"""Test that hub children use the correct delay."""
|
||||
if not dev.children:
|
||||
pytest.skip(f"Device {dev.model} does not have children.")
|
||||
@@ -416,14 +420,15 @@ async def test_update_module_query_errors(
|
||||
mocker: MockerFixture,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
first_update,
|
||||
error_type,
|
||||
recover,
|
||||
):
|
||||
first_update: bool,
|
||||
error_type: SmartErrorCode | TimeoutError,
|
||||
recover: bool,
|
||||
) -> None:
|
||||
"""Test that modules that disabled / removed on query failures.
|
||||
|
||||
i.e. the whole query times out rather than device returns an error.
|
||||
"""
|
||||
caplog.set_level(logging.DEBUG)
|
||||
# We need to have some modules initialized by now
|
||||
assert dev._modules
|
||||
|
||||
@@ -480,8 +485,6 @@ async def test_update_module_query_errors(
|
||||
raise TimeoutError()
|
||||
if len(child_requests) > 1:
|
||||
raise TimeoutError()
|
||||
|
||||
if raise_error:
|
||||
resp = {
|
||||
"method": child_requests[0]["method"],
|
||||
"error_code": error_type.value,
|
||||
@@ -594,7 +597,7 @@ async def test_update_module_query_errors(
|
||||
assert emod.status is not None
|
||||
|
||||
|
||||
async def test_get_modules():
|
||||
async def test_get_modules() -> None:
|
||||
"""Test getting modules for child and parent modules."""
|
||||
dummy_device = await get_device_for_fixture_protocol(
|
||||
"KS240(US)_1.0_1.0.5.json", "SMART"
|
||||
@@ -629,7 +632,9 @@ async def test_get_modules():
|
||||
|
||||
|
||||
@device_smart
|
||||
async def test_smartdevice_cloud_connection(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_smartdevice_cloud_connection(
|
||||
dev: SmartDevice, mocker: MockerFixture
|
||||
) -> None:
|
||||
"""Test is_cloud_connected property."""
|
||||
assert isinstance(dev, SmartDevice)
|
||||
assert "cloud_connect" in dev._components
|
||||
@@ -697,7 +702,7 @@ async def test_smartdevice_cloud_connection(dev: SmartDevice, mocker: MockerFixt
|
||||
|
||||
|
||||
@variable_temp_smart
|
||||
async def test_smart_temp_range(dev: Device):
|
||||
async def test_smart_temp_range(dev: Device) -> None:
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
color_temp_feat = light.get_feature("color_temp")
|
||||
@@ -708,7 +713,7 @@ async def test_smart_temp_range(dev: Device):
|
||||
@device_smart
|
||||
async def test_initialize_modules_sysinfo_lookup_keys(
|
||||
dev: SmartDevice, mocker: MockerFixture
|
||||
):
|
||||
) -> None:
|
||||
"""Test that matching modules using SYSINFO_LOOKUP_KEYS are initialized correctly."""
|
||||
|
||||
class AvailableKey(SmartModule):
|
||||
@@ -737,7 +742,7 @@ async def test_initialize_modules_sysinfo_lookup_keys(
|
||||
@device_smart
|
||||
async def test_initialize_modules_required_component(
|
||||
dev: SmartDevice, mocker: MockerFixture
|
||||
):
|
||||
) -> None:
|
||||
"""Test that matching modules using REQUIRED_COMPONENT are initialized correctly."""
|
||||
|
||||
class AvailableComponent(SmartModule):
|
||||
@@ -763,7 +768,7 @@ async def test_initialize_modules_required_component(
|
||||
assert "NonExistingComponent" not in dev.modules
|
||||
|
||||
|
||||
async def test_smartmodule_query():
|
||||
async def test_smartmodule_query() -> None:
|
||||
"""Test that a module that doesn't set QUERY_GETTER_NAME has empty query."""
|
||||
|
||||
class DummyModule(SmartModule):
|
||||
@@ -779,7 +784,7 @@ async def test_smartmodule_query():
|
||||
@hub_all
|
||||
@pytest.mark.xdist_group(name="caplog")
|
||||
@pytest.mark.requires_dummy
|
||||
async def test_dynamic_devices(dev: Device, caplog: pytest.LogCaptureFixture):
|
||||
async def test_dynamic_devices(dev: Device, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test dynamic child devices."""
|
||||
if not dev.children:
|
||||
pytest.skip(f"Device {dev.model} does not have children.")
|
||||
@@ -992,7 +997,7 @@ async def test_dynamic_devices(dev: Device, caplog: pytest.LogCaptureFixture):
|
||||
|
||||
|
||||
@hubs_smart
|
||||
async def test_unpair(dev: SmartDevice, mocker: MockerFixture):
|
||||
async def test_unpair(dev: SmartDevice, mocker: MockerFixture) -> None:
|
||||
"""Verify that unpair calls childsetup module."""
|
||||
if not dev.children:
|
||||
pytest.skip("device has no children")
|
||||
|
||||
Reference in New Issue
Block a user