Skip to content

Commit c4e0bd6

Browse files
authored
Cover Spook inverse config flow (#1290)
1 parent b2cb6c6 commit c4e0bd6

2 files changed

Lines changed: 214 additions & 0 deletions

File tree

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
"""Tests for the Spook inverse config flow."""
2+
3+
from __future__ import annotations
4+
5+
from typing import TYPE_CHECKING
6+
7+
import pytest
8+
from pytest_homeassistant_custom_component.common import MockConfigEntry
9+
10+
from homeassistant import config_entries
11+
from homeassistant.const import CONF_ENTITY_ID, CONF_NAME, Platform
12+
from homeassistant.data_entry_flow import FlowResultType
13+
from homeassistant.helpers import entity_registry as er
14+
15+
from custom_components.spook.integrations.spook_inverse.const import (
16+
CONF_HIDE_SOURCE,
17+
DOMAIN,
18+
)
19+
20+
if TYPE_CHECKING:
21+
from homeassistant.core import HomeAssistant
22+
23+
24+
def _create_source_entity(hass: HomeAssistant, domain: str) -> str:
25+
"""Create a source entity and return its entity ID."""
26+
entity_registry = er.async_get(hass)
27+
entity_entry = entity_registry.async_get_or_create(
28+
domain,
29+
"test",
30+
"source",
31+
suggested_object_id="source",
32+
)
33+
return entity_entry.entity_id
34+
35+
36+
@pytest.mark.parametrize("platform", [Platform.BINARY_SENSOR, Platform.SWITCH])
37+
async def test_config_flow_creates_inverse_entry(
38+
hass: HomeAssistant,
39+
platform: Platform,
40+
) -> None:
41+
"""Test config flow creates an inverse helper entry."""
42+
source_entity_id = _create_source_entity(hass, platform)
43+
44+
result = await hass.config_entries.flow.async_init(
45+
DOMAIN,
46+
context={"source": config_entries.SOURCE_USER},
47+
)
48+
49+
assert result["type"] is FlowResultType.MENU
50+
assert result["menu_options"] == [Platform.BINARY_SENSOR, Platform.SWITCH]
51+
52+
result = await hass.config_entries.flow.async_configure(
53+
result["flow_id"],
54+
user_input={"next_step_id": platform},
55+
)
56+
57+
assert result["type"] is FlowResultType.FORM
58+
assert result["step_id"] == platform
59+
60+
result = await hass.config_entries.flow.async_configure(
61+
result["flow_id"],
62+
user_input={
63+
CONF_NAME: "Inverse source",
64+
CONF_ENTITY_ID: source_entity_id,
65+
CONF_HIDE_SOURCE: True,
66+
},
67+
)
68+
69+
assert result["type"] is FlowResultType.CREATE_ENTRY
70+
assert result["title"] == "Inverse source"
71+
assert result["data"] == {}
72+
assert result["options"] == {
73+
"inverse_type": platform,
74+
CONF_NAME: "Inverse source",
75+
CONF_ENTITY_ID: source_entity_id,
76+
CONF_HIDE_SOURCE: True,
77+
}
78+
assert (
79+
er.async_get(hass).async_get(source_entity_id).hidden_by
80+
is er.RegistryEntryHider.INTEGRATION
81+
)
82+
83+
84+
async def test_options_flow_updates_hide_source_state(
85+
hass: HomeAssistant,
86+
) -> None:
87+
"""Test options flow hides and unhides the source entity."""
88+
source_entity_id = _create_source_entity(hass, Platform.SWITCH)
89+
entry = MockConfigEntry(
90+
domain=DOMAIN,
91+
title="Inverse source",
92+
options={
93+
"inverse_type": Platform.SWITCH,
94+
CONF_ENTITY_ID: source_entity_id,
95+
CONF_HIDE_SOURCE: False,
96+
},
97+
)
98+
entry.add_to_hass(hass)
99+
own_entity_id = (
100+
er.async_get(hass)
101+
.async_get_or_create(
102+
Platform.SWITCH,
103+
DOMAIN,
104+
"inverse_source",
105+
config_entry=entry,
106+
suggested_object_id="inverse_source",
107+
)
108+
.entity_id
109+
)
110+
111+
result = await hass.config_entries.options.async_init(entry.entry_id)
112+
113+
assert result["type"] is FlowResultType.FORM
114+
assert result["step_id"] == Platform.SWITCH
115+
schema = result["data_schema"].schema
116+
entity_selector = schema[next(iter(schema))]
117+
assert entity_selector.config["domain"] == [Platform.SWITCH]
118+
assert entity_selector.config["exclude_entities"] == [own_entity_id]
119+
120+
result = await hass.config_entries.options.async_configure(
121+
result["flow_id"],
122+
user_input={
123+
CONF_ENTITY_ID: source_entity_id,
124+
CONF_HIDE_SOURCE: True,
125+
},
126+
)
127+
128+
assert result["type"] is FlowResultType.CREATE_ENTRY
129+
assert result["data"] == {
130+
"inverse_type": Platform.SWITCH,
131+
CONF_ENTITY_ID: source_entity_id,
132+
CONF_HIDE_SOURCE: True,
133+
}
134+
assert (
135+
er.async_get(hass).async_get(source_entity_id).hidden_by
136+
is er.RegistryEntryHider.INTEGRATION
137+
)
138+
139+
hass.config_entries.async_update_entry(entry, options=result["data"])
140+
141+
result = await hass.config_entries.options.async_init(entry.entry_id)
142+
result = await hass.config_entries.options.async_configure(
143+
result["flow_id"],
144+
user_input={
145+
CONF_ENTITY_ID: source_entity_id,
146+
CONF_HIDE_SOURCE: False,
147+
},
148+
)
149+
150+
assert result["type"] is FlowResultType.CREATE_ENTRY
151+
assert result["data"] == {
152+
"inverse_type": Platform.SWITCH,
153+
CONF_ENTITY_ID: source_entity_id,
154+
CONF_HIDE_SOURCE: False,
155+
}
156+
assert er.async_get(hass).async_get(source_entity_id).hidden_by is None

tests/integrations/spook_inverse/test_init.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from custom_components.spook.integrations.spook_inverse import (
1313
MIGRATION_MINOR_VERSION,
1414
async_get_source_entity_device_id,
15+
async_remove_entry,
1516
)
1617
from custom_components.spook.integrations.spook_inverse.const import (
1718
CONF_HIDE_SOURCE,
@@ -116,3 +117,60 @@ async def test_async_migrate_entry_handles_unresolved_source_entity_id(
116117
await hass.async_block_till_done()
117118

118119
assert migrated_entry.minor_version == MIGRATION_MINOR_VERSION
120+
121+
122+
async def test_async_remove_entry_unhides_integration_hidden_source(
123+
hass: HomeAssistant,
124+
) -> None:
125+
"""Test remove entry unhides the source entity."""
126+
entity_registry = er.async_get(hass)
127+
entity_registry.async_get_or_create(
128+
"switch",
129+
"test",
130+
"source",
131+
suggested_object_id="source",
132+
hidden_by=er.RegistryEntryHider.INTEGRATION,
133+
)
134+
entry = MockConfigEntry(
135+
domain=DOMAIN,
136+
title="Inverse",
137+
options={
138+
CONF_ENTITY_ID: "switch.source",
139+
CONF_HIDE_SOURCE: True,
140+
"inverse_type": Platform.SWITCH,
141+
},
142+
)
143+
144+
await async_remove_entry(hass, entry)
145+
146+
assert entity_registry.async_get("switch.source").hidden_by is None
147+
148+
149+
async def test_async_remove_entry_preserves_user_hidden_source(
150+
hass: HomeAssistant,
151+
) -> None:
152+
"""Test remove entry leaves non-integration hidden source entities alone."""
153+
entity_registry = er.async_get(hass)
154+
entity_registry.async_get_or_create(
155+
"switch",
156+
"test",
157+
"source",
158+
suggested_object_id="source",
159+
hidden_by=er.RegistryEntryHider.USER,
160+
)
161+
entry = MockConfigEntry(
162+
domain=DOMAIN,
163+
title="Inverse",
164+
options={
165+
CONF_ENTITY_ID: "switch.source",
166+
CONF_HIDE_SOURCE: True,
167+
"inverse_type": Platform.SWITCH,
168+
},
169+
)
170+
171+
await async_remove_entry(hass, entry)
172+
173+
assert (
174+
entity_registry.async_get("switch.source").hidden_by
175+
is er.RegistryEntryHider.USER
176+
)

0 commit comments

Comments
 (0)