aiohomematic-test-support 2025.12.26__tar.gz → 2025.12.54__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {aiohomematic_test_support-2025.12.26/aiohomematic_test_support.egg-info → aiohomematic_test_support-2025.12.54}/PKG-INFO +2 -2
  2. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/__init__.py +32 -1
  3. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54/aiohomematic_test_support.egg-info}/PKG-INFO +2 -2
  4. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/aiohomematic_test_support.egg-info/SOURCES.txt +6 -0
  5. aiohomematic_test_support-2025.12.54/const.py +264 -0
  6. aiohomematic_test_support-2025.12.54/data/device_translation.json +364 -0
  7. aiohomematic_test_support-2025.12.54/event_capture.py +256 -0
  8. aiohomematic_test_support-2025.12.54/event_mock.py +300 -0
  9. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/factory.py +25 -10
  10. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/helper.py +5 -3
  11. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/mock.py +48 -13
  12. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/pyproject.toml +1 -0
  13. aiohomematic_test_support-2025.12.26/const.py +0 -603
  14. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/MANIFEST.in +0 -0
  15. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/README.md +0 -0
  16. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/aiohomematic_test_support.egg-info/dependency_links.txt +0 -0
  17. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/aiohomematic_test_support.egg-info/top_level.txt +0 -0
  18. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/data/full_session_randomized_ccu.zip +0 -0
  19. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/data/full_session_randomized_pydevccu.zip +0 -0
  20. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/py.typed +0 -0
  21. {aiohomematic_test_support-2025.12.26 → aiohomematic_test_support-2025.12.54}/setup.cfg +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiohomematic-test-support
3
- Version: 2025.12.26
3
+ Version: 2025.12.54
4
4
  Summary: Support-only package for AioHomematic (tests/dev). Not part of production builds.
5
- Author-email: SukramJ <sukramj@icloud.com>
5
+ Author-email: SukramJ <sukramj@icloud.com>, Daniel Perna <danielperna84@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/SukramJ/aiohomematic
7
7
  Classifier: Development Status :: 3 - Alpha
8
8
  Classifier: Intended Audience :: Developers
