Wallbox fix too many requests by API (#147197)

This commit is contained in:
Hessel 2025-06-23 14:10:50 +02:00 committed by GitHub
parent b2520394f4
commit 756b858840
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 692 additions and 454 deletions

View File

@ -3,7 +3,7 @@
from enum import StrEnum from enum import StrEnum
DOMAIN = "wallbox" DOMAIN = "wallbox"
UPDATE_INTERVAL = 30 UPDATE_INTERVAL = 60
BIDIRECTIONAL_MODEL_PREFIXES = ["QS"] BIDIRECTIONAL_MODEL_PREFIXES = ["QS"]

View File

@ -90,7 +90,9 @@ def _require_authentication[_WallboxCoordinatorT: WallboxCoordinator, **_P](
except requests.exceptions.HTTPError as wallbox_connection_error: except requests.exceptions.HTTPError as wallbox_connection_error:
if wallbox_connection_error.response.status_code == HTTPStatus.FORBIDDEN: if wallbox_connection_error.response.status_code == HTTPStatus.FORBIDDEN:
raise ConfigEntryAuthFailed from wallbox_connection_error raise ConfigEntryAuthFailed from wallbox_connection_error
raise ConnectionError from wallbox_connection_error raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="api_failed"
) from wallbox_connection_error
return require_authentication return require_authentication
@ -137,56 +139,65 @@ class WallboxCoordinator(DataUpdateCoordinator[dict[str, Any]]):
@_require_authentication @_require_authentication
def _get_data(self) -> dict[str, Any]: def _get_data(self) -> dict[str, Any]:
"""Get new sensor data for Wallbox component.""" """Get new sensor data for Wallbox component."""
data: dict[str, Any] = self._wallbox.getChargerStatus(self._station) try:
data[CHARGER_MAX_CHARGING_CURRENT_KEY] = data[CHARGER_DATA_KEY][ data: dict[str, Any] = self._wallbox.getChargerStatus(self._station)
CHARGER_MAX_CHARGING_CURRENT_KEY data[CHARGER_MAX_CHARGING_CURRENT_KEY] = data[CHARGER_DATA_KEY][
] CHARGER_MAX_CHARGING_CURRENT_KEY
data[CHARGER_LOCKED_UNLOCKED_KEY] = data[CHARGER_DATA_KEY][
CHARGER_LOCKED_UNLOCKED_KEY
]
data[CHARGER_ENERGY_PRICE_KEY] = data[CHARGER_DATA_KEY][
CHARGER_ENERGY_PRICE_KEY
]
# Only show max_icp_current if power_boost is available in the wallbox unit:
if (
data[CHARGER_DATA_KEY].get(CHARGER_MAX_ICP_CURRENT_KEY, 0) > 0
and CHARGER_POWER_BOOST_KEY
in data[CHARGER_DATA_KEY][CHARGER_PLAN_KEY][CHARGER_FEATURES_KEY]
):
data[CHARGER_MAX_ICP_CURRENT_KEY] = data[CHARGER_DATA_KEY][
CHARGER_MAX_ICP_CURRENT_KEY
] ]
data[CHARGER_LOCKED_UNLOCKED_KEY] = data[CHARGER_DATA_KEY][
CHARGER_LOCKED_UNLOCKED_KEY
]
data[CHARGER_ENERGY_PRICE_KEY] = data[CHARGER_DATA_KEY][
CHARGER_ENERGY_PRICE_KEY
]
# Only show max_icp_current if power_boost is available in the wallbox unit:
if (
data[CHARGER_DATA_KEY].get(CHARGER_MAX_ICP_CURRENT_KEY, 0) > 0
and CHARGER_POWER_BOOST_KEY
in data[CHARGER_DATA_KEY][CHARGER_PLAN_KEY][CHARGER_FEATURES_KEY]
):
data[CHARGER_MAX_ICP_CURRENT_KEY] = data[CHARGER_DATA_KEY][
CHARGER_MAX_ICP_CURRENT_KEY
]
data[CHARGER_CURRENCY_KEY] = ( data[CHARGER_CURRENCY_KEY] = (
f"{data[CHARGER_DATA_KEY][CHARGER_CURRENCY_KEY][CODE_KEY]}/kWh" f"{data[CHARGER_DATA_KEY][CHARGER_CURRENCY_KEY][CODE_KEY]}/kWh"
) )
data[CHARGER_STATUS_DESCRIPTION_KEY] = CHARGER_STATUS.get( data[CHARGER_STATUS_DESCRIPTION_KEY] = CHARGER_STATUS.get(
data[CHARGER_STATUS_ID_KEY], ChargerStatus.UNKNOWN data[CHARGER_STATUS_ID_KEY], ChargerStatus.UNKNOWN
) )
# Set current solar charging mode # Set current solar charging mode
eco_smart_enabled = ( eco_smart_enabled = (
data[CHARGER_DATA_KEY] data[CHARGER_DATA_KEY]
.get(CHARGER_ECO_SMART_KEY, {}) .get(CHARGER_ECO_SMART_KEY, {})
.get(CHARGER_ECO_SMART_STATUS_KEY) .get(CHARGER_ECO_SMART_STATUS_KEY)
) )
eco_smart_mode = ( eco_smart_mode = (
data[CHARGER_DATA_KEY] data[CHARGER_DATA_KEY]
.get(CHARGER_ECO_SMART_KEY, {}) .get(CHARGER_ECO_SMART_KEY, {})
.get(CHARGER_ECO_SMART_MODE_KEY) .get(CHARGER_ECO_SMART_MODE_KEY)
) )
if eco_smart_mode is None: if eco_smart_mode is None:
data[CHARGER_ECO_SMART_KEY] = EcoSmartMode.DISABLED data[CHARGER_ECO_SMART_KEY] = EcoSmartMode.DISABLED
elif eco_smart_enabled is False: elif eco_smart_enabled is False:
data[CHARGER_ECO_SMART_KEY] = EcoSmartMode.OFF data[CHARGER_ECO_SMART_KEY] = EcoSmartMode.OFF
elif eco_smart_mode == 0: elif eco_smart_mode == 0:
data[CHARGER_ECO_SMART_KEY] = EcoSmartMode.ECO_MODE data[CHARGER_ECO_SMART_KEY] = EcoSmartMode.ECO_MODE
elif eco_smart_mode == 1: elif eco_smart_mode == 1:
data[CHARGER_ECO_SMART_KEY] = EcoSmartMode.FULL_SOLAR data[CHARGER_ECO_SMART_KEY] = EcoSmartMode.FULL_SOLAR
return data return data # noqa: TRY300
except requests.exceptions.HTTPError as wallbox_connection_error:
if wallbox_connection_error.response.status_code == 429:
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="too_many_requests"
) from wallbox_connection_error
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="api_failed"
) from wallbox_connection_error
async def _async_update_data(self) -> dict[str, Any]: async def _async_update_data(self) -> dict[str, Any]:
"""Get new sensor data for Wallbox component.""" """Get new sensor data for Wallbox component."""
@ -200,7 +211,13 @@ class WallboxCoordinator(DataUpdateCoordinator[dict[str, Any]]):
except requests.exceptions.HTTPError as wallbox_connection_error: except requests.exceptions.HTTPError as wallbox_connection_error:
if wallbox_connection_error.response.status_code == 403: if wallbox_connection_error.response.status_code == 403:
raise InvalidAuth from wallbox_connection_error raise InvalidAuth from wallbox_connection_error
raise if wallbox_connection_error.response.status_code == 429:
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="too_many_requests"
) from wallbox_connection_error
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="api_failed"
) from wallbox_connection_error
async def async_set_charging_current(self, charging_current: float) -> None: async def async_set_charging_current(self, charging_current: float) -> None:
"""Set maximum charging current for Wallbox.""" """Set maximum charging current for Wallbox."""
@ -217,7 +234,13 @@ class WallboxCoordinator(DataUpdateCoordinator[dict[str, Any]]):
except requests.exceptions.HTTPError as wallbox_connection_error: except requests.exceptions.HTTPError as wallbox_connection_error:
if wallbox_connection_error.response.status_code == 403: if wallbox_connection_error.response.status_code == 403:
raise InvalidAuth from wallbox_connection_error raise InvalidAuth from wallbox_connection_error
raise if wallbox_connection_error.response.status_code == 429:
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="too_many_requests"
) from wallbox_connection_error
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="api_failed"
) from wallbox_connection_error
async def async_set_icp_current(self, icp_current: float) -> None: async def async_set_icp_current(self, icp_current: float) -> None:
"""Set maximum icp current for Wallbox.""" """Set maximum icp current for Wallbox."""
@ -227,8 +250,16 @@ class WallboxCoordinator(DataUpdateCoordinator[dict[str, Any]]):
@_require_authentication @_require_authentication
def _set_energy_cost(self, energy_cost: float) -> None: def _set_energy_cost(self, energy_cost: float) -> None:
"""Set energy cost for Wallbox.""" """Set energy cost for Wallbox."""
try:
self._wallbox.setEnergyCost(self._station, energy_cost) self._wallbox.setEnergyCost(self._station, energy_cost)
except requests.exceptions.HTTPError as wallbox_connection_error:
if wallbox_connection_error.response.status_code == 429:
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="too_many_requests"
) from wallbox_connection_error
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="api_failed"
) from wallbox_connection_error
async def async_set_energy_cost(self, energy_cost: float) -> None: async def async_set_energy_cost(self, energy_cost: float) -> None:
"""Set energy cost for Wallbox.""" """Set energy cost for Wallbox."""
@ -246,7 +277,13 @@ class WallboxCoordinator(DataUpdateCoordinator[dict[str, Any]]):
except requests.exceptions.HTTPError as wallbox_connection_error: except requests.exceptions.HTTPError as wallbox_connection_error:
if wallbox_connection_error.response.status_code == 403: if wallbox_connection_error.response.status_code == 403:
raise InvalidAuth from wallbox_connection_error raise InvalidAuth from wallbox_connection_error
raise if wallbox_connection_error.response.status_code == 429:
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="too_many_requests"
) from wallbox_connection_error
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="api_failed"
) from wallbox_connection_error
async def async_set_lock_unlock(self, lock: bool) -> None: async def async_set_lock_unlock(self, lock: bool) -> None:
"""Set wallbox to locked or unlocked.""" """Set wallbox to locked or unlocked."""
@ -256,11 +293,19 @@ class WallboxCoordinator(DataUpdateCoordinator[dict[str, Any]]):
@_require_authentication @_require_authentication
def _pause_charger(self, pause: bool) -> None: def _pause_charger(self, pause: bool) -> None:
"""Set wallbox to pause or resume.""" """Set wallbox to pause or resume."""
try:
if pause: if pause:
self._wallbox.pauseChargingSession(self._station) self._wallbox.pauseChargingSession(self._station)
else: else:
self._wallbox.resumeChargingSession(self._station) self._wallbox.resumeChargingSession(self._station)
except requests.exceptions.HTTPError as wallbox_connection_error:
if wallbox_connection_error.response.status_code == 429:
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="too_many_requests"
) from wallbox_connection_error
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="api_failed"
) from wallbox_connection_error
async def async_pause_charger(self, pause: bool) -> None: async def async_pause_charger(self, pause: bool) -> None:
"""Set wallbox to pause or resume.""" """Set wallbox to pause or resume."""
@ -270,13 +315,21 @@ class WallboxCoordinator(DataUpdateCoordinator[dict[str, Any]]):
@_require_authentication @_require_authentication
def _set_eco_smart(self, option: str) -> None: def _set_eco_smart(self, option: str) -> None:
"""Set wallbox solar charging mode.""" """Set wallbox solar charging mode."""
try:
if option == EcoSmartMode.ECO_MODE: if option == EcoSmartMode.ECO_MODE:
self._wallbox.enableEcoSmart(self._station, 0) self._wallbox.enableEcoSmart(self._station, 0)
elif option == EcoSmartMode.FULL_SOLAR: elif option == EcoSmartMode.FULL_SOLAR:
self._wallbox.enableEcoSmart(self._station, 1) self._wallbox.enableEcoSmart(self._station, 1)
else: else:
self._wallbox.disableEcoSmart(self._station) self._wallbox.disableEcoSmart(self._station)
except requests.exceptions.HTTPError as wallbox_connection_error:
if wallbox_connection_error.response.status_code == 429:
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="too_many_requests"
) from wallbox_connection_error
raise HomeAssistantError(
translation_domain=DOMAIN, translation_key="api_failed"
) from wallbox_connection_error
async def async_set_eco_smart(self, option: str) -> None: async def async_set_eco_smart(self, option: str) -> None:
"""Set wallbox solar charging mode.""" """Set wallbox solar charging mode."""

