File: conftest.py

package info (click to toggle)
python-intellifire4py 4.1.9-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 620 kB
  • sloc: python: 2,585; sh: 13; makefile: 5
file content (440 lines) | stat: -rw-r--r-- 12,380 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
"""Shared config file."""

import asyncio
import os
from collections.abc import Generator
from contextlib import ExitStack
from unittest.mock import patch

import pytest
from aioresponses import aioresponses

from intellifire4py.const import IntelliFireApiMode
from intellifire4py.model import IntelliFireCommonFireplaceData, IntelliFireUserData


# Define fixtures for various test scenarios.


@pytest.fixture()
def mock_common_data_local(
    api_key, user_id, serial, ip, auth_cookie, web_client_id
) -> IntelliFireCommonFireplaceData:
    """Fixture for mock common data."""
    return IntelliFireCommonFireplaceData(
        auth_cookie=auth_cookie,
        user_id=user_id,
        web_client_id=web_client_id,
        serial=serial,
        api_key=api_key,
        ip_address=ip,
        read_mode=IntelliFireApiMode.LOCAL,
        control_mode=IntelliFireApiMode.LOCAL,
    )


@pytest.fixture()
def mock_user_data(
    auth_cookie, user_id, web_client_id, mock_common_data_local
) -> IntelliFireUserData:
    """Fixture for mock user data."""
    return IntelliFireUserData(
        auth_cookie=auth_cookie,
        user_id=user_id,
        web_client_id=web_client_id,
        username="",
        password="",
        fireplaces=[mock_common_data_local],
    )


@pytest.fixture()
def mock_common_data_cloud(
    api_key, user_id, serial, ip, auth_cookie, web_client_id
) -> IntelliFireCommonFireplaceData:
    """Fixture for mock common data."""
    return IntelliFireCommonFireplaceData(
        auth_cookie=auth_cookie,
        user_id=user_id,
        web_client_id=web_client_id,
        serial=serial,
        api_key=api_key,
        ip_address=ip,
        read_mode=IntelliFireApiMode.CLOUD,
        control_mode=IntelliFireApiMode.CLOUD,
    )


@pytest.fixture()
def mock_common_data_none(
    api_key, user_id, serial, ip, web_client_id, auth_cookie
) -> IntelliFireCommonFireplaceData:
    """Fixture for mock common data."""
    return IntelliFireCommonFireplaceData(
        auth_cookie=auth_cookie,
        user_id=user_id,
        web_client_id=web_client_id,
        serial=serial,
        api_key=api_key,
        ip_address=ip,
        read_mode=IntelliFireApiMode.NONE,
        control_mode=IntelliFireApiMode.NONE,
    )


@pytest.fixture
def local_poll_json() -> str:
    """Define a fixture to hold response data."""
    # Reads and returns the content of local_poll.json
    return open(f"{os.path.dirname(__file__)}/fixtures/local_poll.json").read()


@pytest.fixture
def poll_response_text_error_6_642() -> str:
    """Define a fixture to hold response data."""
    # Reads and returns the content of error_6_642.json
    return open(f"{os.path.dirname(__file__)}/fixtures/error_6_642.json").read()


@pytest.fixture
def enum_locations_json() -> str:
    """Define a fixture to hold response data."""
    # Reads and returns the content of enumlocations.json
    return open(f"{os.path.dirname(__file__)}/fixtures/enumlocations.json").read()


@pytest.fixture
def enum_fireplaces_json() -> str:
    """Define a fixture to hold response data."""
    # Reads and returns the content of enumfireplaces.json
    return open(f"{os.path.dirname(__file__)}/fixtures/enumfireplaces.json").read()


@pytest.fixture
def cloud_poll_json() -> str:
    """Define a fixture to hold response data."""
    # Reads and returns the content of cloud_poll.json
    return open(f"{os.path.dirname(__file__)}/fixtures/cloud_poll.json").read()


@pytest.fixture
def user_id() -> str:
    """Return mock user id."""
    # Returns a mock user ID
    return "XXXXE5DA5C74BD88ED1BC00716791092DE495232B69B4631CD79F90ADC10580E"


@pytest.fixture
def api_key() -> str:
    """Mock api key."""
    # Returns a mock API key
    return "12345BDB2D97B3DC7CEE8A8B05DD5FFA"


