Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions homeassistant/components/html5/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import discovery
from homeassistant.helpers import config_validation as cv, discovery

from .const import DOMAIN

CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up HTML5 from a config entry."""
await discovery.async_load_platform(
hass, Platform.NOTIFY, DOMAIN, dict(entry.data), {}
hass.async_create_task(
discovery.async_load_platform(
hass, Platform.NOTIFY, DOMAIN, dict(entry.data), {}
)
)
return True
12 changes: 0 additions & 12 deletions homeassistant/components/html5/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from homeassistant.core import callback

from .const import ATTR_VAPID_EMAIL, ATTR_VAPID_PRV_KEY, ATTR_VAPID_PUB_KEY, DOMAIN
from .issues import async_create_html5_issue


def vapid_generate_private_key() -> str:
Expand Down Expand Up @@ -92,14 +91,3 @@ async def async_step_user(
),
errors=errors,
)

async def async_step_import(
self: HTML5ConfigFlow, import_config: dict
) -> ConfigFlowResult:
"""Handle config import from yaml."""
_, flow_result = self._async_create_html5_entry(import_config)
if not flow_result:
async_create_html5_issue(self.hass, False)
return self.async_abort(reason="invalid_config")
async_create_html5_issue(self.hass, True)
return flow_result
50 changes: 0 additions & 50 deletions homeassistant/components/html5/issues.py

This file was deleted.

23 changes: 0 additions & 23 deletions homeassistant/components/html5/notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@
ATTR_TARGET,
ATTR_TITLE,
ATTR_TITLE_DEFAULT,
PLATFORM_SCHEMA as NOTIFY_PLATFORM_SCHEMA,
BaseNotificationService,
)
from homeassistant.config_entries import SOURCE_IMPORT
from homeassistant.const import ATTR_NAME, URL_ROOT
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import HomeAssistantError
Expand All @@ -47,23 +45,12 @@
DOMAIN,
SERVICE_DISMISS,
)
from .issues import async_create_html5_issue

_LOGGER = logging.getLogger(__name__)

REGISTRATIONS_FILE = "html5_push_registrations.conf"


PLATFORM_SCHEMA = NOTIFY_PLATFORM_SCHEMA.extend(
{
vol.Optional("gcm_sender_id"): cv.string,
vol.Optional("gcm_api_key"): cv.string,
vol.Required(ATTR_VAPID_PUB_KEY): cv.string,
vol.Required(ATTR_VAPID_PRV_KEY): cv.string,
vol.Required(ATTR_VAPID_EMAIL): cv.string,
}
)

ATTR_SUBSCRIPTION = "subscription"
ATTR_BROWSER = "browser"

Expand Down Expand Up @@ -166,17 +153,7 @@ async def async_get_service(
) -> HTML5NotificationService | None:
"""Get the HTML5 push notification service."""
if config:
existing_config_entry = hass.config_entries.async_entries(DOMAIN)
if existing_config_entry:
async_create_html5_issue(hass, True)
return None
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=config
)
)
return None

if discovery_info is None:
return None

Expand Down
30 changes: 6 additions & 24 deletions homeassistant/components/zwave_js/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,22 +267,10 @@ def percentage_to_zwave_speed(self, percentage: int) -> int:
if percentage == 0:
return 0

# Since the percentage steps are computed with rounding, we have to
# search to find the appropriate speed.
for speed_range in self.fan_value_mapping.speeds:
(_, max_speed) = speed_range
step_percentage = self.zwave_speed_to_percentage(max_speed)

# zwave_speed_to_percentage will only return None if
# `self.fan_value_mapping.speeds` doesn't contain the
# specified speed. This can't happen here, because
# the input is coming from the same data structure.
assert step_percentage

if percentage <= step_percentage:
break

return max_speed
speed_level = math.ceil(
percentage_to_ranged_value((1, self.speed_count), percentage)
)
return self.fan_value_mapping.speeds[speed_level - 1][1]

def zwave_speed_to_percentage(self, zwave_speed: int) -> int | None:
"""Convert a Zwave speed to a percentage.
Expand All @@ -293,15 +281,9 @@ def zwave_speed_to_percentage(self, zwave_speed: int) -> int | None:
if zwave_speed == 0:
return 0

