Skip to content

Commit b033876

Browse files
authored
chore(tests): add additional tests (#487)
1 parent 4430504 commit b033876

File tree

3 files changed

+412
-1
lines changed

3 files changed

+412
-1
lines changed

tests/test_main.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import json
55
import logging
66
from unittest import mock
7+
from unittest.mock import AsyncMock, MagicMock, patch
78

89
import aiohttp
910
import pytest
@@ -12,18 +13,19 @@
1213
from awesomeversion.exceptions import AwesomeVersionCompareException
1314

1415
import openevsehttp.__main__ as main
16+
from openevsehttp.__main__ import OpenEVSE
1517
from openevsehttp.exceptions import (
1618
InvalidType,
1719
MissingSerial,
1820
UnknownError,
1921
UnsupportedFeature,
2022
)
21-
from tests.common import load_fixture
2223
from openevsehttp.websocket import (
2324
SIGNAL_CONNECTION_STATE,
2425
STATE_CONNECTED,
2526
STATE_DISCONNECTED,
2627
)
28+
from tests.common import load_fixture
2729

2830
pytestmark = pytest.mark.asyncio
2931

@@ -43,6 +45,7 @@
4345
TEST_URL_GITHUB_v2 = (
4446
"https://api.github.com/repos/OpenEVSE/ESP8266_WiFi_v2.x/releases/latest"
4547
)
48+
SERVER_URL = "openevse.test.tld"
4649

4750

4851
async def test_get_status_auth(test_charger_auth):
@@ -2209,3 +2212,69 @@ async def test_set_divert_mode(
22092212
with caplog.at_level(logging.DEBUG):
22102213
await test_charger_new.set_divert_mode("fast")
22112214
assert "Problem issuing command: error" in caplog.text
2215+
2216+
2217+
async def test_main_auth_instantiation():
2218+
"""Test OpenEVSE auth instantiation (covers __main__.py:111-113)."""
2219+
charger = OpenEVSE(SERVER_URL, user="user", pwd="password")
2220+
2221+
# Setup mock session to be an async context manager
2222+
mock_session = MagicMock()
2223+
mock_session.__aenter__ = AsyncMock(return_value=mock_session)
2224+
mock_session.__aexit__ = AsyncMock(return_value=None)
2225+
2226+
# Setup mock response context to be an async context manager
2227+
mock_resp = AsyncMock()
2228+
mock_resp.status = 200
2229+
mock_resp.text.return_value = "{}"
2230+
2231+
mock_request_ctx = MagicMock()
2232+
mock_request_ctx.__aenter__ = AsyncMock(return_value=mock_resp)
2233+
mock_request_ctx.__aexit__ = AsyncMock(return_value=None)
2234+
2235+
# Ensure session.get() returns the request context
2236+
mock_session.get.return_value = mock_request_ctx
2237+
2238+
with patch("aiohttp.ClientSession", return_value=mock_session), patch(
2239+
"aiohttp.BasicAuth"
2240+
) as mock_basic_auth:
2241+
2242+
await charger.update()
2243+
2244+
# Verify BasicAuth was instantiated
2245+
# Note: process_request is called multiple times in update(), so we check if called at least once
2246+
mock_basic_auth.assert_called_with("user", "password")
2247+
2248+
2249+
async def test_main_sync_callback():
2250+
"""Test synchronous callback in _update_status (covers __main__.py:293)."""
2251+
charger = OpenEVSE(SERVER_URL)
2252+
sync_callback = MagicMock()
2253+
charger.callback = sync_callback
2254+
2255+
# Manually trigger update status
2256+
await charger._update_status("data", {"key": "value"}, None)
2257+
2258+
sync_callback.assert_called_once()
2259+
2260+
2261+
async def test_send_command_msg_fallback():
2262+
"""Test send_command return logic fallback (covers __main__.py:181)."""
2263+
charger = OpenEVSE(SERVER_URL)
2264+
2265+
# Mock response with 'msg' but no 'ret'
2266+
with patch.object(charger, "process_request", return_value={"msg": "ErrorMsg"}):
2267+
cmd, ret = await charger.send_command("$ST")
2268+
assert cmd is False
2269+
assert ret == "ErrorMsg"
2270+
2271+
2272+
async def test_send_command_empty_fallback():
2273+
"""Test send_command empty fallback."""
2274+
charger = OpenEVSE(SERVER_URL)
2275+
2276+
# Mock response with neither 'msg' nor 'ret'
2277+
with patch.object(charger, "process_request", return_value={}):
2278+
cmd, ret = await charger.send_command("$ST")
2279+
assert cmd is False
2280+
assert ret == ""

tests/test_main_edge_cases.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""Edge case tests for OpenEVSE main library."""
2+
3+
import logging
4+
from unittest.mock import AsyncMock, MagicMock, patch
5+
6+
import pytest
7+
8+
from openevsehttp.__main__ import OpenEVSE
9+
10+
pytestmark = pytest.mark.asyncio
11+
12+
SERVER_URL = "openevse.test.tld"
13+
14+
15+
@pytest.fixture
16+
def charger():
17+
return OpenEVSE(SERVER_URL)
18+
19+
20+
async def test_process_request_decode_error(charger, caplog):
21+
"""Test handling of UnicodeDecodeError in process_request."""
22+
mock_resp = MagicMock()
23+
24+
# .text() needs to be an async mock that raises the error
25+
mock_resp.text = AsyncMock(
26+
side_effect=UnicodeDecodeError("utf-8", b"", 0, 1, "err")
27+
)
28+
29+
# .read() needs to be an async mock that returns the bytes
30+
mock_resp.read = AsyncMock(return_value=b'{"msg": "decoded"}')
31+
32+
mock_resp.status = 200
33+
mock_resp.__aenter__.return_value = mock_resp
34+
mock_resp.__aexit__.return_value = None
35+
36+
with patch("aiohttp.ClientSession.get", return_value=mock_resp), caplog.at_level(
37+
logging.DEBUG
38+
):
39+
data = await charger.process_request("http://url", method="get")
40+
41+
assert data == {"msg": "decoded"}
42+
assert "Decoding error" in caplog.text
43+
44+
45+
async def test_process_request_http_warnings(charger, caplog):
46+
"""Test logging of specific HTTP error codes."""
47+
mock_resp = MagicMock()
48+
49+
# .text() needs to be an async mock that returns the string
50+
mock_resp.text = AsyncMock(return_value='{"msg": "Not Found"}')
51+
52+
mock_resp.status = 404
53+
mock_resp.__aenter__.return_value = mock_resp
54+
mock_resp.__aexit__.return_value = None
55+
56+
with patch("aiohttp.ClientSession.get", return_value=mock_resp), caplog.at_level(
57+
logging.WARNING
58+
):
59+
await charger.process_request("http://url", method="get")
60+
# Verify the 404 response body was logged as a warning
61+
assert "{'msg': 'Not Found'}" in caplog.text

0 commit comments

Comments
 (0)