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
|
"""Tests for C4Director — get_item_variable_value, get_all_item_variable_value,
and basic request wrappers.
"""
import json
from unittest.mock import AsyncMock, patch
import pytest
@pytest.mark.asyncio
async def test_get_item_variable_value_int(director):
"""Normal integer value is returned as-is."""
response = json.dumps([{"id": 100, "varName": "LIGHT_LEVEL", "value": 75}])
with patch.object(
director, "send_get_request", new=AsyncMock(return_value=response)
):
result = await director.get_item_variable_value(100, "LIGHT_LEVEL")
assert result == 75
@pytest.mark.asyncio
async def test_get_item_variable_value_zero(director):
"""Zero is returned as 0, not confused with None or falsy."""
response = json.dumps([{"id": 100, "varName": "LIGHT_LEVEL", "value": 0}])
with patch.object(
director, "send_get_request", new=AsyncMock(return_value=response)
):
result = await director.get_item_variable_value(100, "LIGHT_LEVEL")
assert result == 0
assert result is not None
@pytest.mark.asyncio
async def test_get_item_variable_value_bool(director):
"""Boolean value is returned as a Python bool."""
response = json.dumps([{"id": 100, "varName": "IS_ON", "value": True}])
with patch.object(
director, "send_get_request", new=AsyncMock(return_value=response)
):
result = await director.get_item_variable_value(100, "IS_ON")
assert result is True
@pytest.mark.asyncio
async def test_get_item_variable_value_string(director):
"""String value is returned as-is."""
response = json.dumps(
[{"id": 100, "varName": "PARTITION_STATE", "value": "ARMED_AWAY"}]
)
with patch.object(
director, "send_get_request", new=AsyncMock(return_value=response)
):
result = await director.get_item_variable_value(100, "PARTITION_STATE")
assert result == "ARMED_AWAY"
@pytest.mark.asyncio
async def test_get_item_variable_value_null(director):
"""JSON null value passes through as None (distinct from 'Undefined')."""
response = json.dumps([{"id": 100, "varName": "OPTIONAL_VAR", "value": None}])
with patch.object(
director, "send_get_request", new=AsyncMock(return_value=response)
):
result = await director.get_item_variable_value(100, "OPTIONAL_VAR")
assert result is None
@pytest.mark.asyncio
async def test_get_item_variable_value_empty_response(director):
"""Empty list response raises ValueError."""
with patch.object(director, "send_get_request", new=AsyncMock(return_value="[]")):
with pytest.raises(ValueError):
await director.get_item_variable_value(100, "NONEXISTENT")
@pytest.mark.asyncio
async def test_get_item_variable_value_invalid_format(director):
"""Non-list JSON response raises ValueError (2.0 guard)."""
with patch.object(
director, "send_get_request", new=AsyncMock(return_value='{"value": 1}')
):
with pytest.raises(ValueError):
await director.get_item_variable_value(100, "TEST")
@pytest.mark.asyncio
async def test_get_item_variable_value_list_var_name(director):
"""List of var_names is joined with comma in the request URI."""
response = json.dumps([{"id": 100, "varName": "A", "value": 1}])
mock = AsyncMock(return_value=response)
with patch.object(director, "send_get_request", new=mock):
await director.get_item_variable_value(100, ["A", "B"])
uri = mock.call_args[0][0]
assert "varnames=A,B" in uri
@pytest.mark.asyncio
async def test_get_item_variable_value_tuple_var_name(director):
"""Tuple of var_names is joined with comma in the request URI."""
response = json.dumps([{"id": 100, "varName": "X", "value": 42}])
mock = AsyncMock(return_value=response)
with patch.object(director, "send_get_request", new=mock):
await director.get_item_variable_value(100, ("X", "Y"))
uri = mock.call_args[0][0]
assert "varnames=X,Y" in uri
@pytest.mark.asyncio
async def test_get_all_item_variable_value_mixed(director):
"""get_all_item_variable_value normalizes Undefined values in-place."""
response = json.dumps(
[
{"id": 1, "varName": "HUMIDITY", "value": "Undefined"},
{"id": 2, "varName": "HUMIDITY", "value": 45},
{"id": 3, "varName": "HUMIDITY", "value": 0},
]
)
with patch.object(
director, "send_get_request", new=AsyncMock(return_value=response)
):
result = await director.get_all_item_variable_value("HUMIDITY")
assert result[0]["value"] is None
assert result[1]["value"] == 45
assert result[2]["value"] == 0
@pytest.mark.asyncio
async def test_get_all_item_variable_value_empty(director):
"""Empty list response raises ValueError."""
with patch.object(director, "send_get_request", new=AsyncMock(return_value="[]")):
with pytest.raises(ValueError):
await director.get_all_item_variable_value("NONEXISTENT")
@pytest.mark.asyncio
async def test_get_all_item_info_returns_parsed(director):
"""get_all_item_info returns parsed list (2.0 returns parsed JSON)."""
raw = '[{"id": 1, "name": "Light"}]'
with patch.object(director, "send_get_request", new=AsyncMock(return_value=raw)):
result = await director.get_all_item_info()
assert isinstance(result, list)
assert result[0]["id"] == 1
|