mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-01-24 21:57:07 +00:00
Fix tests
This commit is contained in:
parent
20ec2f5c90
commit
3e25c79f39
@ -1117,7 +1117,7 @@ async def feature(dev, name: str, value):
|
|||||||
If both *name* and *value* are set, the described setting is changed.
|
If both *name* and *value* are set, the described setting is changed.
|
||||||
"""
|
"""
|
||||||
if not name:
|
if not name:
|
||||||
echo("[bold]== Feature ==[/bold]")
|
echo("[bold]== Features ==[/bold]")
|
||||||
for name, feat in dev.features.items():
|
for name, feat in dev.features.items():
|
||||||
echo(f"{feat.name} ({name}): {feat.value}")
|
echo(f"{feat.name} ({name}): {feat.value}")
|
||||||
return
|
return
|
||||||
|
@ -36,6 +36,11 @@ async def test_update_called_by_cli(dev, mocker):
|
|||||||
"""Test that device update is called on main."""
|
"""Test that device update is called on main."""
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
update = mocker.patch.object(dev, "update")
|
update = mocker.patch.object(dev, "update")
|
||||||
|
|
||||||
|
# These will mock the features to avoid accessing non-existing
|
||||||
|
mocker.patch("kasa.device.Device.features", return_value={})
|
||||||
|
mocker.patch("kasa.iot.iotdevice.IotDevice.features", return_value={})
|
||||||
|
|
||||||
mocker.patch("kasa.discover.Discover.discover_single", return_value=dev)
|
mocker.patch("kasa.discover.Discover.discover_single", return_value=dev)
|
||||||
|
|
||||||
res = await runner.invoke(
|
res = await runner.invoke(
|
||||||
@ -48,6 +53,7 @@ async def test_update_called_by_cli(dev, mocker):
|
|||||||
"--password",
|
"--password",
|
||||||
"bar",
|
"bar",
|
||||||
],
|
],
|
||||||
|
catch_exceptions=False,
|
||||||
)
|
)
|
||||||
assert res.exit_code == 0
|
assert res.exit_code == 0
|
||||||
update.assert_called()
|
update.assert_called()
|
||||||
@ -291,6 +297,10 @@ async def test_brightness(dev):
|
|||||||
async def test_json_output(dev: Device, mocker):
|
async def test_json_output(dev: Device, mocker):
|
||||||
"""Test that the json output produces correct output."""
|
"""Test that the json output produces correct output."""
|
||||||
mocker.patch("kasa.Discover.discover", return_value={"127.0.0.1": dev})
|
mocker.patch("kasa.Discover.discover", return_value={"127.0.0.1": dev})
|
||||||
|
# These will mock the features to avoid accessing non-existing
|
||||||
|
mocker.patch("kasa.device.Device.features", return_value={})
|
||||||
|
mocker.patch("kasa.iot.iotdevice.IotDevice.features", return_value={})
|
||||||
|
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
res = await runner.invoke(cli, ["--json", "state"], obj=dev)
|
res = await runner.invoke(cli, ["--json", "state"], obj=dev)
|
||||||
assert res.exit_code == 0
|
assert res.exit_code == 0
|
||||||
@ -342,6 +352,10 @@ async def test_without_device_type(dev, mocker):
|
|||||||
"""Test connecting without the device type."""
|
"""Test connecting without the device type."""
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
mocker.patch("kasa.discover.Discover.discover_single", return_value=dev)
|
mocker.patch("kasa.discover.Discover.discover_single", return_value=dev)
|
||||||
|
# These will mock the features to avoid accessing non-existing
|
||||||
|
mocker.patch("kasa.device.Device.features", return_value={})
|
||||||
|
mocker.patch("kasa.iot.iotdevice.IotDevice.features", return_value={})
|
||||||
|
|
||||||
res = await runner.invoke(
|
res = await runner.invoke(
|
||||||
cli,
|
cli,
|
||||||
[
|
[
|
||||||
@ -398,6 +412,10 @@ async def test_duplicate_target_device():
|
|||||||
|
|
||||||
async def test_discover(discovery_mock, mocker):
|
async def test_discover(discovery_mock, mocker):
|
||||||
"""Test discovery output."""
|
"""Test discovery output."""
|
||||||
|
# These will mock the features to avoid accessing non-existing
|
||||||
|
mocker.patch("kasa.device.Device.features", return_value={})
|
||||||
|
mocker.patch("kasa.iot.iotdevice.IotDevice.features", return_value={})
|
||||||
|
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
res = await runner.invoke(
|
res = await runner.invoke(
|
||||||
cli,
|
cli,
|
||||||
@ -417,6 +435,10 @@ async def test_discover(discovery_mock, mocker):
|
|||||||
|
|
||||||
async def test_discover_host(discovery_mock, mocker):
|
async def test_discover_host(discovery_mock, mocker):
|
||||||
"""Test discovery output."""
|
"""Test discovery output."""
|
||||||
|
# These will mock the features to avoid accessing non-existing
|
||||||
|
mocker.patch("kasa.device.Device.features", return_value={})
|
||||||
|
mocker.patch("kasa.iot.iotdevice.IotDevice.features", return_value={})
|
||||||
|
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
res = await runner.invoke(
|
res = await runner.invoke(
|
||||||
cli,
|
cli,
|
||||||
|
79
kasa/tests/test_feature.py
Normal file
79
kasa/tests/test_feature.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from kasa import Feature, FeatureType
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def dummy_feature() -> Feature:
|
||||||
|
# create_autospec for device slows tests way too much, so we use a dummy here
|
||||||
|
class DummyDevice:
|
||||||
|
pass
|
||||||
|
|
||||||
|
feat = Feature(
|
||||||
|
device=DummyDevice(), # type: ignore[arg-type]
|
||||||
|
name="dummy_feature",
|
||||||
|
attribute_getter="dummygetter",
|
||||||
|
attribute_setter="dummysetter",
|
||||||
|
container=None,
|
||||||
|
icon="mdi:dummy",
|
||||||
|
type=FeatureType.BinarySensor,
|
||||||
|
)
|
||||||
|
return feat
|
||||||
|
|
||||||
|
|
||||||
|
def test_feature_api(dummy_feature: Feature):
|
||||||
|
"""Test all properties of a dummy feature."""
|
||||||
|
assert dummy_feature.device is not None
|
||||||
|
assert dummy_feature.name == "dummy_feature"
|
||||||
|
assert dummy_feature.attribute_getter == "dummygetter"
|
||||||
|
assert dummy_feature.attribute_setter == "dummysetter"
|
||||||
|
assert dummy_feature.container is None
|
||||||
|
assert dummy_feature.icon == "mdi:dummy"
|
||||||
|
assert dummy_feature.type == FeatureType.BinarySensor
|
||||||
|
|
||||||
|
|
||||||
|
def test_feature_value(dummy_feature: Feature):
|
||||||
|
"""Verify that property gets accessed on *value* access."""
|
||||||
|
dummy_feature.attribute_getter = "test_prop"
|
||||||
|
dummy_feature.device.test_prop = "dummy" # type: ignore[attr-defined]
|
||||||
|
assert dummy_feature.value == "dummy"
|
||||||
|
|
||||||
|
|
||||||
|
def test_feature_value_container(mocker, dummy_feature: Feature):
|
||||||
|
"""Test that container's attribute is accessed when expected."""
|
||||||
|
|
||||||
|
class DummyContainer:
|
||||||
|
@property
|
||||||
|
def test_prop(self):
|
||||||
|
return "dummy"
|
||||||
|
|
||||||
|
dummy_feature.container = DummyContainer()
|
||||||
|
dummy_feature.attribute_getter = "test_prop"
|
||||||
|
|
||||||
|
mock_dev_prop = mocker.patch.object(
|
||||||
|
dummy_feature, "test_prop", new_callable=mocker.PropertyMock, create=True
|
||||||
|
)
|
||||||
|
|
||||||
|
assert dummy_feature.value == "dummy"
|
||||||
|
mock_dev_prop.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_feature_value_callable(dev, dummy_feature: Feature):
|
||||||
|
"""Verify that callables work as *attribute_getter*."""
|
||||||
|
dummy_feature.attribute_getter = lambda x: "dummy value"
|
||||||
|
assert dummy_feature.value == "dummy value"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_feature_setter(dev, mocker, dummy_feature: Feature):
|
||||||
|
"""Verify that *set_value* calls the defined method."""
|
||||||
|
mock_set_dummy = mocker.patch.object(dummy_feature.device, "set_dummy", create=True)
|
||||||
|
dummy_feature.attribute_setter = "set_dummy"
|
||||||
|
await dummy_feature.set_value("dummy value")
|
||||||
|
mock_set_dummy.assert_called_with("dummy value")
|
||||||
|
|
||||||
|
|
||||||
|
async def test_feature_setter_read_only(dummy_feature):
|
||||||
|
"""Verify that read-only feature raises an exception when trying to change it."""
|
||||||
|
dummy_feature.attribute_setter = None
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
await dummy_feature.set_value("value for read only feature")
|
@ -67,7 +67,7 @@ async def test_invalid_connection(dev):
|
|||||||
async def test_initial_update_emeter(dev, mocker):
|
async def test_initial_update_emeter(dev, mocker):
|
||||||
"""Test that the initial update performs second query if emeter is available."""
|
"""Test that the initial update performs second query if emeter is available."""
|
||||||
dev._last_update = None
|
dev._last_update = None
|
||||||
dev._features = set()
|
dev._legacy_features = set()
|
||||||
spy = mocker.spy(dev.protocol, "query")
|
spy = mocker.spy(dev.protocol, "query")
|
||||||
await dev.update()
|
await dev.update()
|
||||||
# Devices with small buffers may require 3 queries
|
# Devices with small buffers may require 3 queries
|
||||||
@ -79,7 +79,7 @@ async def test_initial_update_emeter(dev, mocker):
|
|||||||
async def test_initial_update_no_emeter(dev, mocker):
|
async def test_initial_update_no_emeter(dev, mocker):
|
||||||
"""Test that the initial update performs second query if emeter is available."""
|
"""Test that the initial update performs second query if emeter is available."""
|
||||||
dev._last_update = None
|
dev._last_update = None
|
||||||
dev._features = set()
|
dev._legacy_features = set()
|
||||||
spy = mocker.spy(dev.protocol, "query")
|
spy = mocker.spy(dev.protocol, "query")
|
||||||
await dev.update()
|
await dev.update()
|
||||||
# 2 calls are necessary as some devices crash on unexpected modules
|
# 2 calls are necessary as some devices crash on unexpected modules
|
||||||
@ -218,9 +218,9 @@ async def test_features(dev):
|
|||||||
"""Make sure features is always accessible."""
|
"""Make sure features is always accessible."""
|
||||||
sysinfo = dev._last_update["system"]["get_sysinfo"]
|
sysinfo = dev._last_update["system"]["get_sysinfo"]
|
||||||
if "feature" in sysinfo:
|
if "feature" in sysinfo:
|
||||||
assert dev.features == set(sysinfo["feature"].split(":"))
|
assert dev._legacy_features == set(sysinfo["feature"].split(":"))
|
||||||
else:
|
else:
|
||||||
assert dev.features == set()
|
assert dev._legacy_features == set()
|
||||||
|
|
||||||
|
|
||||||
@device_iot
|
@device_iot
|
||||||
|
Loading…
Reference in New Issue
Block a user