percentage = 0.0
for speed_range in self.fan_value_mapping.speeds:
(min_speed, max_speed) = speed_range
percentage += self.percentage_step
for index, (min_speed, max_speed) in enumerate(self.fan_value_mapping.speeds):
if min_speed <= zwave_speed <= max_speed:
# This choice of rounding function is to provide consistency with how
# the UI handles steps e.g., for a 3-speed fan, you get steps at 33,
# 67, and 100.
return round(percentage)
return ranged_value_to_percentage((1, self.speed_count), index + 1)

# The specified Z-Wave device value doesn't map to a defined speed.
return None
Expand Down
47 changes: 47 additions & 0 deletions tests/components/html5/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Common fixtures for html5 integration."""

from collections.abc import Generator
from unittest.mock import MagicMock

import pytest

from homeassistant.components.html5.const import (
ATTR_VAPID_EMAIL,
ATTR_VAPID_PRV_KEY,
ATTR_VAPID_PUB_KEY,
DOMAIN,
)
from homeassistant.const import CONF_NAME

from tests.common import MockConfigEntry, patch

MOCK_CONF = {
ATTR_VAPID_EMAIL: "test@example.com",
ATTR_VAPID_PRV_KEY: "h6acSRds8_KR8hT9djD8WucTL06Gfe29XXyZ1KcUjN8",
}
MOCK_CONF_PUB_KEY = "BIUtPN7Rq_8U7RBEqClZrfZ5dR9zPCfvxYPtLpWtRVZTJEc7lzv2dhzDU6Aw1m29Ao0-UA1Uq6XO9Df8KALBKqA"


@pytest.fixture(name="config_entry")
def mock_config_entry() -> MockConfigEntry:
"""Mock ntfy configuration entry."""
return MockConfigEntry(
domain=DOMAIN,
title="HTML5",
data={
ATTR_VAPID_PRV_KEY: MOCK_CONF[ATTR_VAPID_PRV_KEY],
ATTR_VAPID_PUB_KEY: MOCK_CONF_PUB_KEY,
ATTR_VAPID_EMAIL: MOCK_CONF[ATTR_VAPID_EMAIL],
CONF_NAME: DOMAIN,
},
)


@pytest.fixture(name="load_config")
def mock_load_config() -> Generator[MagicMock]:
"""Mock load config."""

with patch(
"homeassistant.components.html5.notify._load_config", return_value={}
) as mock_load_config:
yield mock_load_config
87 changes: 2 additions & 85 deletions tests/components/html5/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,10 @@
ATTR_VAPID_PUB_KEY,
DOMAIN,
)
from homeassistant.components.html5.issues import (
FAILED_IMPORT_TRANSLATION_KEY,
SUCCESSFUL_IMPORT_TRANSLATION_KEY,
)
from homeassistant.const import CONF_NAME
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
from homeassistant.helpers import issue_registry as ir
from homeassistant.core import HomeAssistant

MOCK_CONF = {
ATTR_VAPID_EMAIL: "test@example.com",
ATTR_VAPID_PRV_KEY: "h6acSRds8_KR8hT9djD8WucTL06Gfe29XXyZ1KcUjN8",
}
MOCK_CONF_PUB_KEY = "BIUtPN7Rq_8U7RBEqClZrfZ5dR9zPCfvxYPtLpWtRVZTJEc7lzv2dhzDU6Aw1m29Ao0-UA1Uq6XO9Df8KALBKqA"
from .conftest import MOCK_CONF, MOCK_CONF_PUB_KEY


async def test_step_user_success(hass: HomeAssistant) -> None:
Expand Down Expand Up @@ -127,77 +118,3 @@ async def test_step_user_form_invalid_key(
)
assert result["type"] is data_entry_flow.FlowResultType.CREATE_ENTRY
assert mock_setup_entry.call_count == 1


async def test_step_import_good(
hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
) -> None:
"""Test valid import input."""

with (
patch(
"homeassistant.components.html5.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
conf = MOCK_CONF.copy()
conf[ATTR_VAPID_PUB_KEY] = MOCK_CONF_PUB_KEY
conf["random_key"] = "random_value"

result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=conf
)

await hass.async_block_till_done()

assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
assert result["data"] == {
ATTR_VAPID_PRV_KEY: conf[ATTR_VAPID_PRV_KEY],
ATTR_VAPID_PUB_KEY: MOCK_CONF_PUB_KEY,
ATTR_VAPID_EMAIL: conf[ATTR_VAPID_EMAIL],
CONF_NAME: DOMAIN,
}

assert mock_setup_entry.call_count == 1
assert len(issue_registry.issues) == 1
issue = issue_registry.async_get_issue(
HOMEASSISTANT_DOMAIN, f"deprecated_yaml_{DOMAIN}"
)
assert issue
assert issue.translation_key == SUCCESSFUL_IMPORT_TRANSLATION_KEY


@pytest.mark.parametrize(
("key", "value"),
[
(ATTR_VAPID_PRV_KEY, "invalid"),
],
)
async def test_step_import_bad(
hass: HomeAssistant, issue_registry: ir.IssueRegistry, key: str, value: str
) -> None:
"""Test invalid import input."""

with (
patch(
"homeassistant.components.html5.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
bad_conf = MOCK_CONF.copy()
bad_conf[key] = value

result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=bad_conf
)

await hass.async_block_till_done()

assert result["type"] == data_entry_flow.FlowResultType.ABORT
assert mock_setup_entry.call_count == 0

assert len(issue_registry.issues) == 1
issue = issue_registry.async_get_issue(DOMAIN, f"deprecated_yaml_{DOMAIN}")
assert issue
assert issue.translation_key == FAILED_IMPORT_TRANSLATION_KEY
38 changes: 5 additions & 33 deletions tests/components/html5/test_init.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,16 @@
"""Test the HTML5 setup."""

from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.helpers import issue_registry as ir
from homeassistant.setup import async_setup_component

from tests.common import MockConfigEntry

NOTIFY_CONF = {
"notify": [
{
"platform": "html5",
"name": "html5",
"vapid_pub_key": "BIUtPN7Rq_8U7RBEqClZrfZ5dR9zPCfvxYPtLpWtRVZTJEc7lzv2dhzDU6Aw1m29Ao0-UA1Uq6XO9Df8KALBKqA",
"vapid_prv_key": "h6acSRds8_KR8hT9djD8WucTL06Gfe29XXyZ1KcUjN8",
"vapid_email": "test@example.com",
}
]
}


async def test_setup_entry(
hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
) -> None:
async def test_setup_entry(hass: HomeAssistant, config_entry: MockConfigEntry) -> None:
"""Test setup of a good config entry."""
config_entry = MockConfigEntry(domain="html5", data={})
config_entry.add_to_hass(hass)
assert await async_setup_component(hass, "html5", {})

assert len(issue_registry.issues) == 0


async def test_setup_entry_issue(
hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
) -> None:
"""Test setup of an imported config entry with deprecated YAML."""
config_entry = MockConfigEntry(domain="html5", data={})
config_entry.add_to_hass(hass)
assert await async_setup_component(hass, "notify", NOTIFY_CONF)
assert await async_setup_component(hass, "html5", NOTIFY_CONF)
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()

assert len(issue_registry.issues) == 1
assert config_entry.state is ConfigEntryState.LOADED
Loading
Loading