Skip to content

Commit 84b0d39

Browse files
authored
clean up velux test fixtures (home-assistant#156554)
1 parent 3aff225 commit 84b0d39

File tree

5 files changed

+422
-106
lines changed

5 files changed

+422
-106
lines changed

tests/components/velux/conftest.py

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
from unittest.mock import AsyncMock, MagicMock, patch
55

66
import pytest
7+
from pyvlx.lightening_device import LighteningDevice
8+
from pyvlx.opening_device import Blind, Window
79

810
from homeassistant.components.velux import DOMAIN
9-
from homeassistant.components.velux.binary_sensor import Window
10-
from homeassistant.components.velux.light import LighteningDevice
1111
from homeassistant.components.velux.scene import PyVLXScene as Scene
1212
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_PASSWORD, Platform
1313
from homeassistant.core import HomeAssistant
@@ -26,22 +26,10 @@ def mock_setup_entry() -> Generator[AsyncMock]:
2626

2727

2828
@pytest.fixture
29-
def mock_velux_client() -> Generator[AsyncMock]:
30-
"""Mock a Velux client."""
31-
with (
32-
patch(
33-
"homeassistant.components.velux.config_flow.PyVLX",
34-
autospec=True,
35-
) as mock_client,
36-
):
37-
client = mock_client.return_value
38-
yield client
39-
40-
41-
@pytest.fixture
42-
def mock_user_config_entry() -> MockConfigEntry:
43-
"""Return the user config entry."""
29+
def mock_config_entry() -> MockConfigEntry:
30+
"""Return a mock config entry (unified fixture for all tests)."""
4431
return MockConfigEntry(
32+
entry_id="test_entry_id",
4533
domain=DOMAIN,
4634
title="127.0.0.1",
4735
data={
@@ -66,7 +54,8 @@ def mock_discovered_config_entry() -> MockConfigEntry:
6654
)
6755

6856

69-
# fixtures for the binary sensor tests
57+
# various types of fixtures for specific node types
58+
# first the window
7059
@pytest.fixture
7160
def mock_window() -> AsyncMock:
7261
"""Create a mock Velux window with a rain sensor."""
@@ -81,6 +70,27 @@ def mock_window() -> AsyncMock:
8170
return window
8271

8372

73+
# a blind
74+
@pytest.fixture
75+
def mock_blind() -> AsyncMock:
76+
"""Create a mock Velux blind (cover with tilt)."""
77+
blind = AsyncMock(spec=Blind, autospec=True)
78+
blind.name = "Test Blind"
79+
blind.serial_number = "4711"
80+
# Standard cover position (used by current_cover_position)
81+
blind.position = MagicMock(position_percent=40, closed=False)
82+
blind.is_opening = False
83+
blind.is_closing = False
84+
# Orientation/tilt-related attributes and methods
85+
blind.orientation = MagicMock(position_percent=25)
86+
blind.open_orientation = AsyncMock()
87+
blind.close_orientation = AsyncMock()
88+
blind.stop_orientation = AsyncMock()
89+
blind.set_orientation = AsyncMock()
90+
return blind
91+
92+
93+
# a light
8494
@pytest.fixture
8595
def mock_light() -> AsyncMock:
8696
"""Create a mock Velux light."""
@@ -91,50 +101,72 @@ def mock_light() -> AsyncMock:
91101
return light
92102

93103

104+
# fixture to create all other cover types via parameterization
94105
@pytest.fixture
95-
def mock_scene() -> AsyncMock:
96-
"""Create a mock Velux scene."""
97-
scene = AsyncMock(spec=Scene, autospec=True)
98-
scene.name = "Test Scene"
99-
scene.scene_id = "1234"
100-
scene.scene = AsyncMock()
101-
return scene
106+
def mock_cover_type(request: pytest.FixtureRequest) -> AsyncMock:
107+
"""Create a mock Velux cover of specified type."""
108+
cover = AsyncMock(spec=request.param, autospec=True)
109+
cover.name = f"Test {request.param.__name__}"
110+
cover.serial_number = f"serial_{request.param.__name__}"
111+
cover.is_opening = False
112+
cover.is_closing = False
113+
cover.position = MagicMock(position_percent=30, closed=False)
114+
return cover
102115

103116

104117
@pytest.fixture
105118
def mock_pyvlx(
106-
mock_window: MagicMock, mock_light: MagicMock, mock_scene: AsyncMock
119+
mock_scene: AsyncMock,
120+
mock_light: AsyncMock,
121+
mock_window: AsyncMock,
122+
mock_blind: AsyncMock,
123+
request: pytest.FixtureRequest,
107124
) -> Generator[MagicMock]:
108-
"""Create the library mock and patch PyVLX."""
125+
"""Create the library mock and patch PyVLX in both component and config_flow.
126+
127+
Tests can parameterize this fixture with the name of a node fixture to include
128+
(e.g., "mock_window", "mock_blind", "mock_light", or "mock_cover_type").
129+
If no parameter is provided, an empty node list is used.
130+
"""
131+
109132
pyvlx = MagicMock()
110-
pyvlx.nodes = [mock_window, mock_light]
133+
134+
if hasattr(request, "param"):
135+
pyvlx.nodes = [request.getfixturevalue(request.param)]
136+
else:
137+
pyvlx.nodes = [mock_light, mock_blind, mock_window, mock_cover_type]
138+
111139
pyvlx.scenes = [mock_scene]
140+
141+
# Async methods invoked by the integration/config flow
112142
pyvlx.load_scenes = AsyncMock()
113143
pyvlx.load_nodes = AsyncMock()
144+
pyvlx.connect = AsyncMock()
114145
pyvlx.disconnect = AsyncMock()
115146

116-
with patch("homeassistant.components.velux.PyVLX", return_value=pyvlx):
147+
with (
148+
patch("homeassistant.components.velux.PyVLX", return_value=pyvlx),
149+
patch("homeassistant.components.velux.config_flow.PyVLX", return_value=pyvlx),
150+
):
117151
yield pyvlx
118152

119153

120154
@pytest.fixture
121-
def mock_config_entry() -> MockConfigEntry:
122-
"""Return a mock config entry."""
123-
return MockConfigEntry(
124-
entry_id="test_entry_id",
125-
domain=DOMAIN,
126-
data={
127-
CONF_HOST: "testhost",
128-
CONF_PASSWORD: "testpw",
129-
},
130-
)
155+
def mock_scene() -> AsyncMock:
156+
"""Create a mock Velux scene."""
157+
scene = AsyncMock(spec=Scene, autospec=True)
158+
scene.name = "Test Scene"
159+
scene.scene_id = "1234"
160+
scene.scene = AsyncMock()
161+
return scene
131162

132163

164+
# Fixture to set up the integration for testing, needs platform fixture, to be defined in each test file
133165
@pytest.fixture
134166
async def setup_integration(
135167
hass: HomeAssistant,
136168
mock_config_entry: MockConfigEntry,
137-
mock_pyvlx: MagicMock,
169+
mock_pyvlx: AsyncMock,
138170
platform: Platform,
139171
) -> None:
140172
"""Set up the integration for testing."""

0 commit comments

Comments
 (0)