Skip to content

Commit

Permalink
Add Thread integration (#86283)
Browse files Browse the repository at this point in the history
* Add Thread integration

* Address review comments

* Address review comments
  • Loading branch information
emontnemery authored Jan 23, 2023
1 parent c15f4ad commit 9ef86b7
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/thermopro/ @bdraco
/tests/components/thermopro/ @bdraco
/homeassistant/components/thethingsnetwork/ @fabaff
/homeassistant/components/thread/ @home-assistant/core
/tests/components/thread/ @home-assistant/core
/homeassistant/components/threshold/ @fabaff
/tests/components/threshold/ @fabaff
/homeassistant/components/tibber/ @danielhiversen
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/otbr/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"domain": "otbr",
"name": "Open Thread Border Router",
"config_flow": true,
"dependencies": ["thread"],
"documentation": "https://www.home-assistant.io/integrations/otbr",
"requirements": ["python-otbr-api==1.0.1"],
"after_dependencies": ["hassio"],
Expand Down
30 changes: 30 additions & 0 deletions homeassistant/components/thread/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""The Thread integration."""
from __future__ import annotations

from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType

from .const import DOMAIN


async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Thread integration."""
if not hass.config_entries.async_entries(DOMAIN):
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}
)
)
return True


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up a config entry."""

return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
return True
19 changes: 19 additions & 0 deletions homeassistant/components/thread/config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Config flow for the Thread integration."""
from __future__ import annotations

from homeassistant.config_entries import ConfigFlow
from homeassistant.data_entry_flow import FlowResult

from .const import DOMAIN


class ThreadConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Thread."""

VERSION = 1

async def async_step_import(
self, import_data: dict[str, str] | None = None
) -> FlowResult:
"""Set up by import from async_setup."""
return self.async_create_entry(title="Thread", data={})
3 changes: 3 additions & 0 deletions homeassistant/components/thread/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Constants for the Thread integration."""

DOMAIN = "thread"
9 changes: 9 additions & 0 deletions homeassistant/components/thread/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"domain": "thread",
"name": "Thread",
"codeowners": ["@home-assistant/core"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/thread",
"integration_type": "service",
"iot_class": "local_polling"
}
1 change: 1 addition & 0 deletions homeassistant/generated/config_flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@
"tesla_wall_connector",
"thermobeacon",
"thermopro",
"thread",
"tibber",
"tile",
"tilt_ble",
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/generated/integrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -5571,6 +5571,12 @@
"config_flow": false,
"iot_class": "local_polling"
},
"thread": {
"name": "Thread",
"integration_type": "service",
"config_flow": true,
"iot_class": "local_polling"
},
"tibber": {
"name": "Tibber",
"integration_type": "hub",
Expand Down
1 change: 1 addition & 0 deletions tests/components/thread/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests for the Thread integration."""
22 changes: 22 additions & 0 deletions tests/components/thread/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Test fixtures for the Thread integration."""

import pytest

from homeassistant.components import thread

from tests.common import MockConfigEntry

CONFIG_ENTRY_DATA = {}


@pytest.fixture(name="thread_config_entry")
async def thread_config_entry_fixture(hass):
"""Mock Thread config entry."""
config_entry = MockConfigEntry(
data=CONFIG_ENTRY_DATA,
domain=thread.DOMAIN,
options={},
title="Thread",
)
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
29 changes: 29 additions & 0 deletions tests/components/thread/test_config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Test the Thread config flow."""
from unittest.mock import patch

from homeassistant.components import thread
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType


async def test_import(hass: HomeAssistant) -> None:
"""Test the import flow."""
with patch(
"homeassistant.components.thread.async_setup_entry",
return_value=True,
) as mock_setup_entry:
result = await hass.config_entries.flow.async_init(
thread.DOMAIN, context={"source": "import"}
)

assert result["type"] == FlowResultType.CREATE_ENTRY
assert result["title"] == "Thread"
assert result["data"] == {}
assert result["options"] == {}
assert len(mock_setup_entry.mock_calls) == 1

config_entry = hass.config_entries.async_entries(thread.DOMAIN)[0]
assert config_entry.data == {}
assert config_entry.options == {}
assert config_entry.title == "Thread"
assert config_entry.unique_id is None
29 changes: 29 additions & 0 deletions tests/components/thread/test_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Test the Thread integration."""

from homeassistant.components import thread
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component


async def test_create_entry(hass: HomeAssistant):
"""Test an entry is created by async_setup."""
assert len(hass.config_entries.async_entries(thread.DOMAIN)) == 0
assert await async_setup_component(hass, thread.DOMAIN, {})
await hass.async_block_till_done()

assert len(hass.config_entries.async_entries(thread.DOMAIN)) == 1


async def test_remove_entry(hass: HomeAssistant, thread_config_entry):
"""Test removing the entry."""

config_entry = hass.config_entries.async_entries(thread.DOMAIN)[0]
assert await hass.config_entries.async_remove(config_entry.entry_id) == {
"require_restart": False
}


async def test_import_once(hass: HomeAssistant, thread_config_entry) -> None:
"""Test only a single entry is created."""
await hass.async_block_till_done()
assert len(hass.config_entries.async_entries(thread.DOMAIN)) == 1

0 comments on commit 9ef86b7

Please sign in to comment.