parent
a22a966fac
commit
cc872b4618
|
@ -386,10 +386,6 @@ omit =
|
|||
homeassistant/components/glances/sensor.py
|
||||
homeassistant/components/gntp/notify.py
|
||||
homeassistant/components/goalfeed/*
|
||||
homeassistant/components/goalzero/__init__.py
|
||||
homeassistant/components/goalzero/binary_sensor.py
|
||||
homeassistant/components/goalzero/sensor.py
|
||||
homeassistant/components/goalzero/switch.py
|
||||
homeassistant/components/google/*
|
||||
homeassistant/components/google_cloud/tts.py
|
||||
homeassistant/components/google_maps/device_tracker.py
|
||||
|
|
|
@ -12,6 +12,7 @@ from homeassistant.config_entries import ConfigEntry
|
|||
from homeassistant.const import ATTR_ATTRIBUTION, ATTR_MODEL, CONF_HOST, CONF_NAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
|
@ -101,6 +102,7 @@ class YetiEntity(CoordinatorEntity):
|
|||
def device_info(self) -> DeviceInfo:
|
||||
"""Return the device information of the entity."""
|
||||
return DeviceInfo(
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, self.api.sysdata["macAddress"])},
|
||||
identifiers={(DOMAIN, self._server_unique_id)},
|
||||
manufacturer="Goal Zero",
|
||||
model=self.api.sysdata[ATTR_MODEL],
|
||||
|
|
|
@ -15,7 +15,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|||
from homeassistant.helpers.device_registry import format_mac
|
||||
from homeassistant.helpers.typing import DiscoveryInfoType
|
||||
|
||||
from .const import DEFAULT_NAME, DOMAIN
|
||||
from .const import DEFAULT_NAME, DOMAIN, MANUFACTURER
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -48,7 +48,7 @@ class GoalZeroFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Allow the user to confirm adding the device."""
|
||||
if user_input is not None:
|
||||
return self.async_create_entry(
|
||||
title="Goal Zero",
|
||||
title=MANUFACTURER,
|
||||
data={
|
||||
CONF_HOST: self.ip_address,
|
||||
CONF_NAME: DEFAULT_NAME,
|
||||
|
|
|
@ -8,5 +8,5 @@ DATA_KEY_COORDINATOR = "coordinator"
|
|||
DOMAIN = "goalzero"
|
||||
DEFAULT_NAME = "Yeti"
|
||||
DATA_KEY_API = "api"
|
||||
|
||||
MANUFACTURER = "Goal Zero"
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
|
||||
|
|
|
@ -38,6 +38,8 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
|||
from . import Yeti, YetiEntity
|
||||
from .const import DATA_KEY_API, DATA_KEY_COORDINATOR, DOMAIN
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
|
||||
SensorEntityDescription(
|
||||
key="wattsIn",
|
||||
|
|
|
@ -13,6 +13,8 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
|||
from . import Yeti, YetiEntity
|
||||
from .const import DATA_KEY_API, DATA_KEY_COORDINATOR, DOMAIN
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
SWITCH_TYPES: tuple[SwitchEntityDescription, ...] = (
|
||||
SwitchEntityDescription(
|
||||
key="v12PortStatus",
|
||||
|
|
|
@ -1,33 +1,50 @@
|
|||
"""Tests for the Goal Zero Yeti integration."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from homeassistant.components.dhcp import HOSTNAME, IP_ADDRESS, MAC_ADDRESS
|
||||
from homeassistant.components.goalzero import DOMAIN
|
||||
from homeassistant.components.goalzero.const import DEFAULT_NAME
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import format_mac
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import MockConfigEntry, load_fixture
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
HOST = "1.2.3.4"
|
||||
NAME = "Yeti"
|
||||
MAC = "aa:bb:cc:dd:ee:ff"
|
||||
|
||||
CONF_DATA = {
|
||||
CONF_HOST: HOST,
|
||||
CONF_NAME: NAME,
|
||||
}
|
||||
|
||||
CONF_CONFIG_FLOW = {
|
||||
CONF_HOST: HOST,
|
||||
CONF_NAME: NAME,
|
||||
CONF_NAME: DEFAULT_NAME,
|
||||
}
|
||||
|
||||
CONF_DHCP_FLOW = {
|
||||
IP_ADDRESS: "1.1.1.1",
|
||||
MAC_ADDRESS: "AA:BB:CC:DD:EE:FF",
|
||||
HOSTNAME: "any",
|
||||
IP_ADDRESS: HOST,
|
||||
MAC_ADDRESS: format_mac("AA:BB:CC:DD:EE:FF"),
|
||||
HOSTNAME: "yeti",
|
||||
}
|
||||
|
||||
|
||||
async def _create_mocked_yeti(raise_exception=False):
|
||||
def create_entry(hass: HomeAssistant):
|
||||
"""Add config entry in Home Assistant."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data=CONF_DATA,
|
||||
unique_id=MAC,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
return entry
|
||||
|
||||
|
||||
async def _create_mocked_yeti():
|
||||
mocked_yeti = AsyncMock()
|
||||
mocked_yeti.get_state = AsyncMock()
|
||||
mocked_yeti.data = {}
|
||||
mocked_yeti.data["firmwareVersion"] = "1.0.0"
|
||||
mocked_yeti.sysdata = {}
|
||||
mocked_yeti.sysdata["model"] = "test_model"
|
||||
mocked_yeti.sysdata["macAddress"] = MAC
|
||||
return mocked_yeti
|
||||
|
||||
|
||||
|
@ -40,3 +57,41 @@ def _patch_config_flow_yeti(mocked_yeti):
|
|||
"homeassistant.components.goalzero.config_flow.Yeti",
|
||||
return_value=mocked_yeti,
|
||||
)
|
||||
|
||||
|
||||
async def async_init_integration(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
skip_setup: bool = False,
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the Goal Zero integration in Home Assistant."""
|
||||
entry = create_entry(hass)
|
||||
base_url = f"http://{HOST}/"
|
||||
aioclient_mock.get(
|
||||
f"{base_url}state",
|
||||
text=load_fixture("goalzero/state_data.json"),
|
||||
)
|
||||
aioclient_mock.get(
|
||||
f"{base_url}sysinfo",
|
||||
text=load_fixture("goalzero/info_data.json"),
|
||||
)
|
||||
|
||||
if not skip_setup:
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return entry
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
platform: str,
|
||||
):
|
||||
"""Set up the platform."""
|
||||
entry = await async_init_integration(hass, aioclient_mock)
|
||||
|
||||
with patch("homeassistant.components.goalzero.PLATFORMS", [platform]):
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
|
||||
return entry
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name":"yeti123456789012",
|
||||
"model":"Yeti 1400",
|
||||
"firmwareVersion":"1.5.7",
|
||||
"macAddress":"123456789012",
|
||||
"platform":"esp32"
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"thingName":"yeti123456789012",
|
||||
"v12PortStatus":0,
|
||||
"usbPortStatus":0,
|
||||
"acPortStatus":1,
|
||||
"backlight":1,
|
||||
"app_online":0,
|
||||
"wattsIn":0.0,
|
||||
"ampsIn":0.0,
|
||||
"wattsOut":50.5,
|
||||
"ampsOut":2.1,
|
||||
"whOut":5.23,
|
||||
"whStored":1330,
|
||||
"volts":12.0,
|
||||
"socPercent":95,
|
||||
"isCharging":0,
|
||||
"inputDetected":0,
|
||||
"timeToEmptyFull":-1,
|
||||
"temperature":25,
|
||||
"wifiStrength":-62,
|
||||
"ssid":"wifi",
|
||||
"ipAddr":"1.2.3.4",
|
||||
"timestamp":1720984,
|
||||
"firmwareVersion":"1.5.7",
|
||||
"version":3,
|
||||
"ota":{
|
||||
"delay":0,
|
||||
"status":"000-000-100_001-000-100_002-000-100_003-000-100"
|
||||
},
|
||||
"notify":{
|
||||
"enabled":1048575,
|
||||
"trigger":0
|
||||
},
|
||||
"foreignAcsry":{
|
||||
"model":"Yeti MPPT",
|
||||
"firmwareVersion":"1.1.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
"""Binary sensor tests for the Goalzero integration."""
|
||||
from homeassistant.components.binary_sensor import (
|
||||
DEVICE_CLASS_BATTERY_CHARGING,
|
||||
DEVICE_CLASS_CONNECTIVITY,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.components.goalzero.const import DEFAULT_NAME
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
DEVICE_CLASS_POWER,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import async_setup_platform
|
||||
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
|
||||
async def test_binary_sensors(hass: HomeAssistant, aioclient_mock: AiohttpClientMocker):
|
||||
"""Test we get sensor data."""
|
||||
await async_setup_platform(hass, aioclient_mock, DOMAIN)
|
||||
|
||||
state = hass.states.get(f"binary_sensor.{DEFAULT_NAME}_backlight")
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) is None
|
||||
state = hass.states.get(f"binary_sensor.{DEFAULT_NAME}_app_online")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_CONNECTIVITY
|
||||
state = hass.states.get(f"binary_sensor.{DEFAULT_NAME}_charging")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_BATTERY_CHARGING
|
||||
state = hass.states.get(f"binary_sensor.{DEFAULT_NAME}_input_detected")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_POWER
|
|
@ -3,44 +3,26 @@ from unittest.mock import patch
|
|||
|
||||
from goalzero import exceptions
|
||||
|
||||
from homeassistant.components.goalzero.const import DOMAIN
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.goalzero.const import DEFAULT_NAME, DOMAIN, MANUFACTURER
|
||||
from homeassistant.config_entries import SOURCE_DHCP, SOURCE_USER
|
||||
from homeassistant.data_entry_flow import (
|
||||
RESULT_TYPE_ABORT,
|
||||
RESULT_TYPE_CREATE_ENTRY,
|
||||
RESULT_TYPE_FORM,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import (
|
||||
CONF_CONFIG_FLOW,
|
||||
CONF_DATA,
|
||||
CONF_DHCP_FLOW,
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
NAME,
|
||||
MAC,
|
||||
_create_mocked_yeti,
|
||||
_patch_config_flow_yeti,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
def _flow_next(hass, flow_id):
|
||||
return next(
|
||||
flow
|
||||
for flow in hass.config_entries.flow.async_progress()
|
||||
if flow["flow_id"] == flow_id
|
||||
create_entry,
|
||||
)
|
||||
|
||||
|
||||
def _patch_setup():
|
||||
return patch(
|
||||
"homeassistant.components.goalzero.async_setup_entry",
|
||||
return_value=True,
|
||||
)
|
||||
return patch("homeassistant.components.goalzero.async_setup_entry")
|
||||
|
||||
|
||||
async def test_flow_user(hass):
|
||||
async def test_flow_user(hass: HomeAssistant):
|
||||
"""Test user initialized flow."""
|
||||
mocked_yeti = await _create_mocked_yeti()
|
||||
with _patch_config_flow_yeti(mocked_yeti), _patch_setup():
|
||||
|
@ -50,74 +32,62 @@ async def test_flow_user(hass):
|
|||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_CONFIG_FLOW,
|
||||
user_input=CONF_DATA,
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == NAME
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == DEFAULT_NAME
|
||||
assert result["data"] == CONF_DATA
|
||||
assert result["result"].unique_id == MAC
|
||||
|
||||
|
||||
async def test_flow_user_already_configured(hass):
|
||||
async def test_flow_user_already_configured(hass: HomeAssistant):
|
||||
"""Test user initialized flow with duplicate server."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={CONF_HOST: "1.2.3.4", CONF_NAME: "Yeti"},
|
||||
)
|
||||
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
service_info = {
|
||||
"host": "1.2.3.4",
|
||||
"name": "Yeti",
|
||||
}
|
||||
create_entry(hass)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}, data=service_info
|
||||
DOMAIN, context={"source": SOURCE_USER}, data=CONF_DATA
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_flow_user_cannot_connect(hass):
|
||||
async def test_flow_user_cannot_connect(hass: HomeAssistant):
|
||||
"""Test user initialized flow with unreachable server."""
|
||||
mocked_yeti = await _create_mocked_yeti(True)
|
||||
with _patch_config_flow_yeti(mocked_yeti) as yetimock:
|
||||
with _patch_config_flow_yeti(await _create_mocked_yeti()) as yetimock:
|
||||
yetimock.side_effect = exceptions.ConnectError
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}, data=CONF_CONFIG_FLOW
|
||||
DOMAIN, context={"source": SOURCE_USER}, data=CONF_DATA
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {"base": "cannot_connect"}
|
||||
assert result["errors"]["base"] == "cannot_connect"
|
||||
|
||||
|
||||
async def test_flow_user_invalid_host(hass):
|
||||
async def test_flow_user_invalid_host(hass: HomeAssistant):
|
||||
"""Test user initialized flow with invalid server."""
|
||||
mocked_yeti = await _create_mocked_yeti(True)
|
||||
with _patch_config_flow_yeti(mocked_yeti) as yetimock:
|
||||
with _patch_config_flow_yeti(await _create_mocked_yeti()) as yetimock:
|
||||
yetimock.side_effect = exceptions.InvalidHost
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}, data=CONF_CONFIG_FLOW
|
||||
DOMAIN, context={"source": SOURCE_USER}, data=CONF_DATA
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {"base": "invalid_host"}
|
||||
assert result["errors"]["base"] == "invalid_host"
|
||||
|
||||
|
||||
async def test_flow_user_unknown_error(hass):
|
||||
async def test_flow_user_unknown_error(hass: HomeAssistant):
|
||||
"""Test user initialized flow with unreachable server."""
|
||||
mocked_yeti = await _create_mocked_yeti(True)
|
||||
with _patch_config_flow_yeti(mocked_yeti) as yetimock:
|
||||
with _patch_config_flow_yeti(await _create_mocked_yeti()) as yetimock:
|
||||
yetimock.side_effect = Exception
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}, data=CONF_CONFIG_FLOW
|
||||
DOMAIN, context={"source": SOURCE_USER}, data=CONF_DATA
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {"base": "unknown"}
|
||||
assert result["errors"]["base"] == "unknown"
|
||||
|
||||
|
||||
async def test_dhcp_discovery(hass):
|
||||
async def test_dhcp_discovery(hass: HomeAssistant):
|
||||
"""Test we can process the discovery from dhcp."""
|
||||
|
||||
mocked_yeti = await _create_mocked_yeti()
|
||||
|
@ -127,31 +97,30 @@ async def test_dhcp_discovery(hass):
|
|||
context={"source": SOURCE_DHCP},
|
||||
data=CONF_DHCP_FLOW,
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["data"] == {
|
||||
CONF_HOST: "1.1.1.1",
|
||||
CONF_NAME: "Yeti",
|
||||
}
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == MANUFACTURER
|
||||
assert result["data"] == CONF_DATA
|
||||
assert result["result"].unique_id == MAC
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_DHCP},
|
||||
data=CONF_DHCP_FLOW,
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_dhcp_discovery_failed(hass):
|
||||
async def test_dhcp_discovery_failed(hass: HomeAssistant):
|
||||
"""Test failed setup from dhcp."""
|
||||
mocked_yeti = await _create_mocked_yeti(True)
|
||||
mocked_yeti = await _create_mocked_yeti()
|
||||
with _patch_config_flow_yeti(mocked_yeti) as yetimock:
|
||||
yetimock.side_effect = exceptions.ConnectError
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -159,7 +128,7 @@ async def test_dhcp_discovery_failed(hass):
|
|||
context={"source": SOURCE_DHCP},
|
||||
data=CONF_DHCP_FLOW,
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "cannot_connect"
|
||||
|
||||
with _patch_config_flow_yeti(mocked_yeti) as yetimock:
|
||||
|
@ -169,7 +138,7 @@ async def test_dhcp_discovery_failed(hass):
|
|||
context={"source": SOURCE_DHCP},
|
||||
data=CONF_DHCP_FLOW,
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "invalid_host"
|
||||
|
||||
with _patch_config_flow_yeti(mocked_yeti) as yetimock:
|
||||
|
@ -179,5 +148,5 @@ async def test_dhcp_discovery_failed(hass):
|
|||
context={"source": SOURCE_DHCP},
|
||||
data=CONF_DHCP_FLOW,
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "unknown"
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
"""Test Goal Zero integration."""
|
||||
from datetime import timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
from goalzero import exceptions
|
||||
|
||||
from homeassistant.components.goalzero.const import (
|
||||
DATA_KEY_COORDINATOR,
|
||||
DEFAULT_NAME,
|
||||
DOMAIN,
|
||||
MANUFACTURER,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from . import (
|
||||
CONF_DATA,
|
||||
_create_mocked_yeti,
|
||||
_patch_init_yeti,
|
||||
async_init_integration,
|
||||
create_entry,
|
||||
)
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
|
||||
async def test_setup_config_and_unload(hass: HomeAssistant):
|
||||
"""Test Goal Zero setup and unload."""
|
||||
entry = create_entry(hass)
|
||||
with _patch_init_yeti(await _create_mocked_yeti()):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert entry.state == ConfigEntryState.LOADED
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
assert entry.data == CONF_DATA
|
||||
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entry.state is ConfigEntryState.NOT_LOADED
|
||||
assert not hass.data.get(DOMAIN)
|
||||
|
||||
|
||||
async def test_async_setup_entry_not_ready(hass: HomeAssistant):
|
||||
"""Test that it throws ConfigEntryNotReady when exception occurs during setup."""
|
||||
entry = create_entry(hass)
|
||||
with patch(
|
||||
"homeassistant.components.goalzero.Yeti.init_connect",
|
||||
side_effect=exceptions.ConnectError,
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
assert entry.state == ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_update_failed(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
) -> None:
|
||||
"""Test data update failure."""
|
||||
entry = await async_init_integration(hass, aioclient_mock)
|
||||
coordinator: DataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][
|
||||
DATA_KEY_COORDINATOR
|
||||
]
|
||||
with patch(
|
||||
"homeassistant.components.goalzero.Yeti.get_state",
|
||||
side_effect=exceptions.ConnectError,
|
||||
) as updater:
|
||||
next_update = dt_util.utcnow() + timedelta(seconds=30)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
updater.assert_called_once()
|
||||
assert not coordinator.last_update_success
|
||||
|
||||
|
||||
async def test_device_info(hass: HomeAssistant, aioclient_mock: AiohttpClientMocker):
|
||||
"""Test device info."""
|
||||
entry = await async_init_integration(hass, aioclient_mock)
|
||||
device_registry = await dr.async_get_registry(hass)
|
||||
|
||||
device = device_registry.async_get_device({(DOMAIN, entry.entry_id)})
|
||||
|
||||
assert device.connections == {("mac", "12:34:56:78:90:12")}
|
||||
assert device.identifiers == {(DOMAIN, entry.entry_id)}
|
||||
assert device.manufacturer == MANUFACTURER
|
||||
assert device.model == "Yeti 1400"
|
||||
assert device.name == DEFAULT_NAME
|
||||
assert device.sw_version == "1.5.7"
|
|
@ -0,0 +1,112 @@
|
|||
"""Sensor tests for the Goalzero integration."""
|
||||
from homeassistant.components.goalzero.const import DEFAULT_NAME
|
||||
from homeassistant.components.goalzero.sensor import SENSOR_TYPES
|
||||
from homeassistant.components.sensor import (
|
||||
ATTR_STATE_CLASS,
|
||||
DOMAIN,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
STATE_CLASS_TOTAL_INCREASING,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
DEVICE_CLASS_BATTERY,
|
||||
DEVICE_CLASS_CURRENT,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_POWER,
|
||||
DEVICE_CLASS_SIGNAL_STRENGTH,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
DEVICE_CLASS_VOLTAGE,
|
||||
ELECTRIC_CURRENT_AMPERE,
|
||||
ELECTRIC_POTENTIAL_VOLT,
|
||||
ENERGY_WATT_HOUR,
|
||||
PERCENTAGE,
|
||||
POWER_WATT,
|
||||
SIGNAL_STRENGTH_DECIBELS,
|
||||
TEMP_CELSIUS,
|
||||
TIME_MINUTES,
|
||||
TIME_SECONDS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import async_setup_platform
|
||||
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
|
||||
async def test_sensors(hass: HomeAssistant, aioclient_mock: AiohttpClientMocker):
|
||||
"""Test we get sensor data."""
|
||||
for description in SENSOR_TYPES:
|
||||
description.entity_registry_enabled_default = True
|
||||
await async_setup_platform(hass, aioclient_mock, DOMAIN)
|
||||
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_watts_in")
|
||||
assert state.state == "0.0"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_POWER
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == POWER_WATT
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_amps_in")
|
||||
assert state.state == "0.0"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_CURRENT
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == ELECTRIC_CURRENT_AMPERE
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_watts_out")
|
||||
assert state.state == "50.5"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_POWER
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == POWER_WATT
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_amps_out")
|
||||
assert state.state == "2.1"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_CURRENT
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == ELECTRIC_CURRENT_AMPERE
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_wh_out")
|
||||
assert state.state == "5.23"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_ENERGY
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == ENERGY_WATT_HOUR
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_TOTAL_INCREASING
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_wh_stored")
|
||||
assert state.state == "1330"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_ENERGY
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == ENERGY_WATT_HOUR
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_volts")
|
||||
assert state.state == "12.0"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_VOLTAGE
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == ELECTRIC_POTENTIAL_VOLT
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) is None
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_state_of_charge_percent")
|
||||
assert state.state == "95"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_BATTERY
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == PERCENTAGE
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) is None
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_time_to_empty_full")
|
||||
assert state.state == "-1"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == TIME_MINUTES
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TIME_MINUTES
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) is None
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_temperature")
|
||||
assert state.state == "25"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) is None
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_wifi_strength")
|
||||
assert state.state == "-62"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_SIGNAL_STRENGTH
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == SIGNAL_STRENGTH_DECIBELS
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) is None
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_total_run_time")
|
||||
assert state.state == "1720984"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) is None
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TIME_SECONDS
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) is None
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_wi_fi_ssid")
|
||||
assert state.state == "wifi"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) is None
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) is None
|
||||
state = hass.states.get(f"sensor.{DEFAULT_NAME}_ip_address")
|
||||
assert state.state == "1.2.3.4"
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) is None
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) is None
|
|
@ -0,0 +1,49 @@
|
|||
"""Switch tests for the Goalzero integration."""
|
||||
from homeassistant.components.goalzero.const import DEFAULT_NAME
|
||||
from homeassistant.components.switch import DOMAIN as DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import async_setup_platform
|
||||
|
||||
from tests.common import load_fixture
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
|
||||
async def test_switches_states(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
):
|
||||
"""Test we get sensor data."""
|
||||
aioclient_mock.post(
|
||||
"http://1.2.3.4/state",
|
||||
text=load_fixture("goalzero/state_data.json"),
|
||||
)
|
||||
await async_setup_platform(hass, aioclient_mock, DOMAIN)
|
||||
|
||||
entity_id = f"switch.{DEFAULT_NAME}_12v_port_status"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_OFF
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: [entity_id]},
|
||||
blocking=True,
|
||||
)
|
||||
entity_id = f"switch.{DEFAULT_NAME}_usb_port_status"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_OFF
|
||||
entity_id = f"switch.{DEFAULT_NAME}_ac_port_status"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: [entity_id]},
|
||||
blocking=True,
|
||||
)
|
Loading…
Reference in New Issue