File: test_core_on_device.py

package info (click to toggle)
python-aioairq 0.4.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 152 kB
  • sloc: python: 594; makefile: 5
file content (253 lines) | stat: -rw-r--r-- 7,252 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
"""Collection of tests meant to run on a physical device.

Device credentials are specified via the environment variables AIRQ_{IP,PASS,HOSTNAME}.
"""

import os
import re

import aiohttp
import pytest
import pytest_asyncio

from aioairq import AirQ, DeviceLedTheme, DeviceLedThemePatch, NightMode
from aioairq.exceptions import APIAccessDenied

PASS = os.environ.get("AIRQ_PASS", "placeholder_password")
IP = os.environ.get("AIRQ_IP", "192.168.0.0")
HOSTNAME = os.environ.get("AIRQ_HOSTNAME", "")


@pytest_asyncio.fixture()
async def session():
    session = aiohttp.ClientSession()
    yield session
    await session.close()


@pytest_asyncio.fixture()
async def airq(session):
    return AirQ(IP, PASS, session, timeout=5)


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "address",
    [
        IP,
        pytest.param(
            HOSTNAME,
            marks=pytest.mark.skipif(
                not HOSTNAME, reason="AIRQ_HOSTNAME not specified"
            ),
        ),
    ],
)
@pytest.mark.parametrize("repeat_call", [False, True])
async def test_dns_caching_by_repeated_calls(address, repeat_call, session):
    """Test if a repeated .get request results in a timeout
    when DNS needs to be resolved / looked up from a cache.
    """
    airq = AirQ(address, PASS, session, timeout=5)

    await airq.get("ping")
    if repeat_call:
        await airq.get("ping")


@pytest.mark.asyncio
async def test_blink(airq):
    """Test the /blink endpoint and whether it returns the device ID."""
    device_id = await airq.blink()

    assert re.fullmatch("[0-9a-f]+", device_id) is not None


@pytest.mark.asyncio
async def test_device_name(airq):
    """Test getting and setting the device name."""
    previous_device_name = await airq.get_device_name()

    new_device_name = "just-testing"
    await airq.set_device_name(new_device_name)

    device_name_after_setting = await airq.get_device_name()

    await airq.set_device_name(previous_device_name)
    device_name_after_resetting = await airq.get_device_name()

    assert device_name_after_setting == new_device_name
    assert device_name_after_resetting == previous_device_name


@pytest.mark.asyncio
async def test_log(airq):
    """Test getting the log. It should be a list."""
    log = await airq.get_log()

    assert isinstance(log, list)


@pytest.mark.asyncio
async def test_config(airq):
    """Test getting the config. It should be a big dictionary."""
    config = await airq.get_config()

    keys_expected = {
        "HotspotChannel",
        "TimeServer",
        "cloudUpload",
        "id",
        "logging",
        "sensors",
    }
    keys_found = set(config.keys())

    assert isinstance(config, dict)
    assert len(config) > 40
    assert not keys_expected.difference(keys_found)


@pytest.mark.asyncio
async def test_possible_led_themes(airq):
    """Test getting the possible LED themes."""
    possible_led_themes = await airq.get_possible_led_themes()

    expected = {"standard", "VOC", "Humidity"}

    assert not expected.difference(possible_led_themes)


@pytest.mark.asyncio
async def test_get_led_theme(airq):
    """Test getting the current LED theme."""
    led_theme = await airq.get_led_theme()

    assert isinstance(led_theme["left"], str)
    assert isinstance(led_theme["right"], str)


@pytest_asyncio.fixture()
async def airq_automatically_restoring_led_theme(airq):
    # Setup
    previous_led_theme = await airq.get_led_theme()

    yield airq

    await airq.set_led_theme(previous_led_theme)
    led_theme_after_reset = await airq.get_led_theme()
    assert led_theme_after_reset == previous_led_theme


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "target_sides",
    [["left"], ["right"], ["left", "right"]],
)
async def test_setting_led_theme(airq_automatically_restoring_led_theme, target_sides):
    previous_led_theme: DeviceLedTheme = (
        await airq_automatically_restoring_led_theme.get_led_theme()
    )
    possible_led_themes = (
        await airq_automatically_restoring_led_theme.get_possible_led_themes()
    )
    unused_led_themes = set(possible_led_themes).difference(
        set(previous_led_theme.values())
    )
    target_theme = dict(zip(target_sides, unused_led_themes))
    await airq_automatically_restoring_led_theme.set_led_theme(
        DeviceLedThemePatch(**target_theme)
    )
    led_theme_after_setting = (
        await airq_automatically_restoring_led_theme.get_led_theme()
    )

    for side, theme in led_theme_after_setting.items():
        assert theme == target_theme.get(side, previous_led_theme[side])


@pytest.mark.asyncio
async def test_cloud_remote(airq):
    """Test setting and getting the "cloud remote" setting."""
    previous_value = await airq.get_cloud_remote()

    # on
    await airq.set_cloud_remote(True)
    value_after_on = await airq.get_cloud_remote()

    # off
    await airq.set_cloud_remote(False)
    value_after_off = await airq.get_cloud_remote()

    # reset
    await airq.set_cloud_remote(previous_value)
    value_after_reset = await airq.get_cloud_remote()

    assert value_after_on
    assert not value_after_off
    assert value_after_reset == previous_value


@pytest.mark.asyncio
async def test_time_server_exception(airq):
    """Test setting and getting the time server."""
    if await airq.has_api_access():
        pytest.skip("Test device has API access, not testing for its failure.")
    with pytest.raises(APIAccessDenied):
        await airq.set_time_server("127.0.0.1")


@pytest.mark.asyncio
async def test_time_server(airq):
    """Test setting and getting the time server."""
    if not (await airq.has_api_access()):
        pytest.skip("Cannot test time server setting without API access.")
    previous_value = await airq.get_time_server()

    await airq.set_time_server("127.0.0.1")
    value_after_change = await airq.get_time_server()

    await airq.set_time_server(previous_value)
    value_after_reset = await airq.get_time_server()

    assert value_after_change == "127.0.0.1"
    assert value_after_reset == previous_value


@pytest.mark.asyncio
async def test_night_mode(airq):
    """Test setting and getting the night mode settings."""
    previous_values = await airq.get_night_mode()

    new_values1 = NightMode(
        activated=True,
        start_day="03:47",
        start_night="19:12",
        brightness_day=19.7,
        brightness_night=2.3,
        fan_night_off=True,
        wifi_night_off=False,  # Hint: Don't disable Wi-Fi when testing ;-)
        alarm_night_off=True,
    )
    await airq.set_night_mode(new_values1)
    values_after_change1 = await airq.get_night_mode()

    new_values2 = NightMode(
        activated=False,
        start_day="00:00",
        start_night="23:59",
        brightness_day=17.0,
        brightness_night=4.7,
        fan_night_off=False,
        wifi_night_off=True,
        alarm_night_off=False,
    )
    await airq.set_night_mode(new_values2)
    values_after_change2 = await airq.get_night_mode()

    await airq.set_night_mode(previous_values)
    values_after_reset = await airq.get_night_mode()

    assert values_after_change1 == new_values1
    assert values_after_change2 == new_values2
    assert values_after_reset == previous_values