Improve fyta tests (#117661)

* 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

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
dontinelli 2024-05-23 10:51:30 +02:00 committed by GitHub
parent e8f544d216
commit 6682244abf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 158 additions and 50 deletions

View File

@ -471,7 +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/__init__.py
homeassistant/components/fyta/coordinator.py
homeassistant/components/fyta/entity.py
homeassistant/components/fyta/sensor.py

View File

@ -1 +1,19 @@
"""Tests for the Fyta integration."""
from unittest.mock import patch
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
async def setup_platform(
hass: HomeAssistant, config_entry: MockConfigEntry, platforms: list[Platform]
) -> MockConfigEntry:
"""Set up the Fyta platform."""
config_entry.add_to_hass(hass)
with patch("homeassistant.components.fyta.PLATFORMS", platforms):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()

View File

@ -1,50 +1,63 @@
"""Test helpers."""
"""Test helpers for FYTA."""
from collections.abc import Generator
from datetime import UTC, datetime, timedelta
from datetime import UTC, datetime
from unittest.mock import AsyncMock, patch
import pytest
from homeassistant.components.fyta.const import CONF_EXPIRATION
from homeassistant.const import CONF_ACCESS_TOKEN
from homeassistant.components.fyta.const import CONF_EXPIRATION, DOMAIN as FYTA_DOMAIN
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_PASSWORD, CONF_USERNAME
from .test_config_flow import ACCESS_TOKEN, EXPIRATION
from .const import ACCESS_TOKEN, EXPIRATION, PASSWORD, USERNAME
from tests.common import MockConfigEntry
@pytest.fixture
def mock_fyta():
"""Build a fixture for the Fyta API that connects successfully and returns one device."""
mock_fyta_api = AsyncMock()
with patch(
"homeassistant.components.fyta.config_flow.FytaConnector",
return_value=mock_fyta_api,
) as mock_fyta_api:
mock_fyta_api.return_value.login.return_value = {
def mock_config_entry() -> MockConfigEntry:
"""Mock a config entry."""
return MockConfigEntry(
domain=FYTA_DOMAIN,
title="fyta_user",
data={
CONF_USERNAME: USERNAME,
CONF_PASSWORD: PASSWORD,
CONF_ACCESS_TOKEN: ACCESS_TOKEN,
CONF_EXPIRATION: EXPIRATION,
}
yield mock_fyta_api
},
minor_version=2,
)
@pytest.fixture
def mock_fyta_init():
def mock_fyta_connector():
"""Build a fixture for the Fyta API that connects successfully and returns one device."""
mock_fyta_api = AsyncMock()
mock_fyta_api.expiration = datetime.now(tz=UTC) + timedelta(days=1)
mock_fyta_api.login = AsyncMock(
mock_fyta_connector = AsyncMock()
mock_fyta_connector.expiration = datetime.fromisoformat(EXPIRATION).replace(
tzinfo=UTC
)
mock_fyta_connector.client = AsyncMock(autospec=True)
mock_fyta_connector.login = AsyncMock(
return_value={
CONF_ACCESS_TOKEN: ACCESS_TOKEN,
CONF_EXPIRATION: EXPIRATION,
CONF_EXPIRATION: datetime.fromisoformat(EXPIRATION).replace(tzinfo=UTC),
}
)
with patch(
"homeassistant.components.fyta.FytaConnector.__new__",
return_value=mock_fyta_api,
with (
patch(
"homeassistant.components.fyta.FytaConnector",
autospec=True,
return_value=mock_fyta_connector,
),
patch(
"homeassistant.components.fyta.config_flow.FytaConnector",
autospec=True,
return_value=mock_fyta_connector,
),
):
yield mock_fyta_api
yield mock_fyta_connector
@pytest.fixture

View File

@ -0,0 +1,7 @@
"""Common methods and const used across tests for FYTA."""
USERNAME = "fyta_user"
PASSWORD = "fyta_pass"
ACCESS_TOKEN = "123xyz"
EXPIRATION = "2030-12-31T10:00:00+00:00"
EXPIRATION_OLD = "2020-01-01T00:00:00+00:00"

View File

@ -1,6 +1,5 @@
"""Test the fyta config flow."""
from datetime import UTC, datetime
from unittest.mock import AsyncMock
from fyta_cli.fyta_exceptions import (
@ -16,16 +15,13 @@ from homeassistant.const import CONF_ACCESS_TOKEN, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry
from .const import ACCESS_TOKEN, EXPIRATION, PASSWORD, USERNAME
USERNAME = "fyta_user"
PASSWORD = "fyta_pass"
ACCESS_TOKEN = "123xyz"
EXPIRATION = datetime.fromisoformat("2024-12-31T10:00:00").replace(tzinfo=UTC)
from tests.common import MockConfigEntry
async def test_user_flow(
hass: HomeAssistant, mock_fyta: AsyncMock, mock_setup_entry: AsyncMock
hass: HomeAssistant, mock_fyta_connector: AsyncMock, mock_setup_entry: AsyncMock
) -> None:
"""Test we get the form."""
@ -46,7 +42,7 @@ async def test_user_flow(
CONF_USERNAME: USERNAME,
CONF_PASSWORD: PASSWORD,
CONF_ACCESS_TOKEN: ACCESS_TOKEN,
CONF_EXPIRATION: "2024-12-31T10:00:00+00:00",
CONF_EXPIRATION: EXPIRATION,
}
assert len(mock_setup_entry.mock_calls) == 1
@ -64,7 +60,7 @@ async def test_form_exceptions(
hass: HomeAssistant,
exception: Exception,
error: dict[str, str],
mock_fyta: AsyncMock,
mock_fyta_connector: AsyncMock,
mock_setup_entry: AsyncMock,
) -> None:
"""Test we can handle Form exceptions."""
@ -73,7 +69,7 @@ async def test_form_exceptions(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
mock_fyta.return_value.login.side_effect = exception
mock_fyta_connector.login.side_effect = exception
# tests with connection error
result = await hass.config_entries.flow.async_configure(
@ -85,7 +81,7 @@ async def test_form_exceptions(
assert result["step_id"] == "user"
assert result["errors"] == error
mock_fyta.return_value.login.side_effect = None
mock_fyta_connector.login.side_effect = None
# tests with all information provided
result = await hass.config_entries.flow.async_configure(
@ -98,12 +94,14 @@ async def test_form_exceptions(
assert result["data"][CONF_USERNAME] == USERNAME
assert result["data"][CONF_PASSWORD] == PASSWORD
assert result["data"][CONF_ACCESS_TOKEN] == ACCESS_TOKEN
assert result["data"][CONF_EXPIRATION] == "2024-12-31T10:00:00+00:00"
assert result["data"][CONF_EXPIRATION] == EXPIRATION
assert len(mock_setup_entry.mock_calls) == 1
async def test_duplicate_entry(hass: HomeAssistant, mock_fyta: AsyncMock) -> None:
async def test_duplicate_entry(
hass: HomeAssistant, mock_fyta_connector: AsyncMock
) -> None:
"""Test duplicate setup handling."""
entry = MockConfigEntry(
domain=DOMAIN,
@ -143,7 +141,7 @@ async def test_reauth(
hass: HomeAssistant,
exception: Exception,
error: dict[str, str],
mock_fyta: AsyncMock,
mock_fyta_connector: AsyncMock,
mock_setup_entry: AsyncMock,
) -> None:
"""Test reauth-flow works."""
@ -155,7 +153,7 @@ async def test_reauth(
CONF_USERNAME: USERNAME,
CONF_PASSWORD: PASSWORD,
CONF_ACCESS_TOKEN: ACCESS_TOKEN,
CONF_EXPIRATION: "2024-06-30T10:00:00+00:00",
CONF_EXPIRATION: EXPIRATION,
},
)
entry.add_to_hass(hass)
@ -168,7 +166,7 @@ async def test_reauth(
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
mock_fyta.return_value.login.side_effect = exception
mock_fyta_connector.login.side_effect = exception
# tests with connection error
result = await hass.config_entries.flow.async_configure(
@ -181,7 +179,7 @@ async def test_reauth(
assert result["step_id"] == "reauth_confirm"
assert result["errors"] == error
mock_fyta.return_value.login.side_effect = None
mock_fyta_connector.login.side_effect = None
# tests with all information provided
result = await hass.config_entries.flow.async_configure(
@ -195,4 +193,4 @@ async def test_reauth(
assert entry.data[CONF_USERNAME] == "other_username"
assert entry.data[CONF_PASSWORD] == "other_password"
assert entry.data[CONF_ACCESS_TOKEN] == ACCESS_TOKEN
assert entry.data[CONF_EXPIRATION] == "2024-12-31T10:00:00+00:00"
assert entry.data[CONF_EXPIRATION] == EXPIRATION

View File

@ -1,23 +1,96 @@
"""Test the initialization."""
from datetime import UTC, datetime
from unittest.mock import AsyncMock
from homeassistant.components.fyta.const import CONF_EXPIRATION, DOMAIN
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_PASSWORD, CONF_USERNAME
from fyta_cli.fyta_exceptions import (
FytaAuthentificationError,
FytaConnectionError,
FytaPasswordError,
)
import pytest
from homeassistant.components.fyta.const import CONF_EXPIRATION, DOMAIN as FYTA_DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import (
CONF_ACCESS_TOKEN,
CONF_PASSWORD,
CONF_USERNAME,
Platform,
)
from homeassistant.core import HomeAssistant
from .test_config_flow import ACCESS_TOKEN, PASSWORD, USERNAME
from . import setup_platform
from .const import ACCESS_TOKEN, EXPIRATION, EXPIRATION_OLD, PASSWORD, USERNAME
from tests.common import MockConfigEntry
async def test_load_unload(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_fyta_connector: AsyncMock,
) -> None:
"""Test load and unload."""
await setup_platform(hass, mock_config_entry, [Platform.SENSOR])
assert mock_config_entry.state is ConfigEntryState.LOADED
assert await hass.config_entries.async_unload(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
@pytest.mark.parametrize(
"exception",
[
FytaAuthentificationError,
FytaPasswordError,
],
)
async def test_invalid_credentials(
hass: HomeAssistant,
exception: Exception,
mock_config_entry: MockConfigEntry,
mock_fyta_connector: AsyncMock,
) -> None:
"""Test FYTA credentials changing."""
mock_fyta_connector.expiration = datetime.fromisoformat(EXPIRATION_OLD).replace(
tzinfo=UTC
)
mock_fyta_connector.login.side_effect = exception
await setup_platform(hass, mock_config_entry, [Platform.SENSOR])
await hass.async_block_till_done()
assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR
async def test_raise_config_entry_not_ready_when_offline(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_fyta_connector: AsyncMock,
) -> None:
"""Config entry state is SETUP_RETRY when FYTA is offline."""
mock_fyta_connector.update_all_plants.side_effect = FytaConnectionError
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_init: AsyncMock,
mock_fyta_connector: AsyncMock,
) -> None:
"""Test successful migration of entry data."""
entry = MockConfigEntry(
domain=DOMAIN,
domain=FYTA_DOMAIN,
title=USERNAME,
data={
CONF_USERNAME: USERNAME,
@ -39,4 +112,4 @@ async def test_migrate_config_entry(
assert entry.data[CONF_USERNAME] == USERNAME
assert entry.data[CONF_PASSWORD] == PASSWORD
assert entry.data[CONF_ACCESS_TOKEN] == ACCESS_TOKEN
assert entry.data[CONF_EXPIRATION] == "2024-12-31T10:00:00+00:00"
assert entry.data[CONF_EXPIRATION] == EXPIRATION