core/tests/components/tuya/conftest.py

199 lines
6.1 KiB
Python

"""Fixtures for the Tuya integration tests."""
from __future__ import annotations
from collections.abc import Generator
from unittest.mock import MagicMock, patch
import pytest
from tuya_sharing import CustomerApi, CustomerDevice, DeviceFunction, DeviceStatusRange
from homeassistant.components.tuya import ManagerCompat
from homeassistant.components.tuya.const import (
CONF_APP_TYPE,
CONF_ENDPOINT,
CONF_TERMINAL_ID,
CONF_TOKEN_INFO,
CONF_USER_CODE,
DOMAIN,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.json import json_dumps
from homeassistant.util import dt as dt_util
from . import MockDeviceListener
from tests.common import MockConfigEntry, async_load_json_object_fixture
@pytest.fixture
def mock_old_config_entry() -> MockConfigEntry:
"""Mock an old config entry that can be migrated."""
return MockConfigEntry(
title="Old Tuya configuration entry",
domain=DOMAIN,
data={CONF_APP_TYPE: "tuyaSmart"},
unique_id="12345",
)
@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
"""Mock a config entry."""
return MockConfigEntry(
title="Test Tuya entry",
domain=DOMAIN,
data={
CONF_ENDPOINT: "test_endpoint",
CONF_TERMINAL_ID: "test_terminal",
CONF_TOKEN_INFO: "test_token",
CONF_USER_CODE: "test_user_code",
},
unique_id="12345",
)
@pytest.fixture
async def mock_loaded_entry(
hass: HomeAssistant,
mock_manager: ManagerCompat,
mock_config_entry: MockConfigEntry,
mock_device: CustomerDevice,
) -> MockConfigEntry:
"""Mock a config entry."""
# Setup
mock_manager.device_map = {
mock_device.id: mock_device,
}
mock_config_entry.add_to_hass(hass)
# Initialize the component
with (
patch("homeassistant.components.tuya.ManagerCompat", return_value=mock_manager),
):
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
return mock_config_entry
@pytest.fixture
def mock_setup_entry() -> Generator[None]:
"""Mock setting up a config entry."""
with patch("homeassistant.components.tuya.async_setup_entry", return_value=True):
yield
@pytest.fixture
def mock_tuya_login_control() -> Generator[MagicMock]:
"""Return a mocked Tuya login control."""
with patch(
"homeassistant.components.tuya.config_flow.LoginControl", autospec=True
) as login_control_mock:
login_control = login_control_mock.return_value
login_control.qr_code.return_value = {
"success": True,
"result": {
"qrcode": "mocked_qr_code",
},
}
login_control.login_result.return_value = (
True,
{
"t": "mocked_t",
"uid": "mocked_uid",
"username": "mocked_username",
"expire_time": "mocked_expire_time",
"access_token": "mocked_access_token",
"refresh_token": "mocked_refresh_token",
"terminal_id": "mocked_terminal_id",
"endpoint": "mocked_endpoint",
},
)
yield login_control
@pytest.fixture
def mock_manager() -> ManagerCompat:
"""Mock Tuya Manager."""
manager = MagicMock(spec=ManagerCompat)
manager.device_map = {}
manager.mq = MagicMock()
manager.mq.client = MagicMock()
manager.mq.client.is_connected = MagicMock(return_value=True)
manager.customer_api = MagicMock(spec=CustomerApi)
# Meaningless URL / UUIDs
manager.customer_api.endpoint = "https://apigw.tuyaeu.com"
manager.terminal_id = "7cd96aff-6ec8-4006-b093-3dbff7947591"
return manager
@pytest.fixture
def mock_device_code() -> str:
"""Fixture to parametrize the type of the mock device.
To set a configuration, tests can be marked with:
@pytest.mark.parametrize("mock_device_code", ["device_code_1", "device_code_2"])
"""
return None
@pytest.fixture
async def mock_device(hass: HomeAssistant, mock_device_code: str) -> CustomerDevice:
"""Mock a Tuya CustomerDevice."""
details = await async_load_json_object_fixture(
hass, f"{mock_device_code}.json", DOMAIN
)
device = MagicMock(spec=CustomerDevice)
device.id = details.get("id", "mocked_device_id")
device.name = details["name"]
device.category = details["category"]
device.product_id = details["product_id"]
device.product_name = details["product_name"]
device.online = details["online"]
device.sub = details.get("sub")
device.time_zone = details.get("time_zone")
device.active_time = details.get("active_time")
if device.active_time:
device.active_time = int(dt_util.as_timestamp(device.active_time))
device.create_time = details.get("create_time")
if device.create_time:
device.create_time = int(dt_util.as_timestamp(device.create_time))
device.update_time = details.get("update_time")
if device.update_time:
device.update_time = int(dt_util.as_timestamp(device.update_time))
device.support_local = details.get("support_local")
device.mqtt_connected = details.get("mqtt_connected")
device.function = {
key: DeviceFunction(
code=value.get("code"),
type=value["type"],
values=json_dumps(value["value"]),
)
for key, value in details["function"].items()
}
device.status_range = {
key: DeviceStatusRange(
code=value.get("code"),
type=value["type"],
values=json_dumps(value["value"]),
)
for key, value in details["status_range"].items()
}
device.status = details["status"]
for key, value in device.status.items():
if device.status_range[key].type == "Json":
device.status[key] = json_dumps(value)
return device
@pytest.fixture
def mock_listener(
hass: HomeAssistant, mock_manager: ManagerCompat
) -> MockDeviceListener:
"""Create a DeviceListener for testing."""
listener = MockDeviceListener(hass, mock_manager)
mock_manager.add_device_listener(listener)
return listener