View File

@ -7,7 +7,7 @@ from typing import Any
from homeassistant.components.lock import LockEntity, LockEntityDescription from homeassistant.components.lock import LockEntity, LockEntityDescription
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady from homeassistant.exceptions import HomeAssistantError, PlatformNotReady
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import ( from .const import (
@ -41,7 +41,7 @@ async def async_setup_entry(
) )
except InvalidAuth: except InvalidAuth:
return return
except ConnectionError as exc: except HomeAssistantError as exc:
raise PlatformNotReady from exc raise PlatformNotReady from exc
async_add_entities( async_add_entities(

View File

@ -12,7 +12,7 @@ from typing import cast
from homeassistant.components.number import NumberEntity, NumberEntityDescription from homeassistant.components.number import NumberEntity, NumberEntityDescription
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady from homeassistant.exceptions import HomeAssistantError, PlatformNotReady
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import ( from .const import (
@ -93,7 +93,7 @@ async def async_setup_entry(
) )
except InvalidAuth: except InvalidAuth:
return return
except ConnectionError as exc: except HomeAssistantError as exc:
raise PlatformNotReady from exc raise PlatformNotReady from exc
async_add_entities( async_add_entities(

View File

@ -3,7 +3,6 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
import logging
from typing import cast from typing import cast
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
@ -49,11 +48,6 @@ from .const import (
from .coordinator import WallboxCoordinator from .coordinator import WallboxCoordinator
from .entity import WallboxEntity from .entity import WallboxEntity
CHARGER_STATION = "station"
UPDATE_INTERVAL = 30
_LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True) @dataclass(frozen=True)
class WallboxSensorEntityDescription(SensorEntityDescription): class WallboxSensorEntityDescription(SensorEntityDescription):

View File

@ -112,6 +112,9 @@
"exceptions": { "exceptions": {
"api_failed": { "api_failed": {
"message": "Error communicating with Wallbox API" "message": "Error communicating with Wallbox API"
},
"too_many_requests": {
"message": "Error communicating with Wallbox API, too many requests"
} }
} }
} }

View File

@ -162,6 +162,9 @@ test_response_no_power_boost = {
http_404_error = requests.exceptions.HTTPError() http_404_error = requests.exceptions.HTTPError()
http_404_error.response = requests.Response() http_404_error.response = requests.Response()
http_404_error.response.status_code = HTTPStatus.NOT_FOUND http_404_error.response.status_code = HTTPStatus.NOT_FOUND
http_429_error = requests.exceptions.HTTPError()
http_429_error.response = requests.Response()
http_429_error.response.status_code = HTTPStatus.TOO_MANY_REQUESTS
authorisation_response = { authorisation_response = {
"data": { "data": {
@ -192,6 +195,24 @@ authorisation_response_unauthorised = {
} }
} }
invalid_reauth_response = {
"jwt": "fakekeyhere",
"refresh_token": "refresh_fakekeyhere",
"user_id": 12345,
"ttl": 145656758,
"refresh_token_ttl": 145756758,
"error": False,
"status": 200,
}
http_403_error = requests.exceptions.HTTPError()
http_403_error.response = requests.Response()
http_403_error.response.status_code = HTTPStatus.FORBIDDEN
http_404_error = requests.exceptions.HTTPError()
http_404_error.response = requests.Response()
http_404_error.response.status_code = HTTPStatus.NOT_FOUND
async def setup_integration(hass: HomeAssistant, entry: MockConfigEntry) -> None: async def setup_integration(hass: HomeAssistant, entry: MockConfigEntry) -> None:
"""Test wallbox sensor class setup.""" """Test wallbox sensor class setup."""

View File

@ -1,9 +1,6 @@
"""Test the Wallbox config flow.""" """Test the Wallbox config flow."""
from http import HTTPStatus from unittest.mock import Mock, patch
import json
import requests_mock
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.wallbox import config_flow from homeassistant.components.wallbox import config_flow
@ -24,23 +21,21 @@ from homeassistant.data_entry_flow import FlowResultType
from . import ( from . import (
authorisation_response, authorisation_response,
authorisation_response_unauthorised, authorisation_response_unauthorised,
http_403_error,
http_404_error,
setup_integration, setup_integration,
) )
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
test_response = json.loads( test_response = {
json.dumps( CHARGER_CHARGING_POWER_KEY: 0,
{ CHARGER_MAX_AVAILABLE_POWER_KEY: "xx",
CHARGER_CHARGING_POWER_KEY: 0, CHARGER_CHARGING_SPEED_KEY: 0,
CHARGER_MAX_AVAILABLE_POWER_KEY: "xx", CHARGER_ADDED_RANGE_KEY: "xx",
CHARGER_CHARGING_SPEED_KEY: 0, CHARGER_ADDED_ENERGY_KEY: "44.697",
CHARGER_ADDED_RANGE_KEY: "xx", CHARGER_DATA_KEY: {CHARGER_MAX_CHARGING_CURRENT_KEY: 24},
CHARGER_ADDED_ENERGY_KEY: "44.697", }
CHARGER_DATA_KEY: {CHARGER_MAX_CHARGING_CURRENT_KEY: 24},
}
)
)
async def test_show_set_form(hass: HomeAssistant) -> None: async def test_show_set_form(hass: HomeAssistant) -> None:
@ -59,17 +54,16 @@ async def test_form_cannot_authenticate(hass: HomeAssistant) -> None:
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(side_effect=http_403_error),
status_code=HTTPStatus.FORBIDDEN, ),
) patch(
mock_request.get( "homeassistant.components.wallbox.Wallbox.pauseChargingSession",
"https://api.wall-box.com/chargers/status/12345", new=Mock(side_effect=http_403_error),
json=test_response, ),
status_code=HTTPStatus.FORBIDDEN, ):
)
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
{ {
@ -89,17 +83,16 @@ async def test_form_cannot_connect(hass: HomeAssistant) -> None:
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response_unauthorised, new=Mock(side_effect=http_404_error),
status_code=HTTPStatus.NOT_FOUND, ),
) patch(
mock_request.get( "homeassistant.components.wallbox.Wallbox.pauseChargingSession",
"https://api.wall-box.com/chargers/status/12345", new=Mock(side_effect=http_404_error),
json=test_response, ),
status_code=HTTPStatus.NOT_FOUND, ):
)
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
{ {
@ -119,17 +112,16 @@ async def test_form_validate_input(hass: HomeAssistant) -> None:
DOMAIN, context={"source": config_entries.SOURCE_USER} DOMAIN, context={"source": config_entries.SOURCE_USER}
) )
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=HTTPStatus.OK, ),
) patch(
mock_request.get( "homeassistant.components.wallbox.Wallbox.getChargerStatus",
"https://api.wall-box.com/chargers/status/12345", new=Mock(return_value=test_response),
json=test_response, ),
status_code=HTTPStatus.OK, ):
)
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
{ {
@ -148,18 +140,16 @@ async def test_form_reauth(hass: HomeAssistant, entry: MockConfigEntry) -> None:
await setup_integration(hass, entry) await setup_integration(hass, entry)
assert entry.state is ConfigEntryState.LOADED assert entry.state is ConfigEntryState.LOADED
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response_unauthorised),
status_code=200, ),
) patch(
mock_request.get( "homeassistant.components.wallbox.Wallbox.getChargerStatus",
"https://api.wall-box.com/chargers/status/12345", new=Mock(return_value=test_response),
json=test_response, ),
status_code=200, ):
)
result = await entry.start_reauth_flow(hass) result = await entry.start_reauth_flow(hass)
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
@ -183,26 +173,16 @@ async def test_form_reauth_invalid(hass: HomeAssistant, entry: MockConfigEntry)
await setup_integration(hass, entry) await setup_integration(hass, entry)
assert entry.state is ConfigEntryState.LOADED assert entry.state is ConfigEntryState.LOADED
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json={ new=Mock(return_value=authorisation_response_unauthorised),
"jwt": "fakekeyhere", ),
"refresh_token": "refresh_fakekeyhere", patch(
"user_id": 12345, "homeassistant.components.wallbox.Wallbox.getChargerStatus",
"ttl": 145656758, new=Mock(return_value=test_response),
"refresh_token_ttl": 145756758, ),
"error": False, ):
"status": 200,
},
status_code=200,
)
mock_request.get(
"https://api.wall-box.com/chargers/status/12345",
json=test_response,
status_code=200,
)
result = await entry.start_reauth_flow(hass) result = await entry.start_reauth_flow(hass)
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(

View File

@ -1,16 +1,15 @@
"""Test Wallbox Init Component.""" """Test Wallbox Init Component."""
import requests_mock from unittest.mock import Mock, patch
from homeassistant.components.wallbox.const import ( from homeassistant.components.wallbox.const import DOMAIN
CHARGER_MAX_CHARGING_CURRENT_KEY,
DOMAIN,
)
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from . import ( from . import (
authorisation_response, authorisation_response,
http_403_error,
http_429_error,
setup_integration, setup_integration,
setup_integration_connection_error, setup_integration_connection_error,
setup_integration_no_eco_mode, setup_integration_no_eco_mode,
@ -53,18 +52,16 @@ async def test_wallbox_refresh_failed_connection_error_auth(
await setup_integration(hass, entry) await setup_integration(hass, entry)
assert entry.state is ConfigEntryState.LOADED assert entry.state is ConfigEntryState.LOADED
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(side_effect=http_429_error),
status_code=404, ),
) patch(
mock_request.get( "homeassistant.components.wallbox.Wallbox.pauseChargingSession",
"https://api.wall-box.com/chargers/status/12345", new=Mock(return_value=test_response),
json=test_response, ),
status_code=200, ):
)
wallbox = hass.data[DOMAIN][entry.entry_id] wallbox = hass.data[DOMAIN][entry.entry_id]
await wallbox.async_refresh() await wallbox.async_refresh()
@ -81,18 +78,68 @@ async def test_wallbox_refresh_failed_invalid_auth(
await setup_integration(hass, entry) await setup_integration(hass, entry)
assert entry.state is ConfigEntryState.LOADED assert entry.state is ConfigEntryState.LOADED
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(side_effect=http_403_error),
status_code=403, ),
) patch(
mock_request.put( "homeassistant.components.wallbox.Wallbox.pauseChargingSession",
"https://api.wall-box.com/v2/charger/12345", new=Mock(side_effect=http_403_error),
json={CHARGER_MAX_CHARGING_CURRENT_KEY: 20}, ),
status_code=403, ):
) wallbox = hass.data[DOMAIN][entry.entry_id]
await wallbox.async_refresh()
assert await hass.config_entries.async_unload(entry.entry_id)
assert entry.state is ConfigEntryState.NOT_LOADED
async def test_wallbox_refresh_failed_http_error(
hass: HomeAssistant, entry: MockConfigEntry
) -> None:
"""Test Wallbox setup with authentication error."""
await setup_integration(hass, entry)
assert entry.state is ConfigEntryState.LOADED
with (
patch(
"homeassistant.components.wallbox.Wallbox.authenticate",
new=Mock(return_value=authorisation_response),
),
patch(
"homeassistant.components.wallbox.Wallbox.getChargerStatus",
new=Mock(side_effect=http_403_error),
),
):
wallbox = hass.data[DOMAIN][entry.entry_id]
await wallbox.async_refresh()
assert await hass.config_entries.async_unload(entry.entry_id)
assert entry.state is ConfigEntryState.NOT_LOADED
async def test_wallbox_refresh_failed_too_many_requests(
hass: HomeAssistant, entry: MockConfigEntry
) -> None:
"""Test Wallbox setup with authentication error."""
await setup_integration(hass, entry)
assert entry.state is ConfigEntryState.LOADED
with (
patch(
"homeassistant.components.wallbox.Wallbox.authenticate",
new=Mock(return_value=authorisation_response),
),
patch(
"homeassistant.components.wallbox.Wallbox.getChargerStatus",
new=Mock(side_effect=http_429_error),
),
):
wallbox = hass.data[DOMAIN][entry.entry_id] wallbox = hass.data[DOMAIN][entry.entry_id]
await wallbox.async_refresh() await wallbox.async_refresh()
@ -109,18 +156,16 @@ async def test_wallbox_refresh_failed_connection_error(
await setup_integration(hass, entry) await setup_integration(hass, entry)
assert entry.state is ConfigEntryState.LOADED assert entry.state is ConfigEntryState.LOADED
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
mock_request.get( "homeassistant.components.wallbox.Wallbox.pauseChargingSession",
"https://api.wall-box.com/chargers/status/12345", new=Mock(side_effect=http_403_error),
json=test_response, ),
status_code=403, ):
)
wallbox = hass.data[DOMAIN][entry.entry_id] wallbox = hass.data[DOMAIN][entry.entry_id]
await wallbox.async_refresh() await wallbox.async_refresh()

