thinqconnect 0.9.0__py3-none-any.whl
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.
- tests/__init__.py +0 -0
- tests/conftest.py +195 -0
- tests/device_test_base.py +145 -0
- tests/test_air_conditioner.py +29 -0
- tests/test_air_purifier.py +23 -0
- tests/test_air_purifier_fan.py +32 -0
- tests/test_ceiling_fan.py +23 -0
- tests/test_cooktop.py +22 -0
- tests/test_dehumidifier.py +20 -0
- tests/test_dish_washer.py +19 -0
- tests/test_dryer.py +18 -0
- tests/test_home_brew.py +15 -0
- tests/test_hood.py +19 -0
- tests/test_humidifier.py +23 -0
- tests/test_kimchi_refrigerator.py +15 -0
- tests/test_microwave_oven.py +19 -0
- tests/test_mqtt_client.py +136 -0
- tests/test_oven.py +21 -0
- tests/test_plant_cultivator.py +15 -0
- tests/test_refrigerator.py +25 -0
- tests/test_robot_cleaner.py +19 -0
- tests/test_stick_cleaner.py +15 -0
- tests/test_styler.py +19 -0
- tests/test_system_boiler.py +25 -0
- tests/test_thinq_device_api.py +87 -0
- tests/test_washcomnbo_main.py +19 -0
- tests/test_washcomnbo_mini.py +19 -0
- tests/test_washer.py +19 -0
- tests/test_washtower.py +23 -0
- tests/test_washtower_dryer.py +15 -0
- tests/test_washtower_washer.py +20 -0
- tests/test_water_heater.py +22 -0
- tests/test_water_purifier.py +15 -0
- tests/test_wine_cellar.py +24 -0
- thinqconnect/__init__.py +74 -0
- thinqconnect/const.py +41 -0
- thinqconnect/country.py +358 -0
- thinqconnect/device.py +67 -0
- thinqconnect/devices/__init__.py +0 -0
- thinqconnect/devices/air_conditioner.py +207 -0
- thinqconnect/devices/air_purifier.py +99 -0
- thinqconnect/devices/air_purifier_fan.py +125 -0
- thinqconnect/devices/ceiling_fan.py +51 -0
- thinqconnect/devices/connect_device.py +484 -0
- thinqconnect/devices/cooktop.py +183 -0
- thinqconnect/devices/dehumidifier.py +53 -0
- thinqconnect/devices/dish_washer.py +79 -0
- thinqconnect/devices/dryer.py +72 -0
- thinqconnect/devices/home_brew.py +56 -0
- thinqconnect/devices/hood.py +86 -0
- thinqconnect/devices/humidifier.py +152 -0
- thinqconnect/devices/kimchi_refrigerator.py +140 -0
- thinqconnect/devices/microwave_oven.py +75 -0
- thinqconnect/devices/oven.py +248 -0
- thinqconnect/devices/plant_cultivator.py +121 -0
- thinqconnect/devices/refrigerator.py +207 -0
- thinqconnect/devices/robot_cleaner.py +75 -0
- thinqconnect/devices/stick_cleaner.py +52 -0
- thinqconnect/devices/styler.py +65 -0
- thinqconnect/devices/system_boiler.py +77 -0
- thinqconnect/devices/washcombo.py +60 -0
- thinqconnect/devices/washcombo_main.py +29 -0
- thinqconnect/devices/washcombo_mini.py +29 -0
- thinqconnect/devices/washer.py +172 -0
- thinqconnect/devices/washtower.py +114 -0
- thinqconnect/devices/washtower_dryer.py +36 -0
- thinqconnect/devices/washtower_washer.py +36 -0
- thinqconnect/devices/water_heater.py +59 -0
- thinqconnect/devices/water_purifier.py +45 -0
- thinqconnect/devices/wine_cellar.py +167 -0
- thinqconnect/mqtt_client.py +282 -0
- thinqconnect/thinq_api.py +327 -0
- thinqconnect-0.9.0.dist-info/LICENSE +201 -0
- thinqconnect-0.9.0.dist-info/METADATA +606 -0
- thinqconnect-0.9.0.dist-info/RECORD +77 -0
- thinqconnect-0.9.0.dist-info/WHEEL +5 -0
- thinqconnect-0.9.0.dist-info/top_level.txt +2 -0
tests/__init__.py
ADDED
|
File without changes
|
tests/conftest.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Callable
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from thinqconnect.const import DeviceType
|
|
11
|
+
from thinqconnect.devices.connect_device import ConnectBaseDevice
|
|
12
|
+
from thinqconnect.thinq_api import ThinQApi
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger("test")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def pytest_generate_tests(metafunc):
|
|
18
|
+
if "model_name" in metafunc.fixturenames:
|
|
19
|
+
device_type = metafunc.cls.get_device_type()
|
|
20
|
+
model_list = get_model_list(device_type)
|
|
21
|
+
metafunc.parametrize("model_name", model_list)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_model_list(device_type: str) -> list[str]:
|
|
25
|
+
base_path = Path.cwd() / "tests" / "devices" / device_type.split("DEVICE_")[1].lower()
|
|
26
|
+
return [d.name for d in base_path.iterdir() if d.is_dir()]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def generate_device() -> Callable[[type[ConnectBaseDevice], ThinQApi, dict, str, str, str | None], ConnectBaseDevice]:
|
|
31
|
+
def _device(
|
|
32
|
+
device_class: type[ConnectBaseDevice],
|
|
33
|
+
thinq_api: ThinQApi,
|
|
34
|
+
profile: dict,
|
|
35
|
+
device_type: str,
|
|
36
|
+
model_name: str,
|
|
37
|
+
reportable: bool = False,
|
|
38
|
+
group_id: str | None = None,
|
|
39
|
+
) -> ConnectBaseDevice:
|
|
40
|
+
if device_type in [
|
|
41
|
+
DeviceType.WASHCOMBO_MAIN,
|
|
42
|
+
DeviceType.WASHCOMBO_MINI,
|
|
43
|
+
DeviceType.WASHTOWER_DRYER,
|
|
44
|
+
DeviceType.WASHTOWER_WASHER,
|
|
45
|
+
]:
|
|
46
|
+
return device_class(
|
|
47
|
+
thinq_api=thinq_api,
|
|
48
|
+
device_id=profile["deviceId"],
|
|
49
|
+
device_type=device_type,
|
|
50
|
+
model_name=model_name,
|
|
51
|
+
alias=f"TEST_{device_type}",
|
|
52
|
+
reportable=reportable,
|
|
53
|
+
profile=profile["response"],
|
|
54
|
+
group_id=group_id,
|
|
55
|
+
)
|
|
56
|
+
else:
|
|
57
|
+
return device_class(
|
|
58
|
+
thinq_api=thinq_api,
|
|
59
|
+
device_id=profile["deviceId"],
|
|
60
|
+
device_type=device_type,
|
|
61
|
+
model_name=model_name,
|
|
62
|
+
alias=f"TEST_{device_type}",
|
|
63
|
+
reportable=reportable,
|
|
64
|
+
profile=profile["response"],
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return _device
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@pytest.fixture
|
|
71
|
+
def json_object() -> Callable[[str], dict]:
|
|
72
|
+
def _json_object(file_path: str):
|
|
73
|
+
return read_file(file_path)
|
|
74
|
+
|
|
75
|
+
return _json_object
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def read_file(file_path: str) -> dict:
|
|
79
|
+
default_dict = {}
|
|
80
|
+
try:
|
|
81
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
82
|
+
sample_set = f.read()
|
|
83
|
+
return json.loads(sample_set)
|
|
84
|
+
except Exception as e:
|
|
85
|
+
logger.error(f"read file error: {e}")
|
|
86
|
+
return default_dict
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@pytest.fixture
|
|
90
|
+
def test_device_profile() -> Callable[[str, ConnectBaseDevice], dict]:
|
|
91
|
+
def _device_profile(device_name: str, device: ConnectBaseDevice) -> dict:
|
|
92
|
+
profile_attr: dict[str, dict | list | None] = {
|
|
93
|
+
"properties": device.profiles.properties,
|
|
94
|
+
"writable_properties": device.profiles.writable_properties,
|
|
95
|
+
"location_properties": device.profiles.location_properties,
|
|
96
|
+
"notification": device.profiles.notification,
|
|
97
|
+
"errors": device.profiles.errors,
|
|
98
|
+
}
|
|
99
|
+
for key, value in profile_attr.items():
|
|
100
|
+
logger.info(f"test {device_name}.profiles.{key}: {value}")
|
|
101
|
+
|
|
102
|
+
test_result = dict.copy(profile_attr)
|
|
103
|
+
for properties in profile_attr["properties"].values():
|
|
104
|
+
for prop in properties:
|
|
105
|
+
test_result[prop] = device.profiles.get_property(prop)
|
|
106
|
+
logger.info(f"test {device_name}.profiles.{prop}: {test_result[prop]}")
|
|
107
|
+
|
|
108
|
+
for location, resources in profile_attr["location_properties"].items():
|
|
109
|
+
location_profiles = device.profiles.get_sub_profile(location)
|
|
110
|
+
sub_profile_attr: dict[str, dict | list | None] = {
|
|
111
|
+
"writable_properties": location_profiles.writable_properties,
|
|
112
|
+
**(
|
|
113
|
+
{"notification": location_profiles.notification, "errors": location_profiles.errors}
|
|
114
|
+
if location_profiles.notification or location_profiles.errors
|
|
115
|
+
else {}
|
|
116
|
+
),
|
|
117
|
+
}
|
|
118
|
+
for key, value in sub_profile_attr.items():
|
|
119
|
+
logger.info(f"test {device_name}.profiles.{location}.{key}: {value}")
|
|
120
|
+
|
|
121
|
+
test_result[location] = dict.copy(sub_profile_attr)
|
|
122
|
+
for properties in resources.values():
|
|
123
|
+
for prop in properties:
|
|
124
|
+
test_result[location][prop] = location_profiles.get_property(prop)
|
|
125
|
+
logger.info(f"test {device_name}.profiles.{location}.{prop}: {test_result[location][prop]}")
|
|
126
|
+
|
|
127
|
+
return test_result
|
|
128
|
+
|
|
129
|
+
return _device_profile
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@pytest.fixture
|
|
133
|
+
def test_device_status() -> Callable[[str, ConnectBaseDevice, dict, bool], dict]:
|
|
134
|
+
def _device_status(device_name: str, device: ConnectBaseDevice, status: dict, is_update: bool = False) -> dict:
|
|
135
|
+
device_properties = device.profiles.properties
|
|
136
|
+
location_properties = device.profiles.location_properties
|
|
137
|
+
if is_update:
|
|
138
|
+
device.update_status(status=status["response"])
|
|
139
|
+
else:
|
|
140
|
+
device.set_status(status=status["response"])
|
|
141
|
+
|
|
142
|
+
test_result = {}
|
|
143
|
+
if device.profiles.errors:
|
|
144
|
+
test_result["error"] = device.get_status("error")
|
|
145
|
+
logger.info(f"test {device_name}.error: {test_result['error']}")
|
|
146
|
+
|
|
147
|
+
for properties in device_properties.values():
|
|
148
|
+
for prop in properties:
|
|
149
|
+
test_result[prop] = device.get_status(prop)
|
|
150
|
+
logger.info(f"test {device_name}.{prop}: {test_result[prop]}")
|
|
151
|
+
|
|
152
|
+
for location, resources in location_properties.items():
|
|
153
|
+
sub_device = device.get_sub_device(location)
|
|
154
|
+
test_result[location] = {}
|
|
155
|
+
if device.profiles.get_sub_profile(location).errors:
|
|
156
|
+
test_result[location]["error"] = sub_device.get_status("error")
|
|
157
|
+
logger.info(f"test {device_name}.{location}.error: {test_result[location]['error']}")
|
|
158
|
+
|
|
159
|
+
for properties in resources.values():
|
|
160
|
+
for prop in properties:
|
|
161
|
+
test_result[location][prop] = sub_device.get_status(prop)
|
|
162
|
+
logger.info(f"test {device_name}.{location}.{prop}: {test_result[location][prop]}")
|
|
163
|
+
return test_result
|
|
164
|
+
|
|
165
|
+
return _device_status
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@pytest.fixture
|
|
169
|
+
def check_device_control() -> Callable[[str, ConnectBaseDevice], None]:
|
|
170
|
+
def _check_result(fn_name: str | None, prop_name: str) -> str:
|
|
171
|
+
if fn_name == f"set_{prop_name}":
|
|
172
|
+
return "Exist"
|
|
173
|
+
elif fn_name:
|
|
174
|
+
return f"Exist with custom name '{fn_name}'"
|
|
175
|
+
return "Not Exist"
|
|
176
|
+
|
|
177
|
+
def _check_control(device_name: str, device: ConnectBaseDevice):
|
|
178
|
+
location_properties = device.profiles.location_properties
|
|
179
|
+
writable_props = device.profiles.writable_properties
|
|
180
|
+
logger.info(f"test {device_name}.profiles.writable_properties: {device.profiles.writable_properties}")
|
|
181
|
+
for prop in writable_props:
|
|
182
|
+
logger.info(f"check {device_name}.set_{prop}: {_check_result(device.get_property_set_fn(prop), prop)}")
|
|
183
|
+
|
|
184
|
+
for location in location_properties.keys():
|
|
185
|
+
sub_device = device.get_sub_device(location)
|
|
186
|
+
writable_props = sub_device.profiles.writable_properties
|
|
187
|
+
logger.info(
|
|
188
|
+
f"test {device_name}.profiles.{location}.writable_properties: {sub_device.profiles.writable_properties}"
|
|
189
|
+
)
|
|
190
|
+
for prop in writable_props:
|
|
191
|
+
logger.info(
|
|
192
|
+
f"check {device_name}.{location}.set_{prop}: {_check_result(sub_device.get_property_set_fn(prop), prop)}"
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return _check_control
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
from glob import glob
|
|
6
|
+
from typing import Callable
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
from aiohttp import ClientSession
|
|
10
|
+
from deepdiff import DeepDiff
|
|
11
|
+
|
|
12
|
+
from thinqconnect.devices.connect_device import ConnectBaseDevice
|
|
13
|
+
from thinqconnect.thinq_api import ThinQApi
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger("test")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DeviceTestBase(abc.ABC):
|
|
19
|
+
@pytest.mark.asyncio
|
|
20
|
+
async def test_device(
|
|
21
|
+
self,
|
|
22
|
+
model_name: str,
|
|
23
|
+
generate_device: Callable[[type[ConnectBaseDevice], ThinQApi, dict, str, str, str | None], ConnectBaseDevice],
|
|
24
|
+
json_object: Callable[[str], dict],
|
|
25
|
+
test_device_profile: Callable[[str, ConnectBaseDevice], dict],
|
|
26
|
+
test_device_status: Callable[[str, ConnectBaseDevice, dict, bool], dict],
|
|
27
|
+
check_device_control: Callable[[str, ConnectBaseDevice], None],
|
|
28
|
+
):
|
|
29
|
+
async with ClientSession() as session:
|
|
30
|
+
access_token, client_id = self.get_credentials()
|
|
31
|
+
thinq_api = ThinQApi(
|
|
32
|
+
session=session,
|
|
33
|
+
access_token=access_token,
|
|
34
|
+
country_code="KR",
|
|
35
|
+
client_id=client_id,
|
|
36
|
+
)
|
|
37
|
+
device = generate_device(
|
|
38
|
+
self.get_device_class(),
|
|
39
|
+
thinq_api,
|
|
40
|
+
json_object(self.get_profile_file_path(self.get_device_type(), model_name)),
|
|
41
|
+
self.get_device_type(),
|
|
42
|
+
model_name,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
await self.run_device_test(
|
|
46
|
+
device,
|
|
47
|
+
json_object,
|
|
48
|
+
test_device_profile,
|
|
49
|
+
test_device_status,
|
|
50
|
+
check_device_control,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def get_credentials(cls) -> tuple[str, str]:
|
|
55
|
+
access_token = "ab3f3fa8443d91d48a2e331c6489ae0c1133acd441e539035ac1"
|
|
56
|
+
client_id = "test_client_id"
|
|
57
|
+
return (access_token, client_id)
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def get_device_type_path(cls, device_type: str) -> str:
|
|
61
|
+
short_device_type = cls.get_short_device_type(device_type)
|
|
62
|
+
return f"tests/devices/{short_device_type}/"
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def get_profile_file_path(cls, device_type: str, model_name: str) -> str:
|
|
66
|
+
return f"{cls.get_device_type_path(device_type)}{model_name}/profile.json"
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def get_result_file_path(cls, device_type: str, model_name: str) -> str:
|
|
70
|
+
return f"{cls.get_device_type_path(device_type)}result_{model_name}.json"
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def get_short_device_type(cls, device_type: str) -> str:
|
|
74
|
+
return device_type.split("DEVICE_")[1].lower()
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def write_test_result(cls, device_type: str, model_name: str, test_result: dict) -> str:
|
|
78
|
+
try:
|
|
79
|
+
file_path = cls.get_result_file_path(device_type, model_name)
|
|
80
|
+
if file_exist := os.path.exists(file_path):
|
|
81
|
+
with open(file_path) as file:
|
|
82
|
+
if file:
|
|
83
|
+
prev_result = json.load(file)
|
|
84
|
+
if not DeepDiff(prev_result, test_result, ignore_order=True):
|
|
85
|
+
logger.info("Test Result is not Changed.")
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
with open(file_path, "w") as file:
|
|
89
|
+
json.dump(test_result, file, indent=4)
|
|
90
|
+
|
|
91
|
+
except Exception as e:
|
|
92
|
+
logger.info(f"An error occurred: {e}")
|
|
93
|
+
|
|
94
|
+
if not file_exist:
|
|
95
|
+
logger.info(f"Test Result is Created to {file_path}")
|
|
96
|
+
else:
|
|
97
|
+
logger.info(f"Test Result is Updated to {file_path}")
|
|
98
|
+
assert False
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
async def run_device_test(
|
|
102
|
+
cls,
|
|
103
|
+
device: ConnectBaseDevice,
|
|
104
|
+
json_object: Callable[[str], dict],
|
|
105
|
+
test_device_profile: Callable[[str, ConnectBaseDevice], dict],
|
|
106
|
+
test_device_status: Callable[[str, ConnectBaseDevice, dict, bool], dict],
|
|
107
|
+
check_device_control: Callable[[str, ConnectBaseDevice], None],
|
|
108
|
+
):
|
|
109
|
+
device_type = device.device_type
|
|
110
|
+
short_device_type = cls.get_short_device_type(device_type)
|
|
111
|
+
model_name = device.model_name
|
|
112
|
+
test_result = {"profile": None, "status": {}, "event": {}}
|
|
113
|
+
|
|
114
|
+
logger.info(f"{device_type} Test with model : {model_name}")
|
|
115
|
+
|
|
116
|
+
test_result["profile"] = test_device_profile(device_type, device)
|
|
117
|
+
|
|
118
|
+
status_files = glob(f"tests/devices/{short_device_type}/{model_name}/status/*.json")
|
|
119
|
+
for status_file in status_files:
|
|
120
|
+
status = json_object(status_file)
|
|
121
|
+
test_result["status"][status_file.split("/")[-1]] = test_device_status(device_type, device, status)
|
|
122
|
+
|
|
123
|
+
event_files = glob(f"tests/devices/{short_device_type}/{model_name}/event/*.json")
|
|
124
|
+
|
|
125
|
+
for event_file in sorted(event_files):
|
|
126
|
+
print(event_file.split("/")[-1])
|
|
127
|
+
event = json_object(event_file)
|
|
128
|
+
test_result["event"][event_file.split("/")[-1]] = test_device_status(
|
|
129
|
+
device_type, device, event, is_update=True
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
check_device_control(device_type, device)
|
|
133
|
+
|
|
134
|
+
logger.info(f"{device_type} Test with model : {model_name} is done.")
|
|
135
|
+
cls.write_test_result(device_type, model_name, test_result)
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
@abc.abstractmethod
|
|
139
|
+
def get_device_class(cls) -> type[ConnectBaseDevice]:
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
@classmethod
|
|
143
|
+
@abc.abstractmethod
|
|
144
|
+
def get_device_type(cls) -> str:
|
|
145
|
+
pass
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.air_conditioner import AirConditionerDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestAirConditioner(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[AirConditionerDevice]:
|
|
11
|
+
return AirConditionerDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.AIR_CONDITIONER
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: AirConditionerDevice):
|
|
18
|
+
await device.set_current_job_mode("COOL")
|
|
19
|
+
await device.set_air_con_operation_mode("POWER_ON")
|
|
20
|
+
await device.set_air_con_operation_mode("POWER_OFF")
|
|
21
|
+
await device.set_current_job_mode("AIR_DRY")
|
|
22
|
+
await device.set_air_clean_operation_mode("START")
|
|
23
|
+
await device.set_monitoring_enabled("ON_WORKING")
|
|
24
|
+
await device.set_wind_strength("MID")
|
|
25
|
+
await device.set_relative_time_to_stop(1, 10)
|
|
26
|
+
await device.set_sleep_timer_relative_time_to_stop(1, 10)
|
|
27
|
+
await device.set_target_temperature(20)
|
|
28
|
+
await device.set_cool_target_temperature(24)
|
|
29
|
+
await device.set_power_save_enabled(False)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.air_purifier import AirPurifierDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestAirPurifier(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[AirPurifierDevice]:
|
|
11
|
+
return AirPurifierDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.AIR_PURIFIER
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: AirPurifierDevice):
|
|
18
|
+
# NOTE: AIR_910604_WW 제어 테스트이고, 시뮬레이터 기기로 테스트 시 전원 켠 후 Mode를 Single로 변경하고 Speed를 Turbo로 변경 필요
|
|
19
|
+
await device.set_wind_strength("LOW")
|
|
20
|
+
await device.set_absolute_time_to_stop(13, 30)
|
|
21
|
+
await device.set_air_purifier_operation_mode("POWER_OFF")
|
|
22
|
+
await device.set_absolute_time_to_start(12, 30)
|
|
23
|
+
await device.set_air_purifier_operation_mode("POWER_ON")
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.air_purifier_fan import AirPurifierFanDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestAirPurifierFan(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[AirPurifierFanDevice]:
|
|
11
|
+
return AirPurifierFanDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.AIR_PURIFIER_FAN
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: AirPurifierFanDevice):
|
|
18
|
+
# NOTE: 밀웜 동작 확인 불가
|
|
19
|
+
# await device.set_current_job_mode("DIRECT_CLEAN")
|
|
20
|
+
# await device.set_relative_time_to_stop(5)
|
|
21
|
+
# await device.set_wind_angle("ANGLE_45")
|
|
22
|
+
# await device.set_warm_mode("WARM_ON")
|
|
23
|
+
# await device.set_wind_temperature(35)
|
|
24
|
+
|
|
25
|
+
# NOTE: 밀웜 테스트 완료
|
|
26
|
+
await device.set_air_fan_operation_mode("POWER_ON")
|
|
27
|
+
await device.set_absolute_time_to_stop(13, 30)
|
|
28
|
+
await device.set_display_light("LEVEL_2")
|
|
29
|
+
await device.set_wind_strength("AUTO")
|
|
30
|
+
await device.set_uv_nano("ON")
|
|
31
|
+
await device.set_air_fan_operation_mode("POWER_OFF")
|
|
32
|
+
await device.set_absolute_time_to_start(12, 30)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.ceiling_fan import CeilingFanDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestCeilingFan(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[CeilingFanDevice]:
|
|
11
|
+
return CeilingFanDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.CEILING_FAN
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: CeilingFanDevice):
|
|
18
|
+
await device.set_ceiling_fan_operation_mode("POWER_ON")
|
|
19
|
+
await device.set_ceiling_fan_operation_mode("POWER_OFF")
|
|
20
|
+
await device.set_wind_strength("TURBO")
|
|
21
|
+
await device.set_wind_strength("HIGH")
|
|
22
|
+
await device.set_wind_strength("LOW")
|
|
23
|
+
await device.set_wind_strength("MID")
|
tests/test_cooktop.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.cooktop import CooktopDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestCooktop(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[CooktopDevice]:
|
|
11
|
+
return CooktopDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.COOKTOP
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: CooktopDevice):
|
|
18
|
+
await device.set_operation_mode("POWER_OFF")
|
|
19
|
+
await device.set_power_level("left_rear", 1)
|
|
20
|
+
# await device.set_power_level("left_rear", 15) # negative
|
|
21
|
+
await device.set_remain_hour("right_front", 1)
|
|
22
|
+
await device.set_remain_minute("left_rear", 5)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.dehumidifier import DehumidifierDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestDehumidifier(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[DehumidifierDevice]:
|
|
11
|
+
return DehumidifierDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.DEHUMIDIFIER
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: DehumidifierDevice):
|
|
18
|
+
await device.set_dehumidifier_operation_mode("POWER_ON")
|
|
19
|
+
await device.set_wind_strength("LOW")
|
|
20
|
+
await device.set_dehumidifier_operation_mode("POWER_OFF")
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.dish_washer import DishWasherDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestDishWasher(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[DishWasherDevice]:
|
|
11
|
+
return DishWasherDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.DISH_WASHER
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: DishWasherDevice):
|
|
18
|
+
await device.set_dish_washer_operation_mode("START")
|
|
19
|
+
await device.set_relative_hour_to_start(1)
|
tests/test_dryer.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.dryer import DryerDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestDryer(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[DryerDevice]:
|
|
11
|
+
return DryerDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.DRYER
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: DryerDevice):
|
|
18
|
+
await device.set_dryer_operation_mode("POWER_OFF")
|
tests/test_home_brew.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.home_brew import HomeBrewDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestHomeBrew(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[HomeBrewDevice]:
|
|
11
|
+
return HomeBrewDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.HOME_BREW
|
tests/test_hood.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.hood import HoodDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestHood(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[HoodDevice]:
|
|
11
|
+
return HoodDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.HOOD
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: HoodDevice):
|
|
18
|
+
await device.set_fan_speed(2)
|
|
19
|
+
await device.set_lamp_brightness(1)
|
tests/test_humidifier.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.humidifier import HumidifierDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestHumidifier(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[HumidifierDevice]:
|
|
11
|
+
return HumidifierDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.HUMIDIFIER
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: HumidifierDevice):
|
|
18
|
+
# NOTE: 실기기 테스트 필요
|
|
19
|
+
await device.set_current_job_mode("AIR_CLEAN")
|
|
20
|
+
await device.set_humidifier_operation_mode("POWER_OFF")
|
|
21
|
+
await device.set_humidifier_operation_mode("POWER_ON")
|
|
22
|
+
await device.set_sleep_mode("SLEEP_OFF")
|
|
23
|
+
await device.set_sleep_mode("SLEEP_ON")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.kimchi_refrigerator import KimchiRefrigeratorDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestKimchiRefrigerator(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[KimchiRefrigeratorDevice]:
|
|
11
|
+
return KimchiRefrigeratorDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.KIMCHI_REFRIGERATOR
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tests.device_test_base import DeviceTestBase
|
|
4
|
+
from thinqconnect.const import DeviceType
|
|
5
|
+
from thinqconnect.devices.microwave_oven import MicrowaveOvenDevice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestMicrowaveOven(DeviceTestBase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def get_device_class(cls) -> type[MicrowaveOvenDevice]:
|
|
11
|
+
return MicrowaveOvenDevice
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def get_device_type(cls) -> str:
|
|
15
|
+
return DeviceType.MICROWAVE_OVEN
|
|
16
|
+
|
|
17
|
+
async def check_control(self, device: MicrowaveOvenDevice):
|
|
18
|
+
await device.set_fan_speed(2)
|
|
19
|
+
await device.set_lamp_brightness(1)
|