Add base integration tests to Luftdaten (#62594)

This commit is contained in:
Franck Nijhof 2021-12-23 07:25:26 +01:00 committed by GitHub
parent ef5e5c3f96
commit 6ef7539a31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 170 additions and 46 deletions

View file

@ -607,7 +607,6 @@ omit =
homeassistant/components/lookin/climate.py homeassistant/components/lookin/climate.py
homeassistant/components/lookin/media_player.py homeassistant/components/lookin/media_player.py
homeassistant/components/luci/device_tracker.py homeassistant/components/luci/device_tracker.py
homeassistant/components/luftdaten/__init__.py
homeassistant/components/luftdaten/sensor.py homeassistant/components/luftdaten/sensor.py
homeassistant/components/lupusec/* homeassistant/components/lupusec/*
homeassistant/components/lutron/* homeassistant/components/lutron/*

View file

@ -28,7 +28,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# For backwards compat, set unique ID # For backwards compat, set unique ID
if entry.unique_id is None: if entry.unique_id is None:
hass.config_entries.async_update_entry( hass.config_entries.async_update_entry(
entry, unique_id=entry.data[CONF_SENSOR_ID] entry, unique_id=str(entry.data[CONF_SENSOR_ID])
) )
luftdaten = Luftdaten(entry.data[CONF_SENSOR_ID]) luftdaten = Luftdaten(entry.data[CONF_SENSOR_ID])

View file

@ -2,12 +2,13 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Generator from collections.abc import Generator
from unittest.mock import patch from unittest.mock import MagicMock, patch
import pytest import pytest
from homeassistant.components.luftdaten import DOMAIN from homeassistant.components.luftdaten.const import CONF_SENSOR_ID, DOMAIN
from homeassistant.components.luftdaten.const import CONF_SENSOR_ID from homeassistant.const import CONF_SHOW_ON_MAP
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -18,7 +19,7 @@ def mock_config_entry() -> MockConfigEntry:
return MockConfigEntry( return MockConfigEntry(
title="12345", title="12345",
domain=DOMAIN, domain=DOMAIN,
data={CONF_SENSOR_ID: 123456}, data={CONF_SENSOR_ID: 12345, CONF_SHOW_ON_MAP: True},
unique_id="12345", unique_id="12345",
) )
@ -30,3 +31,52 @@ def mock_setup_entry() -> Generator[None, None, None]:
"homeassistant.components.luftdaten.async_setup_entry", return_value=True "homeassistant.components.luftdaten.async_setup_entry", return_value=True
): ):
yield yield
@pytest.fixture
def mock_luftdaten_config_flow() -> Generator[None, MagicMock, None]:
"""Return a mocked Luftdaten client."""
with patch(
"homeassistant.components.luftdaten.config_flow.Luftdaten", autospec=True
) as luftdaten_mock:
luftdaten = luftdaten_mock.return_value
luftdaten.validate_sensor.return_value = True
yield luftdaten
@pytest.fixture
def mock_luftdaten() -> Generator[None, MagicMock, None]:
"""Return a mocked Luftdaten client."""
with patch(
"homeassistant.components.luftdaten.Luftdaten", autospec=True
) as luftdaten_mock:
luftdaten = luftdaten_mock.return_value
luftdaten.sensor_id = 12345
luftdaten.meta = {
"altitude": 123.456,
"latitude": 56.789,
"longitude": 12.345,
"sensor_id": 12345,
}
luftdaten.values = {
"humidity": 34.70,
"P1": 8.5,
"P2": 4.07,
"pressure_at_sea_level": 103102.13,
"pressure": 98545.00,
"temperature": 22.30,
}
yield luftdaten
@pytest.fixture
async def init_integration(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_luftdaten: MagicMock
) -> MockConfigEntry:
"""Set up the Luftdaten integration for testing."""
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
return mock_config_entry

View file

@ -1,5 +1,5 @@
"""Define tests for the Luftdaten config flow.""" """Define tests for the Luftdaten config flow."""
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock
from luftdaten.exceptions import LuftdatenConnectionError from luftdaten.exceptions import LuftdatenConnectionError
@ -40,7 +40,9 @@ async def test_duplicate_error(
assert result2.get("reason") == "already_configured" assert result2.get("reason") == "already_configured"
async def test_communication_error(hass: HomeAssistant) -> None: async def test_communication_error(
hass: HomeAssistant, mock_luftdaten_config_flow: MagicMock
) -> None:
"""Test that no sensor is added while unable to communicate with API.""" """Test that no sensor is added while unable to communicate with API."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER} DOMAIN, context={"source": SOURCE_USER}
@ -50,7 +52,7 @@ async def test_communication_error(hass: HomeAssistant) -> None:
assert result.get("step_id") == SOURCE_USER assert result.get("step_id") == SOURCE_USER
assert "flow_id" in result assert "flow_id" in result
with patch("luftdaten.Luftdaten.get_data", side_effect=LuftdatenConnectionError): mock_luftdaten_config_flow.get_data.side_effect = LuftdatenConnectionError
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
user_input={CONF_SENSOR_ID: 12345}, user_input={CONF_SENSOR_ID: 12345},
@ -59,10 +61,9 @@ async def test_communication_error(hass: HomeAssistant) -> None:
assert result2.get("type") == RESULT_TYPE_FORM assert result2.get("type") == RESULT_TYPE_FORM
assert result2.get("step_id") == SOURCE_USER assert result2.get("step_id") == SOURCE_USER
assert result2.get("errors") == {CONF_SENSOR_ID: "cannot_connect"} assert result2.get("errors") == {CONF_SENSOR_ID: "cannot_connect"}
assert "flow_id" in result2
with patch("luftdaten.Luftdaten.get_data"), patch( mock_luftdaten_config_flow.get_data.side_effect = None
"luftdaten.Luftdaten.validate_sensor", return_value=True
):
result3 = await hass.config_entries.flow.async_configure( result3 = await hass.config_entries.flow.async_configure(
result2["flow_id"], result2["flow_id"],
user_input={CONF_SENSOR_ID: 12345}, user_input={CONF_SENSOR_ID: 12345},
@ -76,7 +77,9 @@ async def test_communication_error(hass: HomeAssistant) -> None:
} }
async def test_invalid_sensor(hass: HomeAssistant) -> None: async def test_invalid_sensor(
hass: HomeAssistant, mock_luftdaten_config_flow: MagicMock
) -> None:
"""Test that an invalid sensor throws an error.""" """Test that an invalid sensor throws an error."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER} DOMAIN, context={"source": SOURCE_USER}
@ -86,12 +89,10 @@ async def test_invalid_sensor(hass: HomeAssistant) -> None:
assert result.get("step_id") == SOURCE_USER assert result.get("step_id") == SOURCE_USER
assert "flow_id" in result assert "flow_id" in result
with patch("luftdaten.Luftdaten.get_data", return_value=False), patch( mock_luftdaten_config_flow.validate_sensor.return_value = False
"luftdaten.Luftdaten.validate_sensor", return_value=False
):
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
user_input={CONF_SENSOR_ID: 12345}, user_input={CONF_SENSOR_ID: 11111},
) )
assert result2.get("type") == RESULT_TYPE_FORM assert result2.get("type") == RESULT_TYPE_FORM
@ -99,9 +100,7 @@ async def test_invalid_sensor(hass: HomeAssistant) -> None:
assert result2.get("errors") == {CONF_SENSOR_ID: "invalid_sensor"} assert result2.get("errors") == {CONF_SENSOR_ID: "invalid_sensor"}
assert "flow_id" in result2 assert "flow_id" in result2
with patch("luftdaten.Luftdaten.get_data"), patch( mock_luftdaten_config_flow.validate_sensor.return_value = True
"luftdaten.Luftdaten.validate_sensor", return_value=True
):
result3 = await hass.config_entries.flow.async_configure( result3 = await hass.config_entries.flow.async_configure(
result2["flow_id"], result2["flow_id"],
user_input={CONF_SENSOR_ID: 12345}, user_input={CONF_SENSOR_ID: 12345},
@ -115,7 +114,11 @@ async def test_invalid_sensor(hass: HomeAssistant) -> None:
} }
async def test_step_user(hass: HomeAssistant, mock_setup_entry: MagicMock) -> None: async def test_step_user(
hass: HomeAssistant,
mock_setup_entry: MagicMock,
mock_luftdaten_config_flow: MagicMock,
) -> None:
"""Test that the user step works.""" """Test that the user step works."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER} DOMAIN, context={"source": SOURCE_USER}
@ -125,9 +128,6 @@ async def test_step_user(hass: HomeAssistant, mock_setup_entry: MagicMock) -> No
assert result.get("step_id") == SOURCE_USER assert result.get("step_id") == SOURCE_USER
assert "flow_id" in result assert "flow_id" in result
with patch("luftdaten.Luftdaten.get_data", return_value=True), patch(
"luftdaten.Luftdaten.validate_sensor", return_value=True
):
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"],
user_input={ user_input={

View file

@ -0,0 +1,75 @@
"""Tests for the Luftdaten integration."""
from unittest.mock import AsyncMock, MagicMock, patch
from luftdaten.exceptions import LuftdatenError
from homeassistant.components.luftdaten.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
async def test_load_unload_config_entry(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_luftdaten: AsyncMock,
) -> None:
"""Test the Luftdaten configuration entry loading/unloading."""
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.state is ConfigEntryState.LOADED
await hass.config_entries.async_unload(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert not hass.data.get(DOMAIN)
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
@patch(
"homeassistant.components.luftdaten.Luftdaten.get_data",
side_effect=LuftdatenError,
)
async def test_config_entry_not_ready(
mock_get_data: MagicMock,
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Luftdaten configuration entry not ready."""
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_get_data.call_count == 1
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_config_entry_not_ready_no_data(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_luftdaten: MagicMock,
) -> None:
"""Test the Luftdaten configuration entry not ready."""
mock_luftdaten.values = {}
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
mock_luftdaten.get_data.assert_called()
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_setting_unique_id(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_luftdaten: MagicMock
) -> None:
"""Test we set unique ID if not set yet."""
mock_config_entry.unique_id = None
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.unique_id == "12345"