@@ -1,3 +1,5 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2021-2025
1
3
  """
2
4
  Test support infrastructure for aiohomematic.
3
5
 
@@ -16,6 +18,8 @@ Key Components
16
18
  playback support for deterministic testing.
17
19
  - **helper**: Test helper utilities for common testing operations.
18
20
  - **const**: Test-specific constants and configuration values.
21
+ - **event_capture**: Event capture and assertion utilities for behavior testing.
22
+ - **event_mock**: Event-driven mock server for test triggers.
19
23
 
20
24
  Usage Example
21
25
  -------------
@@ -33,6 +37,33 @@ Using the factory to create a test central with session playback:
33
37
  device = central.device_coordinator.get_device_by_address("VCU0000001")
34
38
  await central.stop()
35
39
 
40
+ Using EventCapture for behavior-focused testing:
41
+
42
+ from aiohomematic_test_support.event_capture import EventCapture
43
+ from aiohomematic.central.event_bus import CircuitBreakerTrippedEvent
44
+
45
+ capture = EventCapture()
46
+ capture.subscribe_to(central.event_bus, CircuitBreakerTrippedEvent)
47
+
48
+ # ... trigger failures ...
49
+
50
+ capture.assert_event_emitted(CircuitBreakerTrippedEvent, failure_count=5)
51
+ capture.cleanup()
52
+
53
+ Using EventDrivenMockServer for event-triggered test behavior:
54
+
55
+ from aiohomematic_test_support.event_mock import EventDrivenMockServer
56
+ from aiohomematic.central.event_bus import DataRefreshTriggeredEvent
57
+
58
+ mock_server = EventDrivenMockServer(event_bus=central.event_bus)
59
+ mock_server.when(DataRefreshTriggeredEvent).then_call(
60
+ lambda event: inject_mock_data()
61
+ )
62
+
63
+ # ... trigger refresh ...
64
+
65
+ mock_server.cleanup()
66
+
36
67
  The session player replays pre-recorded backend responses, enabling fast and
37
68
  reproducible tests without backend dependencies.
38
69
 
@@ -45,4 +76,4 @@ test dependencies to access test support functionality.
45
76
 
46
77
  from __future__ import annotations
47
78
 
48
- __version__ = "2025.12.26"
79
+ __version__ = "2025.12.54"
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiohomematic-test-support
3
- Version: 2025.12.26
3
+ Version: 2025.12.54
4
4
  Summary: Support-only package for AioHomematic (tests/dev). Not part of production builds.
5
- Author-email: SukramJ <sukramj@icloud.com>
5
+ Author-email: SukramJ <sukramj@icloud.com>, Daniel Perna <danielperna84@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/SukramJ/aiohomematic
7
7
  Classifier: Development Status :: 3 - Alpha
8
8
  Classifier: Intended Audience :: Developers
@@ -2,6 +2,8 @@ MANIFEST.in
2
2
  README.md
3
3
  __init__.py
4
4
  const.py
5
+ event_capture.py
6
+ event_mock.py
5
7
  factory.py
6
8
  helper.py
7
9
  mock.py
@@ -9,15 +11,19 @@ py.typed
9
11
  pyproject.toml
10
12
  ./__init__.py
11
13
  ./const.py
14
+ ./event_capture.py
15
+ ./event_mock.py
12
16
  ./factory.py
13
17
  ./helper.py
14
18
  ./mock.py
15
19
  ./py.typed
20
+ ./data/device_translation.json
16
21
  ./data/full_session_randomized_ccu.zip
17
22
  ./data/full_session_randomized_pydevccu.zip
18
23
  aiohomematic_test_support.egg-info/PKG-INFO
19
24
  aiohomematic_test_support.egg-info/SOURCES.txt
20
25
  aiohomematic_test_support.egg-info/dependency_links.txt
21
26
  aiohomematic_test_support.egg-info/top_level.txt
27
+ data/device_translation.json
22
28
  data/full_session_randomized_ccu.zip
23
29
  data/full_session_randomized_pydevccu.zip
@@ -0,0 +1,264 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2021-2025
3
+ """Constants for tests."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import functools
8
+ import json
9
+ import os
10
+ from typing import cast
11
+
12
+ from aiohomematic.client.json_rpc import _JsonKey
13
+ from aiohomematic.const import LOCAL_HOST, UTF_8, HubValueType, Interface, ProgramData, SystemVariableData
14
+
15
+ CENTRAL_NAME = "CentralTest"
16
+ CCU_HOST = LOCAL_HOST
17
+ CCU_USERNAME = "user"
18
+ CCU_PASSWORD = "pass"
19
+ CCU_PORT = 2002
20
+ CCU_MINI_PORT = 2003
21
+ INTERFACE_ID = f"{CENTRAL_NAME}-{Interface.BIDCOS_RF}"
22
+
23
+ # Backend info response for get_backend_info.fn script
24
+ BACKEND_INFO_JSON = {
25
+ "version": "3.75.6.20240316",
26
+ "product": "CCU3",
27
+ "hostname": "ccu-test",
28
+ }
29
+
30
+ FULL_SESSION_RANDOMIZED_PYDEVCCU = "full_session_randomized_pydevccu.zip"
31
+ FULL_SESSION_RANDOMIZED_CCU = "full_session_randomized_ccu.zip"
32
+
33
+ ALL_SESSION_FILES = [
34
+ FULL_SESSION_RANDOMIZED_PYDEVCCU,
35
+ FULL_SESSION_RANDOMIZED_CCU,
36
+ ]
37
+
38
+
39
+ SYSVAR_DATA: list[SystemVariableData] = [
40
+ SystemVariableData(
41
+ vid="1",
42
+ legacy_name="alarm",
43
+ description="",
44
+ data_type=HubValueType.ALARM,
45
+ unit=None,
46
+ value=False,
47
+ values=None,
48
+ max_value=None,
49
+ min_value=None,
50
+ extended_sysvar=False,
51
+ ),
52
+ SystemVariableData(
53
+ vid="2",
54
+ legacy_name="alarm_ext",
55
+ description="HAHM",
56
+ data_type=HubValueType.ALARM,
57
+ unit=None,
58
+ value=False,
59
+ values=None,
60
+ max_value=None,
61
+ min_value=None,
62
+ extended_sysvar=True,
63
+ ),
64
+ SystemVariableData(
65
+ vid="3",
66
+ legacy_name="logic",
67
+ description="",
68
+ data_type=HubValueType.LOGIC,
69
+ unit=None,
70
+ value=False,
71
+ values=None,
72
+ max_value=None,
73
+ min_value=None,
74
+ extended_sysvar=False,
75
+ ),
76
+ SystemVariableData(
77
+ vid="4",
78
+ legacy_name="logic_ext",
79
+ description="HAHM",
80
+ data_type=HubValueType.LOGIC,
81
+ unit=None,
82
+ value=False,
83
+ values=None,
84
+ max_value=None,
85
+ min_value=None,
86
+ extended_sysvar=True,
87
+ ),
88
+ SystemVariableData(
89
+ vid="5",
90
+ legacy_name="list",
91
+ description="",
92
+ data_type=HubValueType.LIST,
93
+ unit=None,
94
+ value=0,
95
+ values=("v1", "v2", "v3"),
96
+ max_value=None,
97
+ min_value=None,
98
+ extended_sysvar=False,
99
+ ),
100
+ SystemVariableData(
101
+ vid="6",
102
+ legacy_name="list_ext",
103
+ description="HAHM",
104
+ data_type=HubValueType.LIST,
105
+ unit=None,
106
+ value=0,
107
+ values=("v1", "v2", "v3"),
108
+ max_value=None,
109
+ min_value=None,
110
+ extended_sysvar=True,
111
+ ),
112
+ SystemVariableData(
113
+ vid="7",
114
+ legacy_name="string",
115
+ description="",
116
+ data_type=HubValueType.STRING,
117
+ unit=None,
118
+ value="test1",
119
+ values=None,
120
+ max_value=None,
121
+ min_value=None,
122
+ extended_sysvar=False,
123
+ ),
124
+ SystemVariableData(
125
+ vid="8",
126
+ legacy_name="string_ext",
127
+ description="HAHM",
128
+ data_type=HubValueType.STRING,
129
+ unit=None,
130
+ value="test1",
131
+ values=None,
132
+ max_value=None,
133
+ min_value=None,
134
+ extended_sysvar=True,
135
+ ),
136
+ SystemVariableData(
137
+ vid="9",
138
+ legacy_name="float",
139
+ description="",
140
+ data_type=HubValueType.FLOAT,
141
+ unit=None,
142
+ value=23.2,
143
+ values=None,
144
+ max_value=30.0,
145
+ min_value=5.0,
146
+ extended_sysvar=False,
147
+ ),
148
+ SystemVariableData(
149
+ vid="10",
150
+ legacy_name="float_ext",
151
+ description="HAHM",
152
+ data_type=HubValueType.FLOAT,
153
+ unit="°C",
154
+ value=23.2,
155
+ values=None,
156
+ max_value=30.0,
157
+ min_value=5.0,
158
+ extended_sysvar=True,
159
+ ),
160
+ SystemVariableData(
161
+ vid="11",
162
+ legacy_name="integer",
163
+ description="",
164
+ data_type=HubValueType.INTEGER,
165
+ unit=None,
166
+ value=17,
167
+ values=None,
168
+ max_value=30,
169
+ min_value=5,
170
+ extended_sysvar=False,
171
+ ),
172
+ SystemVariableData(
173
+ vid="12",
174
+ legacy_name="integer_ext",
175
+ description="HAHM",
176
+ data_type=HubValueType.INTEGER,
177
+ unit=None,
178
+ value=17,
179
+ values=None,
180
+ max_value=30,
181
+ min_value=5,
182
+ extended_sysvar=True,
183
+ ),
184
+ ]
185
+
186
+
187
+ SYSVAR_DATA_JSON = [
188
+ {
189
+ _JsonKey.ID: sv.vid,
190
+ _JsonKey.IS_INTERNAL: False,
191
+ _JsonKey.MAX_VALUE: sv.max_value,
192
+ _JsonKey.MIN_VALUE: sv.min_value,
193
+ _JsonKey.NAME: sv.legacy_name,
194
+ _JsonKey.TYPE: sv.data_type,
195
+ _JsonKey.UNIT: sv.unit,
196
+ _JsonKey.VALUE: sv.value,
197
+ _JsonKey.VALUE_LIST: ";".join(sv.values) if sv.values else None,
198
+ }
199
+ for sv in SYSVAR_DATA
200
+ ]
201
+ SYSVAR_DATA_JSON_DESCRIPTION = [
202
+ {
203
+ _JsonKey.ID: sv.vid,
204
+ _JsonKey.DESCRIPTION: sv.description,
205
+ }
206
+ for sv in SYSVAR_DATA
207
+ ]
208
+
209
+ SYSVAR_DATA_XML = {sv.legacy_name: sv.value for sv in SYSVAR_DATA}
210
+
211
+ PROGRAM_DATA: list[ProgramData] = [
212
+ ProgramData(
213
+ legacy_name="p1",
214
+ pid="pid1",
215
+ description="1",
216
+ is_active=True,
217
+ is_internal=False,
218
+ last_execute_time="",
219
+ ),
220
+ ProgramData(
221
+ legacy_name="p_2",
222
+ pid="pid2",
223
+ description="2",
224
+ is_active=False,
225
+ is_internal=False,
226
+ last_execute_time="",
227
+ ),
228
+ ]
229
+ PROGRAM_DATA_JSON = [
230
+ {
231
+ _JsonKey.ID: p.pid,
232
+ _JsonKey.IS_ACTIVE: p.is_active,
233
+ _JsonKey.IS_INTERNAL: p.is_internal,
234
+ _JsonKey.LAST_EXECUTE_TIME: p.last_execute_time,
235
+ _JsonKey.NAME: p.legacy_name,
236
+ }
237
+ for p in PROGRAM_DATA
238
+ ]
239
+ PROGRAM_DATA_JSON_DESCRIPTION = [
240
+ {
241
+ _JsonKey.ID: p.pid,
242
+ _JsonKey.DESCRIPTION: p.description,
243
+ }
244
+ for p in PROGRAM_DATA
245
+ ]
246
+
247
+
248
+ @functools.cache
249
+ def _load_device_translation() -> dict[str, str]:
250
+ """Load device translation mapping from JSON file."""
251
+ file_path = os.path.join(os.path.dirname(__file__), "data", "device_translation.json")
252
+ if os.path.exists(file_path):
253
+ with open(file_path, encoding=UTF_8) as f:
254
+ return cast(dict[str, str], json.load(f))
255
+ return {}
256
+
257
+
258
+ def get_address_device_translation() -> dict[str, str]:
259
+ """Return the address to device translation mapping."""
260
+ return _load_device_translation()
261
+
262
+
263
+ # Public accessor - use this instead of direct dict access
264
+ ADDRESS_DEVICE_TRANSLATION = get_address_device_translation()