109 lines
3.8 KiB
Python
109 lines
3.8 KiB
Python
"""Tests for Baidu Weather API client."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import aiohttp
|
|
import pytest
|
|
|
|
from custom_components.hass_weather_baidu.api import (
|
|
BaiduWeatherApiClient,
|
|
BaiduWeatherApiError,
|
|
BaiduWeatherAuthError,
|
|
BaiduWeatherConnectionError,
|
|
async_fetch_district_data,
|
|
)
|
|
|
|
from .conftest import MOCK_AK, MOCK_DISTRICT_CSV, MOCK_WEATHER_RESPONSE
|
|
|
|
|
|
class TestBaiduWeatherApiClient:
|
|
"""Test BaiduWeatherApiClient."""
|
|
|
|
async def test_get_weather_by_district_success(self) -> None:
|
|
"""Test successful weather fetch by district ID."""
|
|
session = MagicMock(spec=aiohttp.ClientSession)
|
|
mock_response = AsyncMock()
|
|
mock_response.raise_for_status = MagicMock()
|
|
mock_response.json = AsyncMock(return_value=MOCK_WEATHER_RESPONSE)
|
|
session.get = AsyncMock(return_value=mock_response)
|
|
session.get.return_value.__aenter__ = AsyncMock(
|
|
return_value=mock_response
|
|
)
|
|
session.get.return_value.__aexit__ = AsyncMock(return_value=False)
|
|
|
|
client = BaiduWeatherApiClient(session=session, ak=MOCK_AK)
|
|
|
|
with patch("asyncio.timeout"):
|
|
result = await client.async_get_weather_by_district("110108")
|
|
|
|
assert result is not None
|
|
assert "now" in result or "location" in result
|
|
|
|
async def test_get_weather_auth_error(self) -> None:
|
|
"""Test auth error handling."""
|
|
session = MagicMock(spec=aiohttp.ClientSession)
|
|
error_response = {"status": 211, "message": "AK无效"}
|
|
mock_response = AsyncMock()
|
|
mock_response.raise_for_status = MagicMock()
|
|
mock_response.json = AsyncMock(return_value=error_response)
|
|
session.get = AsyncMock(return_value=mock_response)
|
|
|
|
client = BaiduWeatherApiClient(session=session, ak="invalid_ak")
|
|
|
|
with pytest.raises(BaiduWeatherAuthError):
|
|
with patch("asyncio.timeout"):
|
|
await client.async_get_weather_by_district("110108")
|
|
|
|
async def test_clean_abnormal_values(self) -> None:
|
|
"""Test that abnormal values are cleaned."""
|
|
session = MagicMock(spec=aiohttp.ClientSession)
|
|
response_data = {
|
|
"status": 0,
|
|
"result": {
|
|
"now": {
|
|
"temp": 25,
|
|
"pressure": 999999,
|
|
"wind_class": "暂无",
|
|
}
|
|
},
|
|
}
|
|
mock_response = AsyncMock()
|
|
mock_response.raise_for_status = MagicMock()
|
|
mock_response.json = AsyncMock(return_value=response_data)
|
|
session.get = AsyncMock(return_value=mock_response)
|
|
|
|
client = BaiduWeatherApiClient(session=session, ak=MOCK_AK)
|
|
|
|
with patch("asyncio.timeout"):
|
|
result = await client.async_get_weather_by_district("110108")
|
|
|
|
assert result["now"]["temp"] == 25
|
|
assert result["now"]["pressure"] is None
|
|
assert result["now"]["wind_class"] is None
|
|
|
|
|
|
class TestAsyncFetchDistrictData:
|
|
"""Test district data fetching."""
|
|
|
|
async def test_parse_district_csv(self) -> None:
|
|
"""Test CSV parsing returns correct structure."""
|
|
session = MagicMock(spec=aiohttp.ClientSession)
|
|
mock_response = AsyncMock()
|
|
mock_response.raise_for_status = MagicMock()
|
|
mock_response.text = AsyncMock(return_value=MOCK_DISTRICT_CSV)
|
|
session.get = AsyncMock(return_value=mock_response)
|
|
|
|
with patch("asyncio.timeout"):
|
|
result = await async_fetch_district_data(session)
|
|
|
|
assert "北京市" in result
|
|
assert "北京市" in result["北京市"]
|
|
assert "海淀区" in result["北京市"]["北京市"]
|
|
assert result["北京市"]["北京市"]["海淀区"] == "110108"
|
|
|
|
assert "上海市" in result
|
|
assert "黄浦区" in result["上海市"]["上海市"]
|