File: test_version_errors.py

package info (click to toggle)
python-bsblan 2.2.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 784 kB
  • sloc: python: 2,890; makefile: 3
file content (204 lines) | stat: -rw-r--r-- 6,409 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
"""Tests for API version and firmware version error handling."""
# pylint: disable=protected-access

from unittest.mock import AsyncMock, patch

import pytest

from bsblan import BSBLAN
from bsblan.bsblan import BSBLANConfig
from bsblan.constants import API_VERSION_ERROR_MSG, FIRMWARE_VERSION_ERROR_MSG
from bsblan.exceptions import BSBLANError, BSBLANVersionError
from bsblan.models import Device


@pytest.mark.asyncio
async def test_set_api_version_without_firmware() -> None:
    """Test setting API version with firmware version not set."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Firmware version is None by default
    with pytest.raises(BSBLANError, match=FIRMWARE_VERSION_ERROR_MSG):
        bsblan._set_api_version()


@pytest.mark.asyncio
async def test_set_api_version_unsupported() -> None:
    """Test setting API version with unsupported firmware version."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Set firmware version to an unsupported value (between 1.2.0 and 3.0.0)
    bsblan._firmware_version = "2.0.0"

    with pytest.raises(BSBLANVersionError):
        bsblan._set_api_version()


@pytest.mark.asyncio
async def test_set_api_version_v1() -> None:
    """Test setting API version with v1 compatible firmware."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Set firmware version to v1 compatible
    bsblan._firmware_version = "1.0.0"
    bsblan._set_api_version()

    assert bsblan._api_version == "v1"


@pytest.mark.asyncio
async def test_set_api_version_v3() -> None:
    """Test setting API version with v3 compatible firmware."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Set firmware version to v3 compatible
    bsblan._firmware_version = "3.0.0"
    bsblan._set_api_version()

    assert bsblan._api_version == "v3"


@pytest.mark.asyncio
async def test_fetch_firmware_version() -> None:
    """Test fetching firmware version from device."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Create mock device with test version
    device = Device(
        name="Test Device", version="3.1.0", MAC="00:11:22:33:44:55", uptime=1000
    )

    # Mock device method to return our test device
    with (
        patch.object(bsblan, "device", AsyncMock(return_value=device)),
        patch.object(bsblan, "_set_api_version"),
    ):
        await bsblan._fetch_firmware_version()

        # Verify firmware version was set
        assert bsblan._firmware_version == "3.1.0"


@pytest.mark.asyncio
async def test_initialize_api_validator_no_api_version() -> None:
    """Test initialize API validator with no API version set."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # API version is None by default
    with pytest.raises(BSBLANError, match=API_VERSION_ERROR_MSG):
        await bsblan._initialize_api_validator()


@pytest.mark.asyncio
async def test_set_api_version_v5() -> None:
    """Test setting API version with v5 compatible firmware (BSB-LAN 5.x)."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Set firmware version to 5.0.16 (current BSB-LAN version)
    bsblan._firmware_version = "5.0.16"
    bsblan._set_api_version()

    assert bsblan._api_version == "v3"  # BSB-LAN 5.x uses v3 API with extensions


@pytest.mark.asyncio
async def test_set_api_version_v5_early() -> None:
    """Test setting API version with early v5 compatible firmware."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Set firmware version to 5.0.0 (first 5.x version)
    bsblan._firmware_version = "5.0.0"
    bsblan._set_api_version()

    assert bsblan._api_version == "v3"  # BSB-LAN 5.x uses v3 API with extensions


@pytest.mark.asyncio
async def test_process_response_v5_payload_removal() -> None:
    """Test that BSB-LAN 5.x payload field is removed from responses."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Set firmware version to 5.0.16
    bsblan._firmware_version = "5.0.16"

    # Mock response with payload field (as added in BSB-LAN 5.0+)
    response_with_payload = {
        "8700": {"value": "20.5", "unit": "°C"},
        "8740": {"value": "21.0", "unit": "°C"},
        "payload": "debug_payload_data_here",
    }

    # Process the response
    processed = bsblan._process_response(response_with_payload, "/JQ")

    # Payload should be removed
    expected = {
        "8700": {"value": "20.5", "unit": "°C"},
        "8740": {"value": "21.0", "unit": "°C"},
    }

    assert processed == expected
    assert "payload" not in processed


@pytest.mark.asyncio
async def test_process_response_non_jq_endpoint() -> None:
    """Test that non-JQ endpoints are not processed for payload removal."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Set firmware version to 5.0.16
    bsblan._firmware_version = "5.0.16"

    # Mock response with payload field
    response_with_payload = {
        "name": "BSB-LAN",
        "version": "5.0.16",
        "payload": "should_remain_for_non_jq",
    }

    # Process the response for non-JQ endpoint
    processed = bsblan._process_response(response_with_payload, "/JI")

    # Payload should remain for non-JQ endpoints
    assert processed == response_with_payload
    assert "payload" in processed


@pytest.mark.asyncio
async def test_set_api_version_v5_edge_cases() -> None:
    """Test edge cases for BSB-LAN 5.x version detection."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Test version 4.9.9 (should still be v3, not v5)
    bsblan._firmware_version = "4.9.9"
    bsblan._set_api_version()
    assert bsblan._api_version == "v3"

    # Test version 5.0.0-beta (should be v3)
    bsblan._firmware_version = "5.0.0"
    bsblan._set_api_version()
    assert bsblan._api_version == "v3"


@pytest.mark.asyncio
async def test_unsupported_version_still_fails() -> None:
    """Test that unsupported versions between 1.2.0 and 3.0.0 still fail."""
    config = BSBLANConfig(host="example.com")
    bsblan = BSBLAN(config)

    # Test that version 2.0.0 still fails (gap between v1 and v3)
    bsblan._firmware_version = "2.0.0"

    with pytest.raises(BSBLANVersionError):
        bsblan._set_api_version()