|
4 | 4 | import json |
5 | 5 | import logging |
6 | 6 | from unittest import mock |
| 7 | +from unittest.mock import AsyncMock, MagicMock, patch |
7 | 8 |
|
8 | 9 | import aiohttp |
9 | 10 | import pytest |
|
12 | 13 | from awesomeversion.exceptions import AwesomeVersionCompareException |
13 | 14 |
|
14 | 15 | import openevsehttp.__main__ as main |
| 16 | +from openevsehttp.__main__ import OpenEVSE |
15 | 17 | from openevsehttp.exceptions import ( |
16 | 18 | InvalidType, |
17 | 19 | MissingSerial, |
18 | 20 | UnknownError, |
19 | 21 | UnsupportedFeature, |
20 | 22 | ) |
21 | | -from tests.common import load_fixture |
22 | 23 | from openevsehttp.websocket import ( |
23 | 24 | SIGNAL_CONNECTION_STATE, |
24 | 25 | STATE_CONNECTED, |
25 | 26 | STATE_DISCONNECTED, |
26 | 27 | ) |
| 28 | +from tests.common import load_fixture |
27 | 29 |
|
28 | 30 | pytestmark = pytest.mark.asyncio |
29 | 31 |
|
|
43 | 45 | TEST_URL_GITHUB_v2 = ( |
44 | 46 | "https://api.github.com/repos/OpenEVSE/ESP8266_WiFi_v2.x/releases/latest" |
45 | 47 | ) |
| 48 | +SERVER_URL = "openevse.test.tld" |
46 | 49 |
|
47 | 50 |
|
48 | 51 | async def test_get_status_auth(test_charger_auth): |
@@ -2209,3 +2212,69 @@ async def test_set_divert_mode( |
2209 | 2212 | with caplog.at_level(logging.DEBUG): |
2210 | 2213 | await test_charger_new.set_divert_mode("fast") |
2211 | 2214 | 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 == "" |
0 commit comments