mirror of
https://github.com/home-assistant/core.git
synced 2025-11-14 21:40:16 +00:00
Catch more invalid themes in validation (#151719)
This commit is contained in:
@@ -75,39 +75,29 @@ PRIMARY_COLOR = "primary-color"
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
EXTENDED_THEME_SCHEMA = vol.Schema(
|
THEME_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
# Theme variables that apply to all modes
|
# Theme variables that apply to all modes
|
||||||
cv.string: cv.string,
|
cv.string: cv.string,
|
||||||
# Mode specific theme variables
|
# Mode specific theme variables
|
||||||
vol.Optional(CONF_THEMES_MODES): vol.Schema(
|
vol.Optional(CONF_THEMES_MODES): vol.All(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_THEMES_LIGHT): vol.Schema({cv.string: cv.string}),
|
vol.Optional(CONF_THEMES_LIGHT): vol.Schema({cv.string: cv.string}),
|
||||||
vol.Optional(CONF_THEMES_DARK): vol.Schema({cv.string: cv.string}),
|
vol.Optional(CONF_THEMES_DARK): vol.Schema({cv.string: cv.string}),
|
||||||
}
|
},
|
||||||
|
cv.has_at_least_one_key(CONF_THEMES_LIGHT, CONF_THEMES_DARK),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
THEME_SCHEMA = vol.Schema(
|
THEMES_SCHEMA = vol.Schema({cv.string: THEME_SCHEMA})
|
||||||
{
|
|
||||||
cv.string: (
|
|
||||||
vol.Any(
|
|
||||||
# Legacy theme scheme
|
|
||||||
{cv.string: cv.string},
|
|
||||||
# New extended schema with mode support
|
|
||||||
EXTENDED_THEME_SCHEMA,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
CONFIG_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
DOMAIN: vol.Schema(
|
DOMAIN: vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_FRONTEND_REPO): cv.isdir,
|
vol.Optional(CONF_FRONTEND_REPO): cv.isdir,
|
||||||
vol.Optional(CONF_THEMES): THEME_SCHEMA,
|
vol.Optional(CONF_THEMES): THEMES_SCHEMA,
|
||||||
vol.Optional(CONF_EXTRA_MODULE_URL): vol.All(
|
vol.Optional(CONF_EXTRA_MODULE_URL): vol.All(
|
||||||
cv.ensure_list, [cv.string]
|
cv.ensure_list, [cv.string]
|
||||||
),
|
),
|
||||||
@@ -546,7 +536,7 @@ async def _async_setup_themes(
|
|||||||
new_themes = config.get(DOMAIN, {}).get(CONF_THEMES, {})
|
new_themes = config.get(DOMAIN, {}).get(CONF_THEMES, {})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
THEME_SCHEMA(new_themes)
|
THEMES_SCHEMA(new_themes)
|
||||||
except vol.Invalid as err:
|
except vol.Invalid as err:
|
||||||
raise HomeAssistantError(f"Failed to reload themes: {err}") from err
|
raise HomeAssistantError(f"Failed to reload themes: {err}") from err
|
||||||
|
|
||||||
|
|||||||
@@ -410,8 +410,64 @@ async def test_themes_reload_themes(
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("frontend")
|
@pytest.mark.usefixtures("frontend")
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("invalid_theme", "error"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"invalid0": "blue",
|
||||||
|
},
|
||||||
|
"expected a dictionary",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"invalid1": {
|
||||||
|
"primary-color": "black",
|
||||||
|
"modes": "light:{} dark:{}",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"expected a dictionary.*modes",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"invalid2": None,
|
||||||
|
},
|
||||||
|
"expected a dictionary",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"invalid3": {
|
||||||
|
"primary-color": "black",
|
||||||
|
"modes": {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"at least one of light, dark.*modes",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"invalid4": {
|
||||||
|
"primary-color": "black",
|
||||||
|
"modes": None,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"expected a dictionary.*modes",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"invalid5": {
|
||||||
|
"primary-color": "black",
|
||||||
|
"modes": {"light": {}, "dank": {}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra keys not allowed.*dank",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
async def test_themes_reload_invalid(
|
async def test_themes_reload_invalid(
|
||||||
hass: HomeAssistant, themes_ws_client: MockHAClientWebSocket
|
hass: HomeAssistant,
|
||||||
|
themes_ws_client: MockHAClientWebSocket,
|
||||||
|
invalid_theme: dict,
|
||||||
|
error: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test frontend.reload_themes service with an invalid theme."""
|
"""Test frontend.reload_themes service with an invalid theme."""
|
||||||
|
|
||||||
@@ -424,9 +480,9 @@ async def test_themes_reload_invalid(
|
|||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"homeassistant.components.frontend.async_hass_config_yaml",
|
"homeassistant.components.frontend.async_hass_config_yaml",
|
||||||
return_value={DOMAIN: {CONF_THEMES: {"sad": "blue"}}},
|
return_value={DOMAIN: {CONF_THEMES: invalid_theme}},
|
||||||
),
|
),
|
||||||
pytest.raises(HomeAssistantError, match="Failed to reload themes"),
|
pytest.raises(HomeAssistantError, match=rf"Failed to reload themes.*{error}"),
|
||||||
):
|
):
|
||||||
await hass.services.async_call(DOMAIN, "reload_themes", blocking=True)
|
await hass.services.async_call(DOMAIN, "reload_themes", blocking=True)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user