mirror of
https://github.com/python-kasa/python-kasa.git
synced 2026-07-08 06:41:59 +00:00
tests: add type annotations to IoT tests (#1685)
Add type annotations to all test functions across 8 files in `tests/iot/`, improving type safety and enabling mypy to check function bodies.
This commit is contained in:
@@ -8,7 +8,7 @@ from ...device_fixtures import dimmer_iot
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
def test_ambientlight_getters(dev: IotDimmer):
|
||||
def test_ambientlight_getters(dev: IotDimmer) -> None:
|
||||
assert Module.IotAmbientLight in dev.modules
|
||||
ambientlight: AmbientLight = dev.modules[Module.IotAmbientLight]
|
||||
|
||||
@@ -22,7 +22,7 @@ def test_ambientlight_getters(dev: IotDimmer):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_ambientlight_setters(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_ambientlight_setters(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
ambientlight: AmbientLight = dev.modules[Module.IotAmbientLight]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -36,7 +36,7 @@ async def test_ambientlight_setters(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
def test_ambientlight_feature(dev: IotDimmer):
|
||||
def test_ambientlight_feature(dev: IotDimmer) -> None:
|
||||
assert Module.IotAmbientLight in dev.modules
|
||||
ambientlight: AmbientLight = dev.modules[Module.IotAmbientLight]
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from ...device_fixtures import device_iot
|
||||
|
||||
|
||||
@device_iot
|
||||
def test_cloud(dev: Device):
|
||||
def test_cloud(dev: Device) -> None:
|
||||
cloud = dev.modules.get(Module.IotCloud)
|
||||
assert cloud
|
||||
info = cloud.info
|
||||
|
||||
@@ -14,7 +14,7 @@ _TD_ONE_MS: Final[timedelta] = timedelta(milliseconds=1)
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
def test_dimmer_getters(dev: IotDimmer):
|
||||
def test_dimmer_getters(dev: IotDimmer) -> None:
|
||||
assert Module.IotDimmer in dev.modules
|
||||
dimmer: Dimmer = dev.modules[Module.IotDimmer]
|
||||
|
||||
@@ -27,7 +27,7 @@ def test_dimmer_getters(dev: IotDimmer):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_dimmer_setters(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_dimmer_setters(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
dimmer: Dimmer = dev.modules[Module.IotDimmer]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -65,7 +65,7 @@ async def test_dimmer_setters(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_dimmer_setter_min(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_dimmer_setter_min(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
dimmer: Dimmer = dev.modules[Module.IotDimmer]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -103,7 +103,7 @@ async def test_dimmer_setter_min(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_dimmer_setter_max(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_dimmer_setter_max(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
dimmer: Dimmer = dev.modules[Module.IotDimmer]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -141,7 +141,7 @@ async def test_dimmer_setter_max(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_dimmer_setters_min_oob(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_dimmer_setters_min_oob(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
dimmer: Dimmer = dev.modules[Module.IotDimmer]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -173,7 +173,7 @@ async def test_dimmer_setters_min_oob(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_dimmer_setters_max_oob(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_dimmer_setters_max_oob(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
dimmer: Dimmer = dev.modules[Module.IotDimmer]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from voluptuous import (
|
||||
|
||||
from kasa import Device, DeviceType, EmeterStatus, Module
|
||||
from kasa.interfaces.energy import Energy
|
||||
from kasa.iot import IotStrip
|
||||
from kasa.iot import IotDevice, IotStrip
|
||||
from kasa.iot.modules.emeter import Emeter
|
||||
from tests.conftest import has_emeter_iot, no_emeter_iot
|
||||
|
||||
@@ -37,22 +37,22 @@ CURRENT_CONSUMPTION_SCHEMA = Schema(
|
||||
|
||||
|
||||
@no_emeter_iot
|
||||
async def test_no_emeter(dev):
|
||||
async def test_no_emeter(dev: IotDevice) -> None:
|
||||
assert not dev.has_emeter
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
await dev.get_emeter_realtime()
|
||||
await dev.get_emeter_realtime() # type: ignore[attr-defined]
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
await dev.get_emeter_daily()
|
||||
await dev.get_emeter_daily() # type: ignore[attr-defined]
|
||||
with pytest.raises(AttributeError):
|
||||
await dev.get_emeter_monthly()
|
||||
await dev.get_emeter_monthly() # type: ignore[attr-defined]
|
||||
with pytest.raises(AttributeError):
|
||||
await dev.erase_emeter_stats()
|
||||
await dev.erase_emeter_stats() # type: ignore[attr-defined]
|
||||
|
||||
|
||||
@has_emeter_iot
|
||||
async def test_get_emeter_realtime(dev):
|
||||
async def test_get_emeter_realtime(dev: IotDevice) -> None:
|
||||
emeter = dev.modules[Module.Energy]
|
||||
|
||||
current_emeter = await emeter.get_status()
|
||||
@@ -65,7 +65,7 @@ async def test_get_emeter_realtime(dev):
|
||||
|
||||
@has_emeter_iot
|
||||
@pytest.mark.requires_dummy
|
||||
async def test_get_emeter_daily(dev):
|
||||
async def test_get_emeter_daily(dev: IotDevice) -> None:
|
||||
emeter = dev.modules[Module.Energy]
|
||||
|
||||
assert await emeter.get_daily_stats(year=1900, month=1) == {}
|
||||
@@ -85,7 +85,7 @@ async def test_get_emeter_daily(dev):
|
||||
|
||||
@has_emeter_iot
|
||||
@pytest.mark.requires_dummy
|
||||
async def test_get_emeter_monthly(dev):
|
||||
async def test_get_emeter_monthly(dev: IotDevice) -> None:
|
||||
emeter = dev.modules[Module.Energy]
|
||||
|
||||
assert await emeter.get_monthly_stats(year=1900) == {}
|
||||
@@ -104,7 +104,7 @@ async def test_get_emeter_monthly(dev):
|
||||
|
||||
|
||||
@has_emeter_iot
|
||||
async def test_emeter_status(dev):
|
||||
async def test_emeter_status(dev: IotDevice) -> None:
|
||||
emeter = dev.modules[Module.Energy]
|
||||
|
||||
d = await emeter.get_status()
|
||||
@@ -126,21 +126,21 @@ async def test_emeter_status(dev):
|
||||
|
||||
@pytest.mark.skip("not clearing your stats..")
|
||||
@has_emeter_iot
|
||||
async def test_erase_emeter_stats(dev):
|
||||
async def test_erase_emeter_stats(dev: IotDevice) -> None:
|
||||
emeter = dev.modules[Module.Energy]
|
||||
|
||||
await emeter.erase_emeter()
|
||||
|
||||
|
||||
@has_emeter_iot
|
||||
async def test_current_consumption(dev):
|
||||
async def test_current_consumption(dev: IotDevice) -> None:
|
||||
emeter = dev.modules[Module.Energy]
|
||||
x = emeter.current_consumption
|
||||
assert isinstance(x, float)
|
||||
assert x >= 0.0
|
||||
|
||||
|
||||
async def test_emeterstatus_missing_current():
|
||||
async def test_emeterstatus_missing_current() -> None:
|
||||
"""KL125 does not report 'current' for emeter."""
|
||||
regular = EmeterStatus(
|
||||
{"err_code": 0, "power_mw": 0, "total_wh": 13, "current_ma": 123}
|
||||
@@ -154,13 +154,13 @@ async def test_emeterstatus_missing_current():
|
||||
assert missing_current["current"] is None
|
||||
|
||||
|
||||
async def test_emeter_daily():
|
||||
async def test_emeter_daily() -> None:
|
||||
"""Test fetching the emeter for today.
|
||||
|
||||
This test uses inline data since the fixtures
|
||||
will not have data for the current day.
|
||||
"""
|
||||
emeter_data = {
|
||||
emeter_data: dict = {
|
||||
"get_daystat": {
|
||||
"day_list": [{"day": 1, "energy_wh": 8, "month": 1, "year": 2023}],
|
||||
"err_code": 0,
|
||||
@@ -181,7 +181,7 @@ async def test_emeter_daily():
|
||||
|
||||
|
||||
@has_emeter_iot
|
||||
async def test_supported(dev: Device):
|
||||
async def test_supported(dev: Device) -> None:
|
||||
energy_module = dev.modules.get(Module.Energy)
|
||||
assert energy_module
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ from ...device_fixtures import device_iot
|
||||
|
||||
|
||||
@device_iot
|
||||
def test_homekit_getters(dev: IotDevice):
|
||||
def test_homekit_getters(dev: IotDevice) -> None:
|
||||
# HomeKit can be present on any IOT device
|
||||
if Module.IotHomeKit not in dev.modules:
|
||||
pytest.skip("HomeKit module not present on this device")
|
||||
@@ -31,7 +31,7 @@ def test_homekit_getters(dev: IotDevice):
|
||||
|
||||
|
||||
@device_iot
|
||||
def test_homekit_feature(dev: IotDevice):
|
||||
def test_homekit_feature(dev: IotDevice) -> None:
|
||||
if Module.IotHomeKit not in dev.modules:
|
||||
pytest.skip("HomeKit module not present on this device")
|
||||
homekit: HomeKit = dev.modules[Module.IotHomeKit]
|
||||
@@ -45,7 +45,7 @@ def test_homekit_feature(dev: IotDevice):
|
||||
|
||||
|
||||
@device_iot
|
||||
def test_initialize_features_skips_when_no_data(dev: IotDevice):
|
||||
def test_initialize_features_skips_when_no_data(dev: IotDevice) -> None:
|
||||
if Module.IotHomeKit not in dev.modules:
|
||||
pytest.skip("HomeKit module not present on this device")
|
||||
homekit: HomeKit = dev.modules[Module.IotHomeKit]
|
||||
|
||||
@@ -9,7 +9,7 @@ from ...device_fixtures import dimmer_iot
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
def test_motion_getters(dev: IotDimmer):
|
||||
def test_motion_getters(dev: IotDimmer) -> None:
|
||||
assert Module.IotMotion in dev.modules
|
||||
motion: Motion = dev.modules[Module.IotMotion]
|
||||
|
||||
@@ -19,7 +19,7 @@ def test_motion_getters(dev: IotDimmer):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_motion_setters(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_motion_setters(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
motion: Motion = dev.modules[Module.IotMotion]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -33,7 +33,7 @@ async def test_motion_setters(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_motion_range(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_motion_range(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
motion: Motion = dev.modules[Module.IotMotion]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -47,7 +47,7 @@ async def test_motion_range(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_motion_range_from_string(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_motion_range_from_string(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
motion: Motion = dev.modules[Module.IotMotion]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -74,7 +74,7 @@ async def test_motion_range_from_string(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_motion_threshold(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_motion_threshold(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
motion: Motion = dev.modules[Module.IotMotion]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -97,7 +97,7 @@ async def test_motion_threshold(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_motion_realtime(dev: IotDimmer, mocker: MockerFixture):
|
||||
async def test_motion_realtime(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
motion: Motion = dev.modules[Module.IotMotion]
|
||||
query_helper = mocker.patch("kasa.iot.IotDimmer._query_helper")
|
||||
|
||||
@@ -106,7 +106,7 @@ async def test_motion_realtime(dev: IotDimmer, mocker: MockerFixture):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
def test_motion_feature(dev: IotDimmer):
|
||||
def test_motion_feature(dev: IotDimmer) -> None:
|
||||
assert Module.IotMotion in dev.modules
|
||||
motion: Motion = dev.modules[Module.IotMotion]
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from ...device_fixtures import device_iot
|
||||
|
||||
@device_iot
|
||||
@pytest.mark.xdist_group(name="caplog")
|
||||
def test_schedule(dev: Device, caplog: pytest.LogCaptureFixture):
|
||||
def test_schedule(dev: Device, caplog: pytest.LogCaptureFixture) -> None:
|
||||
schedule = dev.modules.get(Module.IotSchedule)
|
||||
assert schedule
|
||||
if rules := schedule.rules:
|
||||
|
||||
@@ -4,10 +4,10 @@ from unittest.mock import Mock
|
||||
from kasa.iot.modules import Usage
|
||||
|
||||
|
||||
def test_usage_convert_stat_data():
|
||||
usage = Usage(None, module="usage")
|
||||
def test_usage_convert_stat_data() -> None:
|
||||
usage = Usage(Mock(), module="usage")
|
||||
|
||||
test_data = []
|
||||
test_data: list[dict[str, int]] = []
|
||||
assert usage._convert_stat_data(test_data, "day") == {}
|
||||
|
||||
test_data = [
|
||||
@@ -24,13 +24,13 @@ def test_usage_convert_stat_data():
|
||||
assert v == 30
|
||||
|
||||
|
||||
def test_usage_today():
|
||||
def test_usage_today() -> None:
|
||||
"""Test fetching the usage for today.
|
||||
|
||||
This test uses inline data since the fixtures
|
||||
will not have data for the current day.
|
||||
"""
|
||||
emeter_data = {
|
||||
emeter_data: dict = {
|
||||
"get_daystat": {
|
||||
"day_list": [],
|
||||
"err_code": 0,
|
||||
@@ -55,13 +55,13 @@ def test_usage_today():
|
||||
assert usage.usage_today == 500
|
||||
|
||||
|
||||
def test_usage_this_month():
|
||||
def test_usage_this_month() -> None:
|
||||
"""Test fetching the usage for this month.
|
||||
|
||||
This test uses inline data since the fixtures
|
||||
will not have data for the current month.
|
||||
"""
|
||||
emeter_data = {
|
||||
emeter_data: dict = {
|
||||
"get_monthstat": {
|
||||
"month_list": [],
|
||||
"err_code": 0,
|
||||
|
||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
import re
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
from voluptuous import (
|
||||
All,
|
||||
Boolean,
|
||||
@@ -27,7 +28,7 @@ from tests.iot.test_iotdevice import SYSINFO_SCHEMA
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_bulb_sysinfo(dev: Device):
|
||||
async def test_bulb_sysinfo(dev: Device) -> None:
|
||||
assert dev.sys_info is not None
|
||||
SYSINFO_SCHEMA_BULB(dev.sys_info)
|
||||
|
||||
@@ -35,19 +36,21 @@ async def test_bulb_sysinfo(dev: Device):
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_light_state_without_update(dev: IotBulb, monkeypatch):
|
||||
async def test_light_state_without_update(
|
||||
dev: IotBulb, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
monkeypatch.setitem(dev._last_update["system"]["get_sysinfo"], "light_state", None)
|
||||
with pytest.raises(KasaException):
|
||||
print(dev.light_state)
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_get_light_state(dev: IotBulb):
|
||||
async def test_get_light_state(dev: IotBulb) -> None:
|
||||
LIGHT_STATE_SCHEMA(await dev.get_light_state())
|
||||
|
||||
|
||||
@color_bulb_iot
|
||||
async def test_set_hsv_transition(dev: IotBulb, mocker):
|
||||
async def test_set_hsv_transition(dev: IotBulb, mocker: MockerFixture) -> None:
|
||||
set_light_state = mocker.patch("kasa.iot.IotBulb._set_light_state")
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
@@ -60,7 +63,7 @@ async def test_set_hsv_transition(dev: IotBulb, mocker):
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_light_set_state(dev: IotBulb, mocker):
|
||||
async def test_light_set_state(dev: IotBulb, mocker: MockerFixture) -> None:
|
||||
"""Testing setting LightState on the light module."""
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
@@ -76,7 +79,7 @@ async def test_light_set_state(dev: IotBulb, mocker):
|
||||
|
||||
|
||||
@variable_temp_iot
|
||||
async def test_set_color_temp_transition(dev: IotBulb, mocker):
|
||||
async def test_set_color_temp_transition(dev: IotBulb, mocker: MockerFixture) -> None:
|
||||
set_light_state = mocker.patch("kasa.iot.IotBulb._set_light_state")
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
@@ -87,7 +90,9 @@ async def test_set_color_temp_transition(dev: IotBulb, mocker):
|
||||
|
||||
@variable_temp_iot
|
||||
@pytest.mark.xdist_group(name="caplog")
|
||||
async def test_unknown_temp_range(dev: IotBulb, monkeypatch, caplog):
|
||||
async def test_unknown_temp_range(
|
||||
dev: IotBulb, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
monkeypatch.setitem(dev._sys_info, "model", "unknown bulb")
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
@@ -99,7 +104,7 @@ async def test_unknown_temp_range(dev: IotBulb, monkeypatch, caplog):
|
||||
|
||||
@dimmable_iot
|
||||
@turn_on
|
||||
async def test_dimmable_brightness(dev: IotBulb, turn_on):
|
||||
async def test_dimmable_brightness(dev: IotBulb, turn_on: bool) -> None:
|
||||
assert isinstance(dev, IotBulb | IotDimmer)
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
@@ -119,7 +124,7 @@ async def test_dimmable_brightness(dev: IotBulb, turn_on):
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_turn_on_transition(dev: IotBulb, mocker):
|
||||
async def test_turn_on_transition(dev: IotBulb, mocker: MockerFixture) -> None:
|
||||
set_light_state = mocker.patch("kasa.iot.IotBulb._set_light_state")
|
||||
await dev.turn_on(transition=1000)
|
||||
|
||||
@@ -131,7 +136,9 @@ async def test_turn_on_transition(dev: IotBulb, mocker):
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_dimmable_brightness_transition(dev: IotBulb, mocker):
|
||||
async def test_dimmable_brightness_transition(
|
||||
dev: IotBulb, mocker: MockerFixture
|
||||
) -> None:
|
||||
set_light_state = mocker.patch("kasa.iot.IotBulb._set_light_state")
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
@@ -141,7 +148,7 @@ async def test_dimmable_brightness_transition(dev: IotBulb, mocker):
|
||||
|
||||
|
||||
@dimmable_iot
|
||||
async def test_invalid_brightness(dev: IotBulb):
|
||||
async def test_invalid_brightness(dev: IotBulb) -> None:
|
||||
assert dev._is_dimmable
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
@@ -159,7 +166,7 @@ async def test_invalid_brightness(dev: IotBulb):
|
||||
|
||||
|
||||
@non_dimmable_iot
|
||||
async def test_non_dimmable(dev: IotBulb):
|
||||
async def test_non_dimmable(dev: IotBulb) -> None:
|
||||
assert not dev._is_dimmable
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
@@ -171,8 +178,8 @@ async def test_non_dimmable(dev: IotBulb):
|
||||
|
||||
@bulb_iot
|
||||
async def test_ignore_default_not_set_without_color_mode_change_turn_on(
|
||||
dev: IotBulb, mocker
|
||||
):
|
||||
dev: IotBulb, mocker: MockerFixture
|
||||
) -> None:
|
||||
query_helper = mocker.patch("kasa.iot.IotBulb._query_helper")
|
||||
# When turning back without settings, ignore default to restore the state
|
||||
await dev.turn_on()
|
||||
@@ -185,7 +192,7 @@ async def test_ignore_default_not_set_without_color_mode_change_turn_on(
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_list_presets(dev: IotBulb):
|
||||
async def test_list_presets(dev: IotBulb) -> None:
|
||||
light_preset = dev.modules.get(Module.LightPreset)
|
||||
assert light_preset
|
||||
assert isinstance(light_preset, IotLightPresetModule)
|
||||
@@ -206,7 +213,7 @@ async def test_list_presets(dev: IotBulb):
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_modify_preset(dev: IotBulb, mocker):
|
||||
async def test_modify_preset(dev: IotBulb, mocker: MockerFixture) -> None:
|
||||
"""Verify that modifying preset calls the and exceptions are raised properly."""
|
||||
if (
|
||||
not (light_preset := dev.modules.get(Module.LightPreset))
|
||||
@@ -254,7 +261,9 @@ async def test_modify_preset(dev: IotBulb, mocker):
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_modify_preset_payloads(dev: IotBulb, preset, payload, mocker):
|
||||
async def test_modify_preset_payloads(
|
||||
dev: IotBulb, preset, payload, mocker: MockerFixture
|
||||
) -> None:
|
||||
"""Test that modify preset payloads ignore none values."""
|
||||
if (
|
||||
not (light_preset := dev.modules.get(Module.LightPreset))
|
||||
@@ -318,6 +327,6 @@ SYSINFO_SCHEMA_BULB = SYSINFO_SCHEMA.extend(
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_turn_on_behaviours(dev: IotBulb):
|
||||
async def test_turn_on_behaviours(dev: IotBulb) -> None:
|
||||
behavior = await dev.get_turn_on_behavior()
|
||||
assert behavior
|
||||
|
||||
@@ -4,6 +4,7 @@ import re
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
from voluptuous import (
|
||||
REMOVE_EXTRA,
|
||||
All,
|
||||
@@ -84,20 +85,20 @@ SYSINFO_SCHEMA = Schema(
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_state_info(dev):
|
||||
async def test_state_info(dev: IotDevice) -> None:
|
||||
assert isinstance(dev.state_information, dict)
|
||||
|
||||
|
||||
@pytest.mark.requires_dummy
|
||||
@device_iot
|
||||
async def test_invalid_connection(mocker, dev):
|
||||
async def test_invalid_connection(mocker: MockerFixture, dev: IotDevice) -> None:
|
||||
mocker.patch.object(FakeIotProtocol, "query", side_effect=KasaException)
|
||||
with pytest.raises(KasaException):
|
||||
await dev.update()
|
||||
|
||||
|
||||
@has_emeter_iot
|
||||
async def test_initial_update_emeter(dev, mocker):
|
||||
async def test_initial_update_emeter(dev: IotDevice, mocker: MockerFixture) -> None:
|
||||
"""Test that the initial update performs second query if emeter is available."""
|
||||
dev._last_update = {}
|
||||
dev._legacy_features = set()
|
||||
@@ -109,7 +110,7 @@ async def test_initial_update_emeter(dev, mocker):
|
||||
|
||||
|
||||
@no_emeter_iot
|
||||
async def test_initial_update_no_emeter(dev, mocker):
|
||||
async def test_initial_update_no_emeter(dev: IotDevice, mocker: MockerFixture) -> None:
|
||||
"""Test that the initial update performs second query if emeter is available."""
|
||||
dev._last_update = {}
|
||||
dev._legacy_features = set()
|
||||
@@ -128,7 +129,7 @@ async def test_initial_update_no_emeter(dev, mocker):
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_query_helper(dev):
|
||||
async def test_query_helper(dev: IotDevice) -> None:
|
||||
with pytest.raises(KasaException):
|
||||
await dev._query_helper("test", "testcmd", {})
|
||||
# TODO check for unwrapping?
|
||||
@@ -136,7 +137,7 @@ async def test_query_helper(dev):
|
||||
|
||||
@device_iot
|
||||
@turn_on
|
||||
async def test_state(dev, turn_on):
|
||||
async def test_state(dev: IotDevice, turn_on: bool) -> None:
|
||||
orig_state = dev.is_on
|
||||
await handle_turn_on(dev, turn_on)
|
||||
await dev.update()
|
||||
@@ -164,7 +165,7 @@ async def test_state(dev, turn_on):
|
||||
|
||||
@device_iot
|
||||
@turn_on
|
||||
async def test_on_since(dev, turn_on):
|
||||
async def test_on_since(dev: IotDevice, turn_on: bool) -> None:
|
||||
await handle_turn_on(dev, turn_on)
|
||||
orig_state = dev.is_on
|
||||
if "on_time" not in dev.sys_info and dev.device_type is not DeviceType.Strip:
|
||||
@@ -176,43 +177,43 @@ async def test_on_since(dev, turn_on):
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_time(dev):
|
||||
async def test_time(dev: IotDevice) -> None:
|
||||
assert isinstance(dev.modules[Module.Time].time, datetime)
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_timezone(dev):
|
||||
async def test_timezone(dev: IotDevice) -> None:
|
||||
TZ_SCHEMA(await dev.modules[Module.Time].get_timezone())
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_hw_info(dev):
|
||||
async def test_hw_info(dev: IotDevice) -> None:
|
||||
SYSINFO_SCHEMA(dev.hw_info)
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_location(dev):
|
||||
async def test_location(dev: IotDevice) -> None:
|
||||
SYSINFO_SCHEMA(dev.location)
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_rssi(dev):
|
||||
async def test_rssi(dev: IotDevice) -> None:
|
||||
SYSINFO_SCHEMA({"rssi": dev.rssi}) # wrapping for vol
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_mac(dev):
|
||||
async def test_mac(dev: IotDevice) -> None:
|
||||
SYSINFO_SCHEMA({"mac": dev.mac}) # wrapping for val
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_representation(dev):
|
||||
async def test_representation(dev: IotDevice) -> None:
|
||||
pattern = re.compile(r"<DeviceType\..+ at .+? - .*? \(.+?\)>")
|
||||
assert pattern.match(str(dev))
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_children(dev):
|
||||
async def test_children(dev: IotDevice) -> None:
|
||||
"""Make sure that children property is exposed by every device."""
|
||||
if dev.device_type is DeviceType.Strip:
|
||||
assert len(dev.children) > 0
|
||||
@@ -221,7 +222,7 @@ async def test_children(dev):
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_modules_preserved(dev: IotDevice):
|
||||
async def test_modules_preserved(dev: IotDevice) -> None:
|
||||
"""Make modules that are not being updated are preserved between updates."""
|
||||
dev._last_update["some_module_not_being_updated"] = "should_be_kept"
|
||||
await dev.update()
|
||||
@@ -229,13 +230,13 @@ async def test_modules_preserved(dev: IotDevice):
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_internal_state(dev):
|
||||
async def test_internal_state(dev: IotDevice) -> None:
|
||||
"""Make sure the internal state returns the last update results."""
|
||||
assert dev.internal_state == dev._last_update
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_features(dev):
|
||||
async def test_features(dev: IotDevice) -> None:
|
||||
"""Make sure features is always accessible."""
|
||||
sysinfo = dev._last_update["system"]["get_sysinfo"]
|
||||
if "feature" in sysinfo:
|
||||
@@ -245,20 +246,20 @@ async def test_features(dev):
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_max_device_response_size(dev):
|
||||
async def test_max_device_response_size(dev: IotDevice) -> None:
|
||||
"""Make sure every device return has a set max response size."""
|
||||
assert dev.max_device_response_size > 0
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_estimated_response_sizes(dev):
|
||||
async def test_estimated_response_sizes(dev: IotDevice) -> None:
|
||||
"""Make sure every module has an estimated response size set."""
|
||||
for mod in dev.modules.values():
|
||||
assert mod.estimated_query_response_size > 0
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_modules_not_supported(dev: IotDevice):
|
||||
async def test_modules_not_supported(dev: IotDevice) -> None:
|
||||
"""Test that unsupported modules do not break the device."""
|
||||
for module in dev.modules.values():
|
||||
assert module.is_supported is not None
|
||||
@@ -267,7 +268,7 @@ async def test_modules_not_supported(dev: IotDevice):
|
||||
assert module.is_supported 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(
|
||||
"HS100(US)_2.0_1.5.6.json", "IOT"
|
||||
@@ -293,10 +294,10 @@ async def test_get_modules():
|
||||
assert module is None
|
||||
|
||||
|
||||
def test_merge_dict():
|
||||
def test_merge_dict() -> None:
|
||||
"""Test the recursive dict merge."""
|
||||
dest = {"a": 1, "b": {"c": 2, "d": 3}}
|
||||
source = {"b": {"c": 4, "e": 5}}
|
||||
dest: dict = {"a": 1, "b": {"c": 2, "d": 3}}
|
||||
source: dict = {"b": {"c": 4, "e": 5}}
|
||||
assert _merge_dict(dest, source) == {"a": 1, "b": {"c": 4, "d": 3, "e": 5}}
|
||||
|
||||
dest = {"smartlife.iot.common.emeter": {"get_realtime": None}}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from kasa import DeviceType, Module
|
||||
from kasa.iot import IotDimmer
|
||||
@@ -6,7 +7,7 @@ from tests.conftest import dimmer_iot, handle_turn_on, turn_on
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_set_brightness(dev):
|
||||
async def test_set_brightness(dev: IotDimmer) -> None:
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
await handle_turn_on(dev, False)
|
||||
@@ -26,7 +27,9 @@ async def test_set_brightness(dev):
|
||||
|
||||
@dimmer_iot
|
||||
@turn_on
|
||||
async def test_set_brightness_transition(dev, turn_on, mocker):
|
||||
async def test_set_brightness_transition(
|
||||
dev: IotDimmer, turn_on: bool, mocker: MockerFixture
|
||||
) -> None:
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
await handle_turn_on(dev, turn_on)
|
||||
@@ -49,7 +52,7 @@ async def test_set_brightness_transition(dev, turn_on, mocker):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_set_brightness_invalid(dev):
|
||||
async def test_set_brightness_invalid(dev: IotDimmer) -> None:
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
for invalid_brightness in [-1, 101]:
|
||||
@@ -62,7 +65,7 @@ async def test_set_brightness_invalid(dev):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_set_brightness_invalid_transition(dev):
|
||||
async def test_set_brightness_invalid_transition(dev: IotDimmer) -> None:
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
for invalid_transition in [-1]:
|
||||
@@ -74,7 +77,7 @@ async def test_set_brightness_invalid_transition(dev):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_turn_on_transition(dev, mocker):
|
||||
async def test_turn_on_transition(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
query_helper = mocker.spy(IotDimmer, "_query_helper")
|
||||
@@ -93,7 +96,7 @@ async def test_turn_on_transition(dev, mocker):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_turn_off_transition(dev, mocker):
|
||||
async def test_turn_off_transition(dev: IotDimmer, mocker: MockerFixture) -> None:
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
await handle_turn_on(dev, True)
|
||||
@@ -115,7 +118,9 @@ async def test_turn_off_transition(dev, mocker):
|
||||
|
||||
@dimmer_iot
|
||||
@turn_on
|
||||
async def test_set_dimmer_transition(dev, turn_on, mocker):
|
||||
async def test_set_dimmer_transition(
|
||||
dev: IotDimmer, turn_on: bool, mocker: MockerFixture
|
||||
) -> None:
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
await handle_turn_on(dev, turn_on)
|
||||
@@ -135,7 +140,9 @@ async def test_set_dimmer_transition(dev, turn_on, mocker):
|
||||
|
||||
@dimmer_iot
|
||||
@turn_on
|
||||
async def test_set_dimmer_transition_to_off(dev, turn_on, mocker):
|
||||
async def test_set_dimmer_transition_to_off(
|
||||
dev: IotDimmer, turn_on: bool, mocker: MockerFixture
|
||||
) -> None:
|
||||
light = dev.modules.get(Module.Light)
|
||||
assert light
|
||||
await handle_turn_on(dev, turn_on)
|
||||
@@ -156,26 +163,26 @@ async def test_set_dimmer_transition_to_off(dev, turn_on, mocker):
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_set_dimmer_transition_invalid_brightness(dev):
|
||||
async def test_set_dimmer_transition_invalid_brightness(dev: IotDimmer) -> None:
|
||||
for invalid_brightness in [-1, 101]:
|
||||
with pytest.raises(ValueError, match="Invalid brightness value: "):
|
||||
await dev.set_dimmer_transition(invalid_brightness, 1000)
|
||||
|
||||
for invalid_type in [0.5, "foo"]:
|
||||
with pytest.raises(TypeError, match="Transition must be integer"):
|
||||
await dev.set_dimmer_transition(1, invalid_type)
|
||||
await dev.set_dimmer_transition(1, invalid_type) # type: ignore[arg-type]
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
async def test_set_dimmer_transition_invalid_transition(dev):
|
||||
async def test_set_dimmer_transition_invalid_transition(dev: IotDimmer) -> None:
|
||||
for invalid_transition in [-1]:
|
||||
with pytest.raises(ValueError, match="Transition value .+? is not valid."):
|
||||
await dev.set_dimmer_transition(1, transition=invalid_transition)
|
||||
for invalid_type in [0.5, "foo"]:
|
||||
with pytest.raises(TypeError, match="Transition must be integer"):
|
||||
await dev.set_dimmer_transition(1, transition=invalid_type)
|
||||
await dev.set_dimmer_transition(1, transition=invalid_type) # type: ignore[arg-type]
|
||||
|
||||
|
||||
@dimmer_iot
|
||||
def test_device_type_dimmer(dev):
|
||||
def test_device_type_dimmer(dev: IotDimmer) -> None:
|
||||
assert dev.device_type == DeviceType.Dimmer
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from kasa import DeviceType, Module
|
||||
from kasa.iot import IotLightStrip
|
||||
@@ -7,13 +8,13 @@ from tests.conftest import lightstrip_iot
|
||||
|
||||
|
||||
@lightstrip_iot
|
||||
async def test_lightstrip_length(dev: IotLightStrip):
|
||||
async def test_lightstrip_length(dev: IotLightStrip) -> None:
|
||||
assert dev.device_type == DeviceType.LightStrip
|
||||
assert dev.length == dev.sys_info["length"]
|
||||
|
||||
|
||||
@lightstrip_iot
|
||||
async def test_lightstrip_effect(dev: IotLightStrip):
|
||||
async def test_lightstrip_effect(dev: IotLightStrip) -> None:
|
||||
le: LightEffect = dev.modules[Module.LightEffect]
|
||||
assert isinstance(le._deprecated_effect, dict)
|
||||
for k in ["brightness", "custom", "enable", "id", "name"]:
|
||||
@@ -21,7 +22,7 @@ async def test_lightstrip_effect(dev: IotLightStrip):
|
||||
|
||||
|
||||
@lightstrip_iot
|
||||
async def test_effects_lightstrip_set_effect(dev: IotLightStrip):
|
||||
async def test_effects_lightstrip_set_effect(dev: IotLightStrip) -> None:
|
||||
le: LightEffect = dev.modules[Module.LightEffect]
|
||||
with pytest.raises(
|
||||
ValueError, match="The effect Not real is not a built in effect"
|
||||
@@ -36,8 +37,8 @@ async def test_effects_lightstrip_set_effect(dev: IotLightStrip):
|
||||
@lightstrip_iot
|
||||
@pytest.mark.parametrize("brightness", [100, 50])
|
||||
async def test_effects_lightstrip_set_effect_brightness(
|
||||
dev: IotLightStrip, brightness, mocker
|
||||
):
|
||||
dev: IotLightStrip, brightness: int, mocker: MockerFixture
|
||||
) -> None:
|
||||
query_helper = mocker.patch("kasa.iot.IotLightStrip._query_helper")
|
||||
le: LightEffect = dev.modules[Module.LightEffect]
|
||||
|
||||
@@ -55,8 +56,8 @@ async def test_effects_lightstrip_set_effect_brightness(
|
||||
@lightstrip_iot
|
||||
@pytest.mark.parametrize("transition", [500, 1000])
|
||||
async def test_effects_lightstrip_set_effect_transition(
|
||||
dev: IotLightStrip, transition, mocker
|
||||
):
|
||||
dev: IotLightStrip, transition: int, mocker: MockerFixture
|
||||
) -> None:
|
||||
query_helper = mocker.patch("kasa.iot.IotLightStrip._query_helper")
|
||||
le: LightEffect = dev.modules[Module.LightEffect]
|
||||
|
||||
@@ -72,12 +73,12 @@ async def test_effects_lightstrip_set_effect_transition(
|
||||
|
||||
|
||||
@lightstrip_iot
|
||||
async def test_effects_lightstrip_has_effects(dev: IotLightStrip):
|
||||
async def test_effects_lightstrip_has_effects(dev: IotLightStrip) -> None:
|
||||
le: LightEffect = dev.modules[Module.LightEffect]
|
||||
assert le is not None
|
||||
assert le.effect_list
|
||||
|
||||
|
||||
@lightstrip_iot
|
||||
def test_device_type_lightstrip(dev):
|
||||
def test_device_type_lightstrip(dev: IotLightStrip) -> None:
|
||||
assert dev.device_type == DeviceType.LightStrip
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from kasa import Module
|
||||
from kasa.iot import IotStrip
|
||||
from kasa.iot.iotstrip import IotStripPlug
|
||||
from tests.conftest import strip_emeter_iot, strip_iot
|
||||
|
||||
|
||||
@strip_iot
|
||||
async def test_strip_update_and_child_update_behaviors(dev):
|
||||
async def test_strip_update_and_child_update_behaviors(dev: IotStrip) -> None:
|
||||
await dev.update()
|
||||
await dev.update(update_children=False)
|
||||
|
||||
@@ -18,9 +22,10 @@ async def test_strip_update_and_child_update_behaviors(dev):
|
||||
|
||||
|
||||
@strip_iot
|
||||
async def test_strip_child_delegated_properties(dev):
|
||||
async def test_strip_child_delegated_properties(dev: IotStrip) -> None:
|
||||
await dev.update()
|
||||
child = dev.children[0]
|
||||
assert isinstance(child, IotStripPlug)
|
||||
|
||||
assert child.led is False
|
||||
assert child.time == dev.time
|
||||
@@ -32,7 +37,7 @@ async def test_strip_child_delegated_properties(dev):
|
||||
|
||||
|
||||
@strip_emeter_iot
|
||||
async def test_strip_emeter_erase_stats(dev, mocker):
|
||||
async def test_strip_emeter_erase_stats(dev: IotStrip, mocker: MockerFixture) -> None:
|
||||
await dev.update()
|
||||
|
||||
for child in dev.children:
|
||||
|
||||
@@ -5,7 +5,7 @@ import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
|
||||
def test_expected_dst_behavior_for_index_cases():
|
||||
def test_expected_dst_behavior_for_index_cases() -> None:
|
||||
"""Exercise _expected_dst_behavior_for_index for several representative indices."""
|
||||
from kasa.iot.iottimezone import _expected_dst_behavior_for_index
|
||||
|
||||
@@ -20,7 +20,7 @@ def test_expected_dst_behavior_for_index_cases():
|
||||
_expected_dst_behavior_for_index(999)
|
||||
|
||||
|
||||
async def test_guess_timezone_by_offset_fixed_fallback_unit():
|
||||
async def test_guess_timezone_by_offset_fixed_fallback_unit() -> None:
|
||||
"""When no ZoneInfo matches, return a fixed-offset tzinfo."""
|
||||
import kasa.iot.iottimezone as tzmod
|
||||
|
||||
@@ -31,7 +31,7 @@ async def test_guess_timezone_by_offset_fixed_fallback_unit():
|
||||
assert tz.utcoffset(when) == offset
|
||||
|
||||
|
||||
async def test_guess_timezone_by_offset_candidates_unit():
|
||||
async def test_guess_timezone_by_offset_candidates_unit() -> None:
|
||||
"""Cover naive when_utc branch and candidate selection path (non-empty candidates)."""
|
||||
import kasa.iot.iottimezone as tzmod
|
||||
|
||||
@@ -47,7 +47,7 @@ async def test_guess_timezone_by_offset_candidates_unit():
|
||||
|
||||
async def test_guess_timezone_by_offset_dst_expected_true_filters(
|
||||
mocker: MockerFixture,
|
||||
):
|
||||
) -> None:
|
||||
"""dst_expected=True should prefer a DST-observing zone when possible."""
|
||||
import kasa.iot.iottimezone as tzmod
|
||||
|
||||
@@ -62,7 +62,7 @@ async def test_guess_timezone_by_offset_dst_expected_true_filters(
|
||||
assert jan != jul # observes DST
|
||||
|
||||
|
||||
async def test_guess_timezone_by_offset_dst_expected_false_prefers_non_dst():
|
||||
async def test_guess_timezone_by_offset_dst_expected_false_prefers_non_dst() -> None:
|
||||
"""dst_expected=False should prefer a non-DST zone and skip DST candidates (covers False branch)."""
|
||||
import kasa.iot.iottimezone as tzmod
|
||||
|
||||
@@ -79,7 +79,7 @@ async def test_guess_timezone_by_offset_dst_expected_false_prefers_non_dst():
|
||||
|
||||
async def test_guess_timezone_by_offset_handles_missing_zoneinfo_unit(
|
||||
mocker: MockerFixture,
|
||||
):
|
||||
) -> None:
|
||||
"""Cover the ZoneInfoNotFoundError continue path within guess_timezone_by_offset."""
|
||||
from zoneinfo import ZoneInfoNotFoundError as ZNF
|
||||
|
||||
@@ -101,7 +101,7 @@ async def test_guess_timezone_by_offset_handles_missing_zoneinfo_unit(
|
||||
assert tz.utcoffset(when) == timedelta(0)
|
||||
|
||||
|
||||
async def test_get_timezone_index_direct_match():
|
||||
async def test_get_timezone_index_direct_match() -> None:
|
||||
"""If ZoneInfo key is in TIMEZONE_INDEX, return index directly."""
|
||||
import kasa.iot.iottimezone as tzmod
|
||||
|
||||
@@ -109,7 +109,7 @@ async def test_get_timezone_index_direct_match():
|
||||
assert idx == 39 # "GB" is mapped to index 39
|
||||
|
||||
|
||||
async def test_get_timezone_index_non_zoneinfo_unit():
|
||||
async def test_get_timezone_index_non_zoneinfo_unit() -> None:
|
||||
"""Exercise get_timezone_index path when input tzinfo is not a ZoneInfo instance."""
|
||||
import kasa.iot.iottimezone as tzmod
|
||||
|
||||
@@ -119,7 +119,7 @@ async def test_get_timezone_index_non_zoneinfo_unit():
|
||||
assert 0 <= idx <= 109
|
||||
|
||||
|
||||
async def test_get_timezone_index_skips_missing_unit(mocker: MockerFixture):
|
||||
async def test_get_timezone_index_skips_missing_unit(mocker: MockerFixture) -> None:
|
||||
"""Cover ZoneInfoNotFoundError path in get_timezone_index loop and successful match."""
|
||||
from zoneinfo import ZoneInfoNotFoundError as ZNF
|
||||
|
||||
@@ -141,7 +141,7 @@ async def test_get_timezone_index_skips_missing_unit(mocker: MockerFixture):
|
||||
assert idx >= 5
|
||||
|
||||
|
||||
async def test_get_timezone_index_raises_for_unmatched_unit():
|
||||
async def test_get_timezone_index_raises_for_unmatched_unit() -> None:
|
||||
"""Ensure get_timezone_index completes loop and raises when no match exists (covers raise branch)."""
|
||||
import kasa.iot.iottimezone as tzmod
|
||||
|
||||
@@ -150,7 +150,7 @@ async def test_get_timezone_index_raises_for_unmatched_unit():
|
||||
await tzmod.get_timezone_index(timezone(timedelta(minutes=2)))
|
||||
|
||||
|
||||
async def test_get_matching_timezones_branches_unit(mocker: MockerFixture):
|
||||
async def test_get_matching_timezones_branches_unit(mocker: MockerFixture) -> None:
|
||||
"""Cover initial append, except path, and duplicate suppression in get_matching_timezones."""
|
||||
from zoneinfo import ZoneInfoNotFoundError as ZNF
|
||||
|
||||
@@ -172,7 +172,7 @@ async def test_get_matching_timezones_branches_unit(mocker: MockerFixture):
|
||||
# Loop should find GB again but not duplicate it
|
||||
|
||||
|
||||
async def test_get_matching_timezones_non_zoneinfo_unit():
|
||||
async def test_get_matching_timezones_non_zoneinfo_unit() -> None:
|
||||
"""Exercise get_matching_timezones when input tzinfo is not a ZoneInfo (skips initial append)."""
|
||||
import kasa.iot.iottimezone as tzmod
|
||||
|
||||
@@ -181,7 +181,7 @@ async def test_get_matching_timezones_non_zoneinfo_unit():
|
||||
assert len(matches) > 0
|
||||
|
||||
|
||||
async def test_get_timezone_out_of_range_defaults_to_utc():
|
||||
async def test_get_timezone_out_of_range_defaults_to_utc() -> None:
|
||||
"""Out-of-range index should log and default to UTC."""
|
||||
import kasa.iot.iottimezone as tzmod
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from kasa.iot import IotWallSwitch
|
||||
|
||||
from ..device_fixtures import wallswitch_iot
|
||||
|
||||
|
||||
@wallswitch_iot
|
||||
def test_wallswitch_motion(dev):
|
||||
def test_wallswitch_motion(dev: IotWallSwitch) -> None:
|
||||
"""Check that wallswitches with motion sensor get modules enabled."""
|
||||
has_motion = "PIR" in dev.sys_info["dev_name"]
|
||||
assert "motion" in dev.modules if has_motion else True
|
||||
|
||||
Reference in New Issue
Block a user