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
|
"""Tests for temperature validation error handling."""
# pylint: disable=protected-access
from typing import Any, cast
from unittest.mock import AsyncMock
import aiohttp
import pytest
from bsblan import BSBLAN
from bsblan.bsblan import BSBLANConfig
from bsblan.constants import API_VERSIONS, TEMPERATURE_RANGE_ERROR_MSG, APIConfig
from bsblan.exceptions import BSBLANError, BSBLANInvalidParameterError
from bsblan.utility import APIValidator
def test_validate_target_temperature_no_range() -> None:
"""Test validating target temperature with temperature range not initialized."""
config = BSBLANConfig(host="example.com")
bsblan = BSBLAN(config)
# Temperature range is not initialized by default
with pytest.raises(BSBLANError, match=TEMPERATURE_RANGE_ERROR_MSG):
bsblan._validate_target_temperature("22.0")
def test_validate_target_temperature_invalid_value() -> None:
"""Test validating target temperature with invalid (non-numeric) value."""
config = BSBLANConfig(host="example.com")
bsblan = BSBLAN(config)
# Initialize temperature range
bsblan._min_temp = 10.0
bsblan._max_temp = 30.0
# Test with non-numeric value
with pytest.raises(BSBLANInvalidParameterError):
bsblan._validate_target_temperature("invalid")
def test_validate_target_temperature_out_of_range() -> None:
"""Test validating target temperature with value outside allowed range."""
config = BSBLANConfig(host="example.com")
bsblan = BSBLAN(config)
# Initialize temperature range
bsblan._min_temp = 10.0
bsblan._max_temp = 30.0
# Test with value below minimum
with pytest.raises(BSBLANInvalidParameterError):
bsblan._validate_target_temperature("5.0")
# Test with value above maximum
with pytest.raises(BSBLANInvalidParameterError):
bsblan._validate_target_temperature("35.0")
def test_validate_target_temperature_valid() -> None:
"""Test validating target temperature with valid value."""
config = BSBLANConfig(host="example.com")
bsblan = BSBLAN(config)
# Initialize temperature range
bsblan._min_temp = 10.0
bsblan._max_temp = 30.0
# Test with valid value (should not raise exception)
bsblan._validate_target_temperature("22.0")
@pytest.mark.asyncio
async def test_temperature_range_min_temp_not_available(monkeypatch: Any) -> None:
"""Test warning when min_temp is not available from device (line 332)."""
async with aiohttp.ClientSession() as session:
config = BSBLANConfig(host="example.com")
client = BSBLAN(config, session=session)
client._api_version = "v1"
# Copy each section dictionary to avoid modifying the shared constant
source_config = API_VERSIONS["v1"]
client._api_data = cast(
"APIConfig",
{
section: cast("dict[str, str]", params).copy()
for section, params in source_config.items()
},
)
client._api_validator = APIValidator(client._api_data)
# Mock static_values to return data without min_temp
static_values_mock = AsyncMock()
static_values_mock.return_value.min_temp = None
static_values_mock.return_value.max_temp = AsyncMock()
static_values_mock.return_value.max_temp.value = "30"
monkeypatch.setattr(client, "static_values", static_values_mock)
# This should log a warning
await client._initialize_temperature_range()
# min_temp should remain None
assert client._min_temp is None
@pytest.mark.asyncio
async def test_temperature_range_max_temp_not_available(monkeypatch: Any) -> None:
"""Test warning when max_temp is not available from device (line 337)."""
async with aiohttp.ClientSession() as session:
config = BSBLANConfig(host="example.com")
client = BSBLAN(config, session=session)
client._api_version = "v1"
# Copy each section dictionary to avoid modifying the shared constant
source_config = API_VERSIONS["v1"]
client._api_data = cast(
"APIConfig",
{
section: cast("dict[str, str]", params).copy()
for section, params in source_config.items()
},
)
client._api_validator = APIValidator(client._api_data)
# Mock static_values to return data without max_temp
static_values_mock = AsyncMock()
static_values_mock.return_value.min_temp = AsyncMock()
static_values_mock.return_value.min_temp.value = "10"
static_values_mock.return_value.max_temp = None
monkeypatch.setattr(client, "static_values", static_values_mock)
# This should log a warning
await client._initialize_temperature_range()
# max_temp should remain None
assert client._max_temp is None
@pytest.mark.asyncio
async def test_temperature_range_static_values_error(monkeypatch: Any) -> None:
"""Test warning when static_values() raises an error (lines 332-337)."""
async with aiohttp.ClientSession() as session:
config = BSBLANConfig(host="example.com")
client = BSBLAN(config, session=session)
client._api_version = "v1"
# Copy each section dictionary to avoid modifying the shared constant
source_config = API_VERSIONS["v1"]
client._api_data = cast(
"APIConfig",
{
section: cast("dict[str, str]", params).copy()
for section, params in source_config.items()
},
)
client._api_validator = APIValidator(client._api_data)
# Mock static_values to raise an error
static_values_mock = AsyncMock(side_effect=BSBLANError("Test error"))
monkeypatch.setattr(client, "static_values", static_values_mock)
# This should log a warning and not raise
await client._initialize_temperature_range()
# Both should remain None
assert client._min_temp is None
assert client._max_temp is None
|