@pytest.fixture
def serial() -> str:
    """Mock serial number."""
    return "XXXXXE834CE109D849CBB15CDDBAFF381"


@pytest.fixture
def ip() -> str:
    """Mock IP address."""
    return "192.168.1.69"


@pytest.fixture
def challenge_text() -> str:
    """Mock challenge text."""
    # Returns a mock challenge text
    return "82FC7D369EC9B59B1A054ADE85F2AF76"


@pytest.fixture
def cookies(user_id: str) -> list[tuple[str, str]]:
    """Mock cookies."""
    # Returns a list of mock cookies
    return [
        ("set-cookie", "auth_cookie=XXXX1B56D18B52DC8F94DC0E5DC89A90"),
        ("set-cookie", f"user={user_id}"),
        ("set-cookie", "web_client_id=XXXX21C9A75384EA726071BFCC95E3F6"),
    ]


@pytest.fixture
def auth_cookie() -> str:
    """Mock auth cookie."""
    return "XXXX1B56D18B52DC8F94DC0E5DC89A90"


@pytest.fixture()
def web_client_id() -> str:
    """Mock web client id."""
    return "XXXX21C9A75384EA726071BFCC95E3F6"


@pytest.fixture
def mock_aioresponse() -> Generator[aioresponses, None, None]:
    """Mock out an aioresponse but i'm not sure if we even use this."""
    # Context manager for mocking aiohttp responses
    with aioresponses() as m:
        yield m


def setup_common_mocks(
    m: aioresponses,
    serial: str,
    cookies: list[tuple[str, str]],
    enum_locations_json: str,
    enum_fireplaces_json: str,
    cloud_poll_json: str,
    repeat: bool = False,
) -> None:
    """Sets up common mocks for HTTP requests."""
    # Mock the POST login request
    m.post("https://iftapi.net/a/login", status=204, headers=cookies)

    # Mock the GET enumlocations request
    m.get("https://iftapi.net/a/enumlocations", status=200, body=enum_locations_json)

    # Mock additional HTTP requests as needed
    m.get(
        "https://iftapi.net/a/enumfireplaces?location_id=11118333339267293392",
        status=200,
        body=enum_fireplaces_json,
    )
    m.get(
        f"https://iftapi.net/a/{serial}//apppoll",
        status=200,
        body=cloud_poll_json,
        repeat=repeat,
    )


@pytest.fixture
def mock_cloud_login_flow_no_local(
    cookies: list[tuple[str, str]],
    enum_locations_json: str,
    enum_fireplaces_json: str,
    cloud_poll_json: str,
    local_poll_json: str,
    serial: str,
    ip: str,
) -> Generator[aioresponses, None, None]:
    """Mock the login flow."""
    with aioresponses() as m:
        setup_common_mocks(
            m,
            serial,
            cookies,
            enum_locations_json,
            enum_fireplaces_json,
            cloud_poll_json,
            repeat=True,
        )
        yield m


@pytest.fixture
def mock_login_flow_with_local_and_cloud(
    cookies: list[tuple[str, str]],
    enum_locations_json: str,
    enum_fireplaces_json: str,
    cloud_poll_json: str,
    local_poll_json: str,
    serial: str,
    ip: str,
) -> Generator[aioresponses, None, None]:
    """Mock the login flow."""
    with aioresponses() as m:
        setup_common_mocks(
            m,
            serial,
            cookies,
            enum_locations_json,
            enum_fireplaces_json,
            cloud_poll_json,
            repeat=True,
        )
        m.get(url=f"http://{ip}/poll", body=local_poll_json, repeat=True)
        yield m


@pytest.fixture
def mock_login_flow_with_cloud_only(
    cookies: list[tuple[str, str]],
    enum_locations_json: str,
    enum_fireplaces_json: str,
    cloud_poll_json: str,
    local_poll_json: str,
    serial: str,
    ip: str,
) -> Generator[aioresponses, None, None]:
    """Mock the login flow."""
    with aioresponses() as m:
        setup_common_mocks(
            m,
            serial,
            cookies,
            enum_locations_json,
            enum_fireplaces_json,
            cloud_poll_json,
            repeat=True,
        )
        m.get(url=f"http://{ip}/poll", status=404, repeat=True)
        yield m