View File

@ -1,15 +1,18 @@
"""Test Wallbox Lock component.""" """Test Wallbox Lock component."""
from unittest.mock import Mock, patch
import pytest import pytest
import requests_mock
from homeassistant.components.lock import SERVICE_LOCK, SERVICE_UNLOCK from homeassistant.components.lock import SERVICE_LOCK, SERVICE_UNLOCK
from homeassistant.components.wallbox.const import CHARGER_LOCKED_UNLOCKED_KEY from homeassistant.components.wallbox.const import CHARGER_LOCKED_UNLOCKED_KEY
from homeassistant.const import ATTR_ENTITY_ID from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from . import ( from . import (
authorisation_response, authorisation_response,
http_429_error,
setup_integration, setup_integration,
setup_integration_platform_not_ready, setup_integration_platform_not_ready,
setup_integration_read_only, setup_integration_read_only,
@ -28,18 +31,20 @@ async def test_wallbox_lock_class(hass: HomeAssistant, entry: MockConfigEntry) -
assert state assert state
assert state.state == "unlocked" assert state.state == "unlocked"
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
mock_request.put( "homeassistant.components.wallbox.Wallbox.lockCharger",
"https://api.wall-box.com/v2/charger/12345", new=Mock(return_value={CHARGER_LOCKED_UNLOCKED_KEY: False}),
json={CHARGER_LOCKED_UNLOCKED_KEY: False}, ),
status_code=200, patch(
) "homeassistant.components.wallbox.Wallbox.unlockCharger",
new=Mock(return_value={CHARGER_LOCKED_UNLOCKED_KEY: False}),
),
):
await hass.services.async_call( await hass.services.async_call(
"lock", "lock",
SERVICE_LOCK, SERVICE_LOCK,
@ -66,36 +71,73 @@ async def test_wallbox_lock_class_connection_error(
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
mock_request.put( "homeassistant.components.wallbox.Wallbox.lockCharger",
"https://api.wall-box.com/v2/charger/12345", new=Mock(side_effect=ConnectionError),
json={CHARGER_LOCKED_UNLOCKED_KEY: False}, ),
status_code=404, pytest.raises(ConnectionError),
):
await hass.services.async_call(
"lock",
SERVICE_LOCK,
{
ATTR_ENTITY_ID: MOCK_LOCK_ENTITY_ID,
},
blocking=True,
) )
with pytest.raises(ConnectionError): with (
await hass.services.async_call( patch(
"lock", "homeassistant.components.wallbox.Wallbox.authenticate",
SERVICE_LOCK, new=Mock(return_value=authorisation_response),
{ ),
ATTR_ENTITY_ID: MOCK_LOCK_ENTITY_ID, patch(
}, "homeassistant.components.wallbox.Wallbox.lockCharger",
blocking=True, new=Mock(side_effect=ConnectionError),
) ),
with pytest.raises(ConnectionError): patch(
await hass.services.async_call( "homeassistant.components.wallbox.Wallbox.unlockCharger",
"lock", new=Mock(side_effect=ConnectionError),
SERVICE_UNLOCK, ),
{ pytest.raises(ConnectionError),
ATTR_ENTITY_ID: MOCK_LOCK_ENTITY_ID, ):
}, await hass.services.async_call(
blocking=True, "lock",
) SERVICE_UNLOCK,
{
ATTR_ENTITY_ID: MOCK_LOCK_ENTITY_ID,
},
blocking=True,
)
with (
patch(
"homeassistant.components.wallbox.Wallbox.authenticate",
new=Mock(return_value=authorisation_response),
),
patch(
"homeassistant.components.wallbox.Wallbox.lockCharger",
new=Mock(side_effect=http_429_error),
),
patch(
"homeassistant.components.wallbox.Wallbox.unlockCharger",
new=Mock(side_effect=http_429_error),
),
pytest.raises(HomeAssistantError),
):
await hass.services.async_call(
"lock",
SERVICE_UNLOCK,
{
ATTR_ENTITY_ID: MOCK_LOCK_ENTITY_ID,
},
blocking=True,
)
async def test_wallbox_lock_class_authentication_error( async def test_wallbox_lock_class_authentication_error(

View File

@ -1,22 +1,26 @@
"""Test Wallbox Switch component.""" """Test Wallbox Switch component."""
from unittest.mock import Mock, patch
import pytest import pytest
import requests_mock
from homeassistant.components.input_number import ATTR_VALUE, SERVICE_SET_VALUE from homeassistant.components.input_number import ATTR_VALUE, SERVICE_SET_VALUE
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN
from homeassistant.components.wallbox import InvalidAuth
from homeassistant.components.wallbox.const import ( from homeassistant.components.wallbox.const import (
CHARGER_ENERGY_PRICE_KEY, CHARGER_ENERGY_PRICE_KEY,
CHARGER_MAX_CHARGING_CURRENT_KEY, CHARGER_MAX_CHARGING_CURRENT_KEY,
CHARGER_MAX_ICP_CURRENT_KEY, CHARGER_MAX_ICP_CURRENT_KEY,
) )
from homeassistant.components.wallbox.coordinator import InvalidAuth
from homeassistant.const import ATTR_ENTITY_ID from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.exceptions import HomeAssistantError
from . import ( from . import (
authorisation_response, authorisation_response,
http_403_error,
http_404_error,
http_429_error,
setup_integration, setup_integration,
setup_integration_bidir, setup_integration_bidir,
setup_integration_platform_not_ready, setup_integration_platform_not_ready,
@ -29,6 +33,14 @@ from .const import (
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
mock_wallbox = Mock()
mock_wallbox.authenticate = Mock(return_value=authorisation_response)
mock_wallbox.setEnergyCost = Mock(return_value={CHARGER_ENERGY_PRICE_KEY: 1.1})
mock_wallbox.setMaxChargingCurrent = Mock(
return_value={CHARGER_MAX_CHARGING_CURRENT_KEY: 20}
)
mock_wallbox.setIcpMaxCurrent = Mock(return_value={CHARGER_MAX_ICP_CURRENT_KEY: 10})
async def test_wallbox_number_class( async def test_wallbox_number_class(
hass: HomeAssistant, entry: MockConfigEntry hass: HomeAssistant, entry: MockConfigEntry
@ -37,17 +49,16 @@ async def test_wallbox_number_class(
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
mock_request.put( "homeassistant.components.wallbox.Wallbox.setMaxChargingCurrent",
"https://api.wall-box.com/v2/charger/12345", new=Mock(return_value={CHARGER_MAX_CHARGING_CURRENT_KEY: 20}),
json={CHARGER_MAX_CHARGING_CURRENT_KEY: 20}, ),
status_code=200, ):
)
state = hass.states.get(MOCK_NUMBER_ENTITY_ID) state = hass.states.get(MOCK_NUMBER_ENTITY_ID)
assert state.attributes["min"] == 6 assert state.attributes["min"] == 6
assert state.attributes["max"] == 25 assert state.attributes["max"] == 25
@ -82,19 +93,16 @@ async def test_wallbox_number_energy_class(
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
"homeassistant.components.wallbox.Wallbox.setEnergyCost",
mock_request.post( new=Mock(return_value={CHARGER_ENERGY_PRICE_KEY: 1.1}),
"https://api.wall-box.com/chargers/config/12345", ),
json={CHARGER_ENERGY_PRICE_KEY: 1.1}, ):
status_code=200,
)
await hass.services.async_call( await hass.services.async_call(
"number", "number",
SERVICE_SET_VALUE, SERVICE_SET_VALUE,
@ -113,59 +121,113 @@ async def test_wallbox_number_class_connection_error(
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
mock_request.put( "homeassistant.components.wallbox.Wallbox.setMaxChargingCurrent",
"https://api.wall-box.com/v2/charger/12345", new=Mock(side_effect=http_404_error),
json={CHARGER_MAX_CHARGING_CURRENT_KEY: 20}, ),
status_code=404, pytest.raises(HomeAssistantError),
):
await hass.services.async_call(
"number",
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ID,
ATTR_VALUE: 20,
},
blocking=True,
) )
with pytest.raises(ConnectionError):
await hass.services.async_call(
"number",
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ID,
ATTR_VALUE: 20,
},
blocking=True,
)
async def test_wallbox_number_class_too_many_requests(
async def test_wallbox_number_class_energy_price_connection_error(
hass: HomeAssistant, entry: MockConfigEntry hass: HomeAssistant, entry: MockConfigEntry
) -> None: ) -> None:
"""Test wallbox sensor class.""" """Test wallbox sensor class."""
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
mock_request.post( "homeassistant.components.wallbox.Wallbox.setMaxChargingCurrent",
"https://api.wall-box.com/chargers/config/12345", new=Mock(side_effect=http_429_error),
json={CHARGER_ENERGY_PRICE_KEY: 1.1}, ),
status_code=404, pytest.raises(HomeAssistantError),
):
await hass.services.async_call(
"number",
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ID,
ATTR_VALUE: 20,
},
blocking=True,
) )
with pytest.raises(ConnectionError):
await hass.services.async_call( async def test_wallbox_number_class_energy_price_update_failed(
"number", hass: HomeAssistant, entry: MockConfigEntry
SERVICE_SET_VALUE, ) -> None:
{ """Test wallbox sensor class."""
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ENERGY_PRICE_ID,
ATTR_VALUE: 1.1, await setup_integration(hass, entry)
},
blocking=True, with (
) patch(
"homeassistant.components.wallbox.Wallbox.authenticate",
new=Mock(return_value=authorisation_response),
),
patch(
"homeassistant.components.wallbox.Wallbox.setEnergyCost",
new=Mock(side_effect=http_429_error),
),
pytest.raises(HomeAssistantError),
):
await hass.services.async_call(
"number",
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ENERGY_PRICE_ID,
ATTR_VALUE: 1.1,
},
blocking=True,
)
async def test_wallbox_number_class_energy_price_update_connection_error(
hass: HomeAssistant, entry: MockConfigEntry
) -> None:
"""Test wallbox sensor class."""
await setup_integration(hass, entry)
with (
patch(
"homeassistant.components.wallbox.Wallbox.authenticate",
new=Mock(return_value=authorisation_response),
),
patch(
"homeassistant.components.wallbox.Wallbox.setEnergyCost",
new=Mock(side_effect=http_404_error),
),
pytest.raises(HomeAssistantError),
):
await hass.services.async_call(
"number",
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ENERGY_PRICE_ID,
ATTR_VALUE: 1.1,
},
blocking=True,
)
async def test_wallbox_number_class_energy_price_auth_error( async def test_wallbox_number_class_energy_price_auth_error(
@ -175,28 +237,26 @@ async def test_wallbox_number_class_energy_price_auth_error(
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
patch(
"homeassistant.components.wallbox.Wallbox.setEnergyCost",
new=Mock(side_effect=http_429_error),
),
pytest.raises(HomeAssistantError),
):
await hass.services.async_call(
"number",
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ENERGY_PRICE_ID,
ATTR_VALUE: 1.1,
},
blocking=True,
) )
mock_request.post(
"https://api.wall-box.com/chargers/config/12345",
json={CHARGER_ENERGY_PRICE_KEY: 1.1},
status_code=403,
)
with pytest.raises(ConfigEntryAuthFailed):
await hass.services.async_call(
"number",
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ENERGY_PRICE_ID,
ATTR_VALUE: 1.1,
},
blocking=True,
)
async def test_wallbox_number_class_platform_not_ready( async def test_wallbox_number_class_platform_not_ready(
@ -218,19 +278,16 @@ async def test_wallbox_number_class_icp_energy(
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
"homeassistant.components.wallbox.Wallbox.setIcpMaxCurrent",
mock_request.post( new=Mock(return_value={CHARGER_MAX_ICP_CURRENT_KEY: 10}),
"https://api.wall-box.com/chargers/config/12345", ),
json={CHARGER_MAX_ICP_CURRENT_KEY: 10}, ):
status_code=200,
)
await hass.services.async_call( await hass.services.async_call(
NUMBER_DOMAIN, NUMBER_DOMAIN,
SERVICE_SET_VALUE, SERVICE_SET_VALUE,
@ -249,28 +306,26 @@ async def test_wallbox_number_class_icp_energy_auth_error(
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
patch(
"homeassistant.components.wallbox.Wallbox.setIcpMaxCurrent",
new=Mock(side_effect=http_403_error),
),
pytest.raises(InvalidAuth),
):
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ICP_CURRENT_ID,
ATTR_VALUE: 10,
},
blocking=True,
) )
mock_request.post(
"https://api.wall-box.com/chargers/config/12345",
json={CHARGER_MAX_ICP_CURRENT_KEY: 10},
status_code=403,
)
with pytest.raises(InvalidAuth):
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ICP_CURRENT_ID,
ATTR_VALUE: 10,
},
blocking=True,
)
async def test_wallbox_number_class_icp_energy_connection_error( async def test_wallbox_number_class_icp_energy_connection_error(
@ -280,25 +335,52 @@ async def test_wallbox_number_class_icp_energy_connection_error(
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
mock_request.post( "homeassistant.components.wallbox.Wallbox.setIcpMaxCurrent",
"https://api.wall-box.com/chargers/config/12345", new=Mock(side_effect=http_404_error),
json={CHARGER_MAX_ICP_CURRENT_KEY: 10}, ),
status_code=404, pytest.raises(HomeAssistantError),
):
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ICP_CURRENT_ID,
ATTR_VALUE: 10,
},
blocking=True,
) )
with pytest.raises(ConnectionError):
await hass.services.async_call( async def test_wallbox_number_class_icp_energy_too_many_request(
NUMBER_DOMAIN, hass: HomeAssistant, entry: MockConfigEntry
SERVICE_SET_VALUE, ) -> None:
{ """Test wallbox sensor class."""
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ICP_CURRENT_ID,
ATTR_VALUE: 10, await setup_integration(hass, entry)
},
blocking=True, with (
) patch(
"homeassistant.components.wallbox.Wallbox.authenticate",
new=Mock(return_value=authorisation_response),
),
patch(
"homeassistant.components.wallbox.Wallbox.setIcpMaxCurrent",
new=Mock(side_effect=http_429_error),
),
pytest.raises(HomeAssistantError),
):
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: MOCK_NUMBER_ENTITY_ICP_CURRENT_ID,
ATTR_VALUE: 10,
},
blocking=True,
)

