Skip to content

Commit bb1188f

Browse files
committed
Bump version
1 parent 912b59f commit bb1188f

File tree

11 files changed

+96
-43
lines changed

11 files changed

+96
-43
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# pytest-homeassistant-custom-component
22

3-
![HA core version](https://img.shields.io/static/v1?label=HA+core+version&message=2023.11.3&labelColor=blue)
3+
![HA core version](https://img.shields.io/static/v1?label=HA+core+version&message=2023.12.0b0&labelColor=blue)
44

55
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/MatthewFlamm/pytest-homeassistant-custom-component)
66

ha_version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2023.11.3
1+
2023.12.0b0

requirements_dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This file is originally from homeassistant/core and modified by pytest-homeassistant-custom-component.
22
astroid==3.0.1
3-
mypy==1.6.1
3+
mypy==1.7.1
44
pre-commit==3.5.0
55
pylint==3.0.2
66
types-aiofiles==23.2.0.0

requirements_test.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ pytest-test-groups==1.0.3
2323
pytest-sugar==0.9.7
2424
pytest-timeout==2.1.0
2525
pytest-unordered==0.5.2
26-
pytest-picked==0.4.6
26+
pytest-picked==0.5.0
2727
pytest-xdist==3.3.1
2828
pytest==7.4.3
2929
requests-mock==1.11.0
3030
respx==0.20.2
31-
syrupy==4.5.0
31+
syrupy==4.6.0
3232
tqdm==4.66.1
33-
homeassistant==2023.11.3
34-
SQLAlchemy==2.0.22
33+
homeassistant==2023.12.0b0
34+
SQLAlchemy==2.0.23
3535

3636
paho-mqtt==1.6.1
3737

src/pytest_homeassistant_custom_component/common.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ def async_create_task(coroutine, name=None):
272272
"homeassistant.helpers.restore_state.RestoreStateData.async_setup_dump",
273273
return_value=None,
274274
), patch(
275-
"homeassistant.helpers.restore_state.start.async_at_start"
275+
"homeassistant.helpers.restore_state.start.async_at_start",
276276
):
277277
await asyncio.gather(
278278
ar.async_load(hass),
@@ -302,6 +302,7 @@ def async_mock_service(
302302
schema: vol.Schema | None = None,
303303
response: ServiceResponse = None,
304304
supports_response: SupportsResponse | None = None,
305+
raise_exception: Exception | None = None,
305306
) -> list[ServiceCall]:
306307
"""Set up a fake service & return a calls log list to this service."""
307308
calls = []
@@ -310,10 +311,15 @@ def async_mock_service(
310311
def mock_service_log(call): # pylint: disable=unnecessary-lambda
311312
"""Mock service call."""
312313
calls.append(call)
314+
if raise_exception is not None:
315+
raise raise_exception
313316
return response
314317

315-
if supports_response is None and response is not None:
316-
supports_response = SupportsResponse.OPTIONAL
318+
if supports_response is None:
319+
if response is not None:
320+
supports_response = SupportsResponse.OPTIONAL
321+
else:
322+
supports_response = SupportsResponse.NONE
317323

318324
hass.services.async_register(
319325
domain,
@@ -987,15 +993,18 @@ def assert_setup_component(count, domain=None):
987993
async def mock_psc(hass, config_input, integration):
988994
"""Mock the prepare_setup_component to capture config."""
989995
domain_input = integration.domain
990-
res = await async_process_component_config(hass, config_input, integration)
996+
integration_config_info = await async_process_component_config(
997+
hass, config_input, integration
998+
)
999+
res = integration_config_info.config
9911000
config[domain_input] = None if res is None else res.get(domain_input)
9921001
_LOGGER.debug(
9931002
"Configuration for %s, Validated: %s, Original %s",
9941003
domain_input,
9951004
config[domain_input],
9961005
config_input.get(domain_input),
9971006
)
998-
return res
1007+
return integration_config_info
9991008

10001009
assert isinstance(config, dict)
10011010
with patch("homeassistant.config.async_process_component_config", mock_psc):
@@ -1304,11 +1313,12 @@ async def get_system_health_info(hass: HomeAssistant, domain: str) -> dict[str,
13041313
@contextmanager
13051314
def mock_config_flow(domain: str, config_flow: type[ConfigFlow]) -> None:
13061315
"""Mock a config flow handler."""
1307-
assert domain not in config_entries.HANDLERS
1316+
handler = config_entries.HANDLERS.get(domain)
13081317
config_entries.HANDLERS[domain] = config_flow
13091318
_LOGGER.info("Adding mock config flow: %s", domain)
13101319
yield
1311-
config_entries.HANDLERS.pop(domain)
1320+
if handler:
1321+
config_entries.HANDLERS[domain] = handler
13121322

13131323

13141324
def mock_integration(
@@ -1342,18 +1352,6 @@ def mock_import_platform(platform_name: str) -> NoReturn:
13421352
return integration
13431353

13441354

1345-
def mock_entity_platform(
1346-
hass: HomeAssistant, platform_path: str, module: MockPlatform | None
1347-
) -> None:
1348-
"""Mock a entity platform.
1349-
1350-
platform_path is in form light.hue. Will create platform
1351-
hue.light.
1352-
"""
1353-
domain, platform_name = platform_path.split(".")
1354-
mock_platform(hass, f"{platform_name}.{domain}", module)
1355-
1356-
13571355
def mock_platform(
13581356
hass: HomeAssistant, platform_path: str, module: Mock | MockPlatform | None = None
13591357
) -> None:

src/pytest_homeassistant_custom_component/components/recorder/common.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -416,17 +416,11 @@ def old_db_schema(schema_version_postfix: str) -> Iterator[None]:
416416
recorder.migration, "SCHEMA_VERSION", old_db_schema.SCHEMA_VERSION
417417
), patch.object(core, "StatesMeta", old_db_schema.StatesMeta), patch.object(
418418
core, "EventTypes", old_db_schema.EventTypes
419-
), patch.object(
420-
core, "EventData", old_db_schema.EventData
421-
), patch.object(
419+
), patch.object(core, "EventData", old_db_schema.EventData), patch.object(
422420
core, "States", old_db_schema.States
423-
), patch.object(
424-
core, "Events", old_db_schema.Events
425-
), patch.object(
421+
), patch.object(core, "Events", old_db_schema.Events), patch.object(
426422
core, "StateAttributes", old_db_schema.StateAttributes
427-
), patch.object(
428-
core, "EntityIDMigrationTask", core.RecorderTask
429-
), patch(
423+
), patch.object(core, "EntityIDMigrationTask", core.RecorderTask), patch(
430424
CREATE_ENGINE_TARGET,
431425
new=partial(
432426
create_engine_test_for_schema_version_postfix,

src/pytest_homeassistant_custom_component/const.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
APPLICATION_NAME: Final = "HomeAssistant"
1212
MAJOR_VERSION: Final = 2023
13-
MINOR_VERSION: Final = 11
14-
PATCH_VERSION: Final = "3"
13+
MINOR_VERSION: Final = 12
14+
PATCH_VERSION: Final = "0b0"
1515
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
1616
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
1717
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 11, 0)

src/pytest_homeassistant_custom_component/plugins.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,13 +1149,19 @@ def mock_zeroconf() -> Generator[None, None, None]:
11491149
@pytest.fixture
11501150
def mock_async_zeroconf(mock_zeroconf: None) -> Generator[None, None, None]:
11511151
"""Mock AsyncZeroconf."""
1152-
from zeroconf import DNSCache # pylint: disable=import-outside-toplevel
1152+
from zeroconf import DNSCache, Zeroconf # pylint: disable=import-outside-toplevel
1153+
from zeroconf.asyncio import ( # pylint: disable=import-outside-toplevel
1154+
AsyncZeroconf,
1155+
)
11531156

1154-
with patch("homeassistant.components.zeroconf.HaAsyncZeroconf") as mock_aiozc:
1157+
with patch(
1158+
"homeassistant.components.zeroconf.HaAsyncZeroconf", spec=AsyncZeroconf
1159+
) as mock_aiozc:
11551160
zc = mock_aiozc.return_value
11561161
zc.async_unregister_service = AsyncMock()
11571162
zc.async_register_service = AsyncMock()
11581163
zc.async_update_service = AsyncMock()
1164+
zc.zeroconf = Mock(spec=Zeroconf)
11591165
zc.zeroconf.async_wait_for_start = AsyncMock()
11601166
# DNSCache has strong Cython type checks, and MagicMock does not work
11611167
# so we must mock the class directly
Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,39 @@
11
"""
2-
Tests for the test utilities.
2+
Test utilities.
33
44
This file is originally from homeassistant/core and modified by pytest-homeassistant-custom-component.
55
"""
6+
from collections.abc import Awaitable, Callable
7+
8+
from aiohttp.web import Application, Request, StreamResponse, middleware
9+
10+
11+
def mock_real_ip(app: Application) -> Callable[[str], None]:
12+
"""Inject middleware to mock real IP.
13+
14+
Returns a function to set the real IP.
15+
"""
16+
ip_to_mock: str | None = None
17+
18+
def set_ip_to_mock(value: str):
19+
nonlocal ip_to_mock
20+
ip_to_mock = value
21+
22+
@middleware
23+
async def mock_real_ip(
24+
request: Request, handler: Callable[[Request], Awaitable[StreamResponse]]
25+
) -> StreamResponse:
26+
"""Mock Real IP middleware."""
27+
nonlocal ip_to_mock
28+
29+
request = request.clone(remote=ip_to_mock)
30+
31+
return await handler(request)
32+
33+
async def real_ip_startup(app):
34+
"""Startup of real ip."""
35+
app.middlewares.insert(0, mock_real_ip)
36+
37+
app.on_startup.append(real_ip_startup)
38+
39+
return set_ip_to_mock

src/pytest_homeassistant_custom_component/test_util/aiohttp.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
from urllib.parse import parse_qs
1212

1313
from aiohttp import ClientSession
14-
from aiohttp.client_exceptions import ClientError, ClientResponseError
14+
from aiohttp.client_exceptions import (
15+
ClientConnectionError,
16+
ClientError,
17+
ClientResponseError,
18+
)
1519
from aiohttp.streams import StreamReader
1620
from multidict import CIMultiDict
1721
from yarl import URL
@@ -57,6 +61,7 @@ def request(
5761
exc=None,
5862
cookies=None,
5963
side_effect=None,
64+
closing=None,
6065
):
6166
"""Mock a request."""
6267
if not isinstance(url, RETYPE):
@@ -76,6 +81,7 @@ def request(
7681
exc=exc,
7782
headers=headers,
7883
side_effect=side_effect,
84+
closing=closing,
7985
)
8086
)
8187

@@ -169,6 +175,7 @@ def __init__(
169175
exc=None,
170176
headers=None,
171177
side_effect=None,
178+
closing=None,
172179
):
173180
"""Initialize a fake response."""
174181
if json is not None:
@@ -182,9 +189,10 @@ def __init__(
182189
self.method = method
183190
self._url = url
184191
self.status = status
185-
self.response = response
192+
self._response = response
186193
self.exc = exc
187194
self.side_effect = side_effect
195+
self.closing = closing
188196
self._headers = CIMultiDict(headers or {})
189197
self._cookies = {}
190198

@@ -276,6 +284,19 @@ def raise_for_status(self):
276284
def close(self):
277285
"""Mock close."""
278286

287+
async def wait_for_close(self):
288+
"""Wait until all requests are done.
289+
290+
Do nothing as we are mocking.
291+
"""
292+
293+
@property
294+
def response(self):
295+
"""Property method to expose the response to other read methods."""
296+
if self.closing:
297+
raise ClientConnectionError("Connection closed")
298+
return self._response
299+
279300

280301
@contextmanager
281302
def mock_aiohttp_client():

0 commit comments

Comments
 (0)