mirror of https://github.com/home-assistant/core
229 lines
7.8 KiB
Python
229 lines
7.8 KiB
Python
"""Test Home Assistant icon util methods."""
|
|
|
|
import pathlib
|
|
from unittest.mock import Mock, patch
|
|
|
|
import pytest
|
|
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers import icon
|
|
from homeassistant.loader import IntegrationNotFound
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
|
|
def test_battery_icon() -> None:
|
|
"""Test icon generator for battery sensor."""
|
|
assert icon.icon_for_battery_level(None, True) == "mdi:battery-unknown"
|
|
assert icon.icon_for_battery_level(None, False) == "mdi:battery-unknown"
|
|
|
|
assert icon.icon_for_battery_level(5, True) == "mdi:battery-outline"
|
|
assert icon.icon_for_battery_level(5, False) == "mdi:battery-alert"
|
|
|
|
assert icon.icon_for_battery_level(100, True) == "mdi:battery-charging-100"
|
|
assert icon.icon_for_battery_level(100, False) == "mdi:battery"
|
|
|
|
iconbase = "mdi:battery"
|
|
for level in range(0, 100, 5):
|
|
print( # noqa: T201
|
|
f"Level: {level}. icon: {icon.icon_for_battery_level(level, False)}, "
|
|
f"charging: {icon.icon_for_battery_level(level, True)}"
|
|
)
|
|
if level <= 10:
|
|
postfix_charging = "-outline"
|
|
elif level <= 30:
|
|
postfix_charging = "-charging-20"
|
|
elif level <= 50:
|
|
postfix_charging = "-charging-40"
|
|
elif level <= 70:
|
|
postfix_charging = "-charging-60"
|
|
elif level <= 90:
|
|
postfix_charging = "-charging-80"
|
|
else:
|
|
postfix_charging = "-charging-100"
|
|
if 5 < level < 95:
|
|
postfix = f"-{int(round(level / 10 - 0.01)) * 10}"
|
|
elif level <= 5:
|
|
postfix = "-alert"
|
|
else:
|
|
postfix = ""
|
|
assert iconbase + postfix == icon.icon_for_battery_level(level, False)
|
|
assert iconbase + postfix_charging == icon.icon_for_battery_level(level, True)
|
|
|
|
|
|
def test_signal_icon() -> None:
|
|
"""Test icon generator for signal sensor."""
|
|
assert icon.icon_for_signal_level(None) == "mdi:signal-cellular-outline"
|
|
assert icon.icon_for_signal_level(0) == "mdi:signal-cellular-outline"
|
|
assert icon.icon_for_signal_level(5) == "mdi:signal-cellular-1"
|
|
assert icon.icon_for_signal_level(40) == "mdi:signal-cellular-2"
|
|
assert icon.icon_for_signal_level(80) == "mdi:signal-cellular-3"
|
|
assert icon.icon_for_signal_level(100) == "mdi:signal-cellular-3"
|
|
|
|
|
|
def test_load_icons_files(hass: HomeAssistant) -> None:
|
|
"""Test the load icons files function."""
|
|
file1 = hass.config.path("custom_components", "test", "icons.json")
|
|
file2 = hass.config.path("custom_components", "test", "invalid.json")
|
|
assert icon._load_icons_files({"test": file1, "invalid": file2}) == {
|
|
"test": {
|
|
"entity": {
|
|
"switch": {
|
|
"something": {
|
|
"state": {"away": "mdi:home-outline", "home": "mdi:home"}
|
|
}
|
|
}
|
|
},
|
|
},
|
|
"invalid": {},
|
|
}
|
|
|
|
|
|
@pytest.mark.usefixtures("enable_custom_integrations")
|
|
async def test_get_icons(hass: HomeAssistant) -> None:
|
|
"""Test the get icon helper."""
|
|
icons = await icon.async_get_icons(hass, "entity")
|
|
assert icons == {}
|
|
|
|
icons = await icon.async_get_icons(hass, "entity_component")
|
|
assert icons == {}
|
|
|
|
# Set up test switch component
|
|
assert await async_setup_component(hass, "switch", {"switch": {"platform": "test"}})
|
|
|
|
# Test getting icons for the entity component
|
|
icons = await icon.async_get_icons(hass, "entity_component")
|
|
assert icons["switch"]["_"]["default"] == "mdi:toggle-switch-variant"
|
|
|
|
# Test services icons are available
|
|
icons = await icon.async_get_icons(hass, "services")
|
|
assert len(icons) == 1
|
|
assert icons["switch"]["turn_off"] == {"service": "mdi:toggle-switch-variant-off"}
|
|
|
|
# Ensure icons file for platform isn't loaded, as that isn't supported
|
|
icons = await icon.async_get_icons(hass, "entity")
|
|
assert icons == {}
|
|
with pytest.raises(ValueError, match="test.switch"):
|
|
await icon.async_get_icons(hass, "entity", ["test.switch"])
|
|
|
|
# Load up an custom integration
|
|
hass.config.components.add("test_package")
|
|
await hass.async_block_till_done()
|
|
|
|
icons = await icon.async_get_icons(hass, "entity")
|
|
assert len(icons) == 1
|
|
|
|
assert icons == {
|
|
"test_package": {
|
|
"switch": {
|
|
"something": {"state": {"away": "mdi:home-outline", "home": "mdi:home"}}
|
|
}
|
|
}
|
|
}
|
|
|
|
icons = await icon.async_get_icons(hass, "services")
|
|
assert len(icons) == 2
|
|
assert icons["test_package"]["enable_god_mode"] == {"service": "mdi:shield"}
|
|
|
|
# Load another one
|
|
hass.config.components.add("test_embedded")
|
|
await hass.async_block_till_done()
|
|
|
|
icons = await icon.async_get_icons(hass, "entity")
|
|
assert len(icons) == 2
|
|
|
|
assert icons["test_package"] == {
|
|
"switch": {
|
|
"something": {"state": {"away": "mdi:home-outline", "home": "mdi:home"}}
|
|
}
|
|
}
|
|
|
|
# Test getting non-existing integration
|
|
with pytest.raises(
|
|
IntegrationNotFound, match="Integration 'non_existing' not found"
|
|
):
|
|
await icon.async_get_icons(hass, "entity", ["non_existing"])
|
|
|
|
|
|
async def test_get_icons_while_loading_components(hass: HomeAssistant) -> None:
|
|
"""Test the get icons helper loads icons."""
|
|
integration = Mock(file_path=pathlib.Path(__file__))
|
|
integration.name = "Component 1"
|
|
hass.config.components.add("component1")
|
|
load_count = 0
|
|
|
|
def mock_load_icons_files(files):
|
|
"""Mock load icon files."""
|
|
nonlocal load_count
|
|
load_count += 1
|
|
return {"component1": {"entity": {"climate": {"test": {"icon": "mdi:home"}}}}}
|
|
|
|
with (
|
|
patch(
|
|
"homeassistant.helpers.icon._load_icons_files",
|
|
mock_load_icons_files,
|
|
),
|
|
patch(
|
|
"homeassistant.helpers.icon.async_get_integrations",
|
|
return_value={"component1": integration},
|
|
),
|
|
):
|
|
times = 5
|
|
all_icons = [await icon.async_get_icons(hass, "entity") for _ in range(times)]
|
|
|
|
assert all_icons == [
|
|
{"component1": {"climate": {"test": {"icon": "mdi:home"}}}}
|
|
for _ in range(times)
|
|
]
|
|
assert load_count == 1
|
|
|
|
|
|
async def test_caching(hass: HomeAssistant) -> None:
|
|
"""Test we cache data."""
|
|
hass.config.components.add("binary_sensor")
|
|
hass.config.components.add("switch")
|
|
|
|
# Patch with same method so we can count invocations
|
|
with patch(
|
|
"homeassistant.helpers.icon.build_resources",
|
|
side_effect=icon.build_resources,
|
|
) as mock_build:
|
|
load1 = await icon.async_get_icons(hass, "entity_component")
|
|
assert len(mock_build.mock_calls) == 2
|
|
|
|
load2 = await icon.async_get_icons(hass, "entity_component")
|
|
assert len(mock_build.mock_calls) == 2
|
|
|
|
assert load1 == load2
|
|
|
|
assert load1["binary_sensor"]
|
|
assert load1["switch"]
|
|
|
|
load_switch_only = await icon.async_get_icons(
|
|
hass, "entity_component", integrations={"switch"}
|
|
)
|
|
assert load_switch_only
|
|
assert list(load_switch_only) == ["switch"]
|
|
|
|
load_binary_sensor_only = await icon.async_get_icons(
|
|
hass, "entity_component", integrations={"binary_sensor"}
|
|
)
|
|
assert load_binary_sensor_only
|
|
assert list(load_binary_sensor_only) == ["binary_sensor"]
|
|
|
|
# Check if new loaded component, trigger load
|
|
hass.config.components.add("media_player")
|
|
with patch(
|
|
"homeassistant.helpers.icon._load_icons_files",
|
|
side_effect=icon._load_icons_files,
|
|
) as mock_load:
|
|
load_sensor_only = await icon.async_get_icons(
|
|
hass, "entity_component", integrations={"switch"}
|
|
)
|
|
assert load_sensor_only
|
|
assert len(mock_load.mock_calls) == 0
|
|
|
|
await icon.async_get_icons(
|
|
hass, "entity_component", integrations={"media_player"}
|
|
)
|
|
assert len(mock_load.mock_calls) == 1
|