@pytest.fixture
def mock_cloud_login_flow_connectivity_testing(
    cookies: list[tuple[str, str]],
    enum_locations_json: str,
    enum_fireplaces_json: str,
    cloud_poll_json: str,
    local_poll_json: str,
    serial: str,
    ip: str,
) -> Generator[aioresponses, None, None]:
    """Test connectivity."""
    with aioresponses() as m:
        # Mock the POST login request
        setup_common_mocks(
            m,
            serial,
            cookies,
            enum_locations_json,
            enum_fireplaces_json,
            cloud_poll_json,
            repeat=False,
        )

        # Double 404
        m.get(
            f"https://iftapi.net/a/{serial}//apppoll",
            status=404,
            # body=cloud_poll_json,
            # repeat=False,
        )
        m.get(
            url=f"http://{ip}/poll",
            status=404,
        )

        # 403 / timeout
        m.get(
            f"https://iftapi.net/a/{serial}//apppoll",
            status=403,  # bad credentials
        )
        m.get(
            url=f"http://{ip}/poll",
            body=None,
            exception=asyncio.TimeoutError(),
        )

        # All is finally good
        m.get(
            f"https://iftapi.net/a/{serial}//apppoll",
            status=200,
            body=cloud_poll_json,
            repeat=False,
        )
        m.get(
            url=f"http://{ip}/poll",
            status=200,
            body=local_poll_json,
        )
        yield m


@pytest.fixture
def mock_login_for_control_testing(
    cookies: list[tuple[str, str]],
    enum_locations_json: str,
    enum_fireplaces_json: str,
    cloud_poll_json: str,
    local_poll_json: str,
    challenge_text: str,
    serial: str,
    ip: str,
) -> Generator[aioresponses, None, None]:
    """Fixture for mocking login process for control testing."""
    # Using 'aioresponses' for mocking asynchronous HTTP responses.
    with aioresponses() as m:
        # Set up common mocks for the test.
        setup_common_mocks(
            m,
            serial,
            cookies,
            enum_locations_json,
            enum_fireplaces_json,
            cloud_poll_json,
            repeat=False,
        )

        # Mock successful polling of the application.
        m.get(
            f"https://iftapi.net/a/{serial}//apppoll",
            status=200,
            body=cloud_poll_json,
            repeat=True,
        )

        # Mock successful POST request for cloud-based operations.
        m.post(
            f"https://iftapi.net/a/{serial}//apppost",
            repeat=True,
            status=204,
        )

        # Mock successful polling of local endpoint.
        m.get(f"http://{ip}/poll", body=local_poll_json, repeat=True)

        # Mock retrieval of a challenge text from the local endpoint.
        m.get(f"http://{ip}/get_challenge", body=challenge_text, repeat=True)

        # Mock POST request to the local control endpoint.
        m.post(f"http://{ip}/post", repeat=True)
        yield m


@pytest.fixture
def mock_login_bad_credentials() -> Generator[aioresponses, None, None]:
    """Fixture for mocking a login process with bad credentials."""
    # Using 'aioresponses' to mock asynchronous HTTP responses.
    with aioresponses() as m:
        # Mock a failed login attempt due to bad credentials.
        m.post("https://iftapi.net/a/login", status=403)
        yield m


@pytest.fixture
def mock_background_polling() -> Generator:
    """Fixture for mocking background polling."""
    with ExitStack() as stack:
        local_stop_mock = stack.enter_context(
            patch("intellifire4py.IntelliFireAPILocal.stop_background_polling")
        )
        cloud_stop_mock = stack.enter_context(
            patch("intellifire4py.IntelliFireAPICloud.stop_background_polling")
        )
        # abstract_stop_mock = stack.enter_context(
        #     patch("intellifire4py.IntelliFireDataProvider.stop_background_polling")
        # )
        local_start_mock = stack.enter_context(
            patch("intellifire4py.IntelliFireAPILocal.start_background_polling")
        )
        cloud_start_mock = stack.enter_context(
            patch("intellifire4py.IntelliFireAPICloud.start_background_polling")
        )
        # abstract_start_mock = stack.enter_context(
        #     patch("intellifire4py.IntelliFireDataProvider.start_background_polling")
        # )

        yield {
            "local_stop": local_stop_mock,
            "cloud_stop": cloud_stop_mock,
            # "abstract_stop": abstract_stop_mock,
            "local_start": local_start_mock,
            "cloud_start": cloud_start_mock,
            # "abstract_start": abstract_start_mock,
        }