Add Fyta sensor tests (#117995)
* Add test for init * update tests * split common.py into const.py and __init__.py * Update tests/components/fyta/__init__.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * add autospec, tidy up * adjust len-test * add test_sensor.py, amend tests for coordinator.py * Update tests/components/fyta/conftest.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * move load_unload with expired token into own test * Update tests/components/fyta/test_init.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * ruff change --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>pull/117229/head^2
parent
1565561c03
commit
2a8fc7f310
|
@ -471,9 +471,6 @@ omit =
|
|||
homeassistant/components/frontier_silicon/browse_media.py
|
||||
homeassistant/components/frontier_silicon/media_player.py
|
||||
homeassistant/components/futurenow/light.py
|
||||
homeassistant/components/fyta/coordinator.py
|
||||
homeassistant/components/fyta/entity.py
|
||||
homeassistant/components/fyta/sensor.py
|
||||
homeassistant/components/garadget/cover.py
|
||||
homeassistant/components/garages_amsterdam/__init__.py
|
||||
homeassistant/components/garages_amsterdam/binary_sensor.py
|
||||
|
|
|
@ -11,7 +11,7 @@ from homeassistant.const import CONF_ACCESS_TOKEN, CONF_PASSWORD, CONF_USERNAME
|
|||
|
||||
from .const import ACCESS_TOKEN, EXPIRATION, PASSWORD, USERNAME
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.common import MockConfigEntry, load_json_object_fixture
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -27,6 +27,7 @@ def mock_config_entry() -> MockConfigEntry:
|
|||
CONF_EXPIRATION: EXPIRATION,
|
||||
},
|
||||
minor_version=2,
|
||||
entry_id="ce5f5431554d101905d31797e1232da8",
|
||||
)
|
||||
|
||||
|
||||
|
@ -39,6 +40,13 @@ def mock_fyta_connector():
|
|||
tzinfo=UTC
|
||||
)
|
||||
mock_fyta_connector.client = AsyncMock(autospec=True)
|
||||
mock_fyta_connector.update_all_plants.return_value = load_json_object_fixture(
|
||||
"plant_status.json", FYTA_DOMAIN
|
||||
)
|
||||
mock_fyta_connector.plant_list = load_json_object_fixture(
|
||||
"plant_list.json", FYTA_DOMAIN
|
||||
)
|
||||
|
||||
mock_fyta_connector.login = AsyncMock(
|
||||
return_value={
|
||||
CONF_ACCESS_TOKEN: ACCESS_TOKEN,
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"0": "Gummibaum",
|
||||
"1": "Kakaobaum"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"0": {
|
||||
"name": "Gummibaum",
|
||||
"scientific_name": "Ficus elastica",
|
||||
"status": 1,
|
||||
"sw_version": "1.0"
|
||||
},
|
||||
"1": {
|
||||
"name": "Kakaobaum",
|
||||
"scientific_name": "Theobroma cacao",
|
||||
"status": 2,
|
||||
"sw_version": "1.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
# serializer version: 1
|
||||
# name: test_all_entities[sensor.gummibaum_plant_state-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'deleted',
|
||||
'doing_great',
|
||||
'need_attention',
|
||||
'no_sensor',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.gummibaum_plant_state',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Plant state',
|
||||
'platform': 'fyta',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'plant_status',
|
||||
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-status',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.gummibaum_plant_state-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'enum',
|
||||
'friendly_name': 'Gummibaum Plant state',
|
||||
'options': list([
|
||||
'deleted',
|
||||
'doing_great',
|
||||
'need_attention',
|
||||
'no_sensor',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gummibaum_plant_state',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'doing_great',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.gummibaum_scientific_name-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.gummibaum_scientific_name',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Scientific name',
|
||||
'platform': 'fyta',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'scientific_name',
|
||||
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-scientific_name',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.gummibaum_scientific_name-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Gummibaum Scientific name',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gummibaum_scientific_name',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'Ficus elastica',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.kakaobaum_plant_state-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'deleted',
|
||||
'doing_great',
|
||||
'need_attention',
|
||||
'no_sensor',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.kakaobaum_plant_state',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Plant state',
|
||||
'platform': 'fyta',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'plant_status',
|
||||
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-status',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.kakaobaum_plant_state-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'enum',
|
||||
'friendly_name': 'Kakaobaum Plant state',
|
||||
'options': list([
|
||||
'deleted',
|
||||
'doing_great',
|
||||
'need_attention',
|
||||
'no_sensor',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.kakaobaum_plant_state',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'need_attention',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.kakaobaum_scientific_name-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.kakaobaum_scientific_name',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Scientific name',
|
||||
'platform': 'fyta',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'scientific_name',
|
||||
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-scientific_name',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[sensor.kakaobaum_scientific_name-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Kakaobaum Scientific name',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.kakaobaum_scientific_name',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'Theobroma cacao',
|
||||
})
|
||||
# ---
|
|
@ -41,6 +41,23 @@ async def test_load_unload(
|
|||
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
|
||||
|
||||
async def test_refresh_expired_token(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_fyta_connector: AsyncMock,
|
||||
) -> None:
|
||||
"""Test we refresh an expired token."""
|
||||
|
||||
mock_fyta_connector.expiration = datetime.fromisoformat(EXPIRATION_OLD).replace(
|
||||
tzinfo=UTC
|
||||
)
|
||||
await setup_platform(hass, mock_config_entry, [Platform.SENSOR])
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
assert len(mock_fyta_connector.login.mock_calls) == 1
|
||||
assert mock_config_entry.data[CONF_EXPIRATION] == EXPIRATION
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"exception",
|
||||
[
|
||||
|
@ -84,6 +101,26 @@ async def test_raise_config_entry_not_ready_when_offline(
|
|||
assert len(hass.config_entries.flow.async_progress()) == 0
|
||||
|
||||
|
||||
async def test_raise_config_entry_not_ready_when_offline_and_expired(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_fyta_connector: AsyncMock,
|
||||
) -> None:
|
||||
"""Config entry state is SETUP_RETRY when FYTA is offline and access_token is expired."""
|
||||
|
||||
mock_fyta_connector.login.side_effect = FytaConnectionError
|
||||
mock_fyta_connector.expiration = datetime.fromisoformat(EXPIRATION_OLD).replace(
|
||||
tzinfo=UTC
|
||||
)
|
||||
|
||||
await setup_platform(hass, mock_config_entry, [Platform.SENSOR])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
assert len(hass.config_entries.flow.async_progress()) == 0
|
||||
|
||||
|
||||
async def test_migrate_config_entry(
|
||||
hass: HomeAssistant,
|
||||
mock_fyta_connector: AsyncMock,
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
"""Test the Home Assistant fyta sensor module."""
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from fyta_cli.fyta_exceptions import FytaConnectionError
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import STATE_UNAVAILABLE, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import setup_platform
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||
|
||||
|
||||
async def test_all_entities(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
mock_fyta_connector: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test all entities."""
|
||||
|
||||
await setup_platform(hass, mock_config_entry, [Platform.SENSOR])
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_connection_error(
|
||||
hass: HomeAssistant,
|
||||
mock_fyta_connector: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test connection error."""
|
||||
await setup_platform(hass, mock_config_entry, [Platform.SENSOR])
|
||||
|
||||
mock_fyta_connector.update_all_plants.side_effect = FytaConnectionError
|
||||
|
||||
freezer.tick(delta=timedelta(hours=12))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("sensor.gummibaum_plant_state").state == STATE_UNAVAILABLE
|
Loading…
Reference in New Issue