View File

@ -16,6 +16,7 @@ from homeassistant.core import HomeAssistant, HomeAssistantError
from . import ( from . import (
authorisation_response, authorisation_response,
http_404_error, http_404_error,
http_429_error,
setup_integration_select, setup_integration_select,
test_response, test_response,
test_response_eco_mode, test_response_eco_mode,
@ -109,7 +110,41 @@ async def test_wallbox_select_class_error(
"homeassistant.components.wallbox.Wallbox.enableEcoSmart", "homeassistant.components.wallbox.Wallbox.enableEcoSmart",
new=Mock(side_effect=error), new=Mock(side_effect=error),
), ),
pytest.raises(HomeAssistantError, match="Error communicating with Wallbox API"), pytest.raises(HomeAssistantError),
):
await hass.services.async_call(
SELECT_DOMAIN,
SERVICE_SELECT_OPTION,
{
ATTR_ENTITY_ID: MOCK_SELECT_ENTITY_ID,
ATTR_OPTION: mode,
},
blocking=True,
)
@pytest.mark.parametrize(("mode", "response"), TEST_OPTIONS)
async def test_wallbox_select_too_many_requests_error(
hass: HomeAssistant,
entry: MockConfigEntry,
mode,
response,
mock_authenticate,
) -> None:
"""Test wallbox select class connection error."""
await setup_integration_select(hass, entry, response)
with (
patch(
"homeassistant.components.wallbox.Wallbox.disableEcoSmart",
new=Mock(side_effect=http_429_error),
),
patch(
"homeassistant.components.wallbox.Wallbox.enableEcoSmart",
new=Mock(side_effect=http_429_error),
),
pytest.raises(HomeAssistantError),
): ):
await hass.services.async_call( await hass.services.async_call(
SELECT_DOMAIN, SELECT_DOMAIN,

View File

@ -1,15 +1,16 @@
"""Test Wallbox Lock component.""" """Test Wallbox Lock component."""
from unittest.mock import Mock, patch
import pytest import pytest
import requests_mock
from homeassistant.components.switch import SERVICE_TURN_OFF, SERVICE_TURN_ON from homeassistant.components.switch import SERVICE_TURN_OFF, SERVICE_TURN_ON
from homeassistant.components.wallbox.const import CHARGER_STATUS_ID_KEY from homeassistant.components.wallbox.const import CHARGER_STATUS_ID_KEY
from homeassistant.const import ATTR_ENTITY_ID from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.exceptions import HomeAssistantError
from . import authorisation_response, setup_integration from . import authorisation_response, http_404_error, http_429_error, setup_integration
from .const import MOCK_SWITCH_ENTITY_ID from .const import MOCK_SWITCH_ENTITY_ID
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -26,18 +27,20 @@ async def test_wallbox_switch_class(
assert state assert state
assert state.state == "on" assert state.state == "on"
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
mock_request.post( "homeassistant.components.wallbox.Wallbox.pauseChargingSession",
"https://api.wall-box.com/v3/chargers/12345/remote-action", new=Mock(return_value={CHARGER_STATUS_ID_KEY: 193}),
json={CHARGER_STATUS_ID_KEY: 193}, ),
status_code=200, patch(
) "homeassistant.components.wallbox.Wallbox.resumeChargingSession",
new=Mock(return_value={CHARGER_STATUS_ID_KEY: 193}),
),
):
await hass.services.async_call( await hass.services.async_call(
"switch", "switch",
SERVICE_TURN_ON, SERVICE_TURN_ON,
@ -64,72 +67,52 @@ async def test_wallbox_switch_class_connection_error(
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
) patch(
mock_request.post( "homeassistant.components.wallbox.Wallbox.resumeChargingSession",
"https://api.wall-box.com/v3/chargers/12345/remote-action", new=Mock(side_effect=http_404_error),
json={CHARGER_STATUS_ID_KEY: 193}, ),
status_code=404, pytest.raises(HomeAssistantError),
):
# Test behavior when a connection error occurs
await hass.services.async_call(
"switch",
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: MOCK_SWITCH_ENTITY_ID,
},
blocking=True,
) )
with pytest.raises(ConnectionError):
await hass.services.async_call(
"switch",
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: MOCK_SWITCH_ENTITY_ID,
},
blocking=True,
)
with pytest.raises(ConnectionError):
await hass.services.async_call(
"switch",
SERVICE_TURN_OFF,
{
ATTR_ENTITY_ID: MOCK_SWITCH_ENTITY_ID,
},
blocking=True,
)
async def test_wallbox_switch_class_too_many_requests(
async def test_wallbox_switch_class_authentication_error(
hass: HomeAssistant, entry: MockConfigEntry hass: HomeAssistant, entry: MockConfigEntry
) -> None: ) -> None:
"""Test wallbox switch class connection error.""" """Test wallbox switch class connection error."""
await setup_integration(hass, entry) await setup_integration(hass, entry)
with requests_mock.Mocker() as mock_request: with (
mock_request.get( patch(
"https://user-api.wall-box.com/users/signin", "homeassistant.components.wallbox.Wallbox.authenticate",
json=authorisation_response, new=Mock(return_value=authorisation_response),
status_code=200, ),
patch(
"homeassistant.components.wallbox.Wallbox.resumeChargingSession",
new=Mock(side_effect=http_429_error),
),
pytest.raises(HomeAssistantError),
):
# Test behavior when a connection error occurs
await hass.services.async_call(
"switch",
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: MOCK_SWITCH_ENTITY_ID,
},
blocking=True,
) )
mock_request.post(
"https://api.wall-box.com/v3/chargers/12345/remote-action",
json={CHARGER_STATUS_ID_KEY: 193},
status_code=403,
)
with pytest.raises(ConfigEntryAuthFailed):
await hass.services.async_call(
"switch",
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: MOCK_SWITCH_ENTITY_ID,
},
blocking=True,
)
with pytest.raises(ConfigEntryAuthFailed):
await hass.services.async_call(
"switch",
SERVICE_TURN_OFF,
{
ATTR_ENTITY_ID: MOCK_SWITCH_ENTITY_ID,
},
blocking=True,
)