diff --git a/homeassistant/components/opensky/config_flow.py b/homeassistant/components/opensky/config_flow.py index 863b6050616..3cfd1ad30a0 100644 --- a/homeassistant/components/opensky/config_flow.py +++ b/homeassistant/components/opensky/config_flow.py @@ -100,19 +100,17 @@ class OpenSkyOptionsFlowHandler(OptionsFlowWithConfigEntry): if user_input[CONF_CONTRIBUTING_USER] and not authentication: errors["base"] = "no_authentication" if authentication and not errors: - async with OpenSky( - session=async_get_clientsession(self.hass) - ) as opensky: - try: - await opensky.authenticate( - BasicAuth( - login=user_input[CONF_USERNAME], - password=user_input[CONF_PASSWORD], - ), - contributing_user=user_input[CONF_CONTRIBUTING_USER], - ) - except OpenSkyUnauthenticatedError: - errors["base"] = "invalid_auth" + opensky = OpenSky(session=async_get_clientsession(self.hass)) + try: + await opensky.authenticate( + BasicAuth( + login=user_input[CONF_USERNAME], + password=user_input[CONF_PASSWORD], + ), + contributing_user=user_input[CONF_CONTRIBUTING_USER], + ) + except OpenSkyUnauthenticatedError: + errors["base"] = "invalid_auth" if not errors: return self.async_create_entry( title=self.options.get(CONF_NAME, "OpenSky"), diff --git a/tests/components/opensky/__init__.py b/tests/components/opensky/__init__.py index 668416c6dcb..ab23de9937b 100644 --- a/tests/components/opensky/__init__.py +++ b/tests/components/opensky/__init__.py @@ -1,20 +1,12 @@ """Opensky tests.""" -from unittest.mock import patch +from homeassistant.core import HomeAssistant -from python_opensky import StatesResponse - -from tests.common import load_json_object_fixture +from tests.common import MockConfigEntry -def patch_setup_entry() -> bool: - """Patch interface.""" - return patch( - "homeassistant.components.opensky.async_setup_entry", return_value=True - ) - - -def get_states_response_fixture(fixture: str) -> StatesResponse: - """Return the states response from json.""" - states_json = load_json_object_fixture(fixture) - return StatesResponse.from_api(states_json) +async def setup_integration(hass: HomeAssistant, config_entry: MockConfigEntry) -> None: + """Set up the integration.""" + config_entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() diff --git a/tests/components/opensky/conftest.py b/tests/components/opensky/conftest.py index 835543b632f..665fdd90e69 100644 --- a/tests/components/opensky/conftest.py +++ b/tests/components/opensky/conftest.py @@ -1,9 +1,10 @@ """Configure tests for the OpenSky integration.""" -from collections.abc import Awaitable, Callable -from unittest.mock import patch +from collections.abc import Generator +from unittest.mock import AsyncMock, patch import pytest +from python_opensky import StatesResponse from homeassistant.components.opensky.const import ( CONF_ALTITUDE, @@ -17,14 +18,18 @@ from homeassistant.const import ( CONF_RADIUS, CONF_USERNAME, ) -from homeassistant.core import HomeAssistant -from homeassistant.setup import async_setup_component -from . import get_states_response_fixture +from tests.common import MockConfigEntry, load_json_object_fixture -from tests.common import MockConfigEntry -ComponentSetup = Callable[[MockConfigEntry], Awaitable[None]] +@pytest.fixture +def mock_setup_entry() -> Generator[AsyncMock, None, None]: + """Override async_setup_entry.""" + with patch( + "homeassistant.components.opensky.async_setup_entry", + return_value=True, + ) as mock_setup_entry: + yield mock_setup_entry @pytest.fixture(name="config_entry") @@ -81,19 +86,22 @@ def mock_config_entry_authenticated() -> MockConfigEntry: ) -@pytest.fixture(name="setup_integration") -async def mock_setup_integration( - hass: HomeAssistant, -) -> Callable[[MockConfigEntry], Awaitable[None]]: - """Fixture for setting up the component.""" - - async def func(mock_config_entry: MockConfigEntry) -> None: - mock_config_entry.add_to_hass(hass) - with patch( - "python_opensky.OpenSky.get_states", - return_value=get_states_response_fixture("opensky/states.json"), - ): - assert await async_setup_component(hass, DOMAIN, {}) - await hass.async_block_till_done() - - return func +@pytest.fixture +async def opensky_client() -> Generator[AsyncMock, None, None]: + """Mock the OpenSky client.""" + with ( + patch( + "homeassistant.components.opensky.OpenSky", + autospec=True, + ) as mock_client, + patch( + "homeassistant.components.opensky.config_flow.OpenSky", + new=mock_client, + ), + ): + client = mock_client.return_value + client.get_states.return_value = StatesResponse.from_api( + load_json_object_fixture("states.json", DOMAIN) + ) + client.is_authenticated = False + yield client diff --git a/tests/components/opensky/test_config_flow.py b/tests/components/opensky/test_config_flow.py index c3ae876d36e..8168511a16c 100644 --- a/tests/components/opensky/test_config_flow.py +++ b/tests/components/opensky/test_config_flow.py @@ -1,7 +1,7 @@ """Test OpenSky config flow.""" from typing import Any -from unittest.mock import patch +from unittest.mock import AsyncMock import pytest from python_opensky.exceptions import OpenSkyUnauthenticatedError @@ -23,39 +23,36 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType -from . import get_states_response_fixture, patch_setup_entry -from .conftest import ComponentSetup - from tests.common import MockConfigEntry +from tests.components.opensky import setup_integration -async def test_full_user_flow(hass: HomeAssistant) -> None: +async def test_full_user_flow(hass: HomeAssistant, mock_setup_entry) -> None: """Test the full user configuration flow.""" - with patch_setup_entry(): - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_USER}, - ) + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": SOURCE_USER}, + ) - result = await hass.config_entries.flow.async_configure( - result["flow_id"], - user_input={ - CONF_RADIUS: 10, - CONF_LATITUDE: 0.0, - CONF_LONGITUDE: 0.0, - CONF_ALTITUDE: 0, - }, - ) - assert result["type"] == FlowResultType.CREATE_ENTRY - assert result["title"] == "OpenSky" - assert result["data"] == { + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={ + CONF_RADIUS: 10, CONF_LATITUDE: 0.0, CONF_LONGITUDE: 0.0, - } - assert result["options"] == { - CONF_ALTITUDE: 0.0, - CONF_RADIUS: 10.0, - } + CONF_ALTITUDE: 0, + }, + ) + assert result["type"] == FlowResultType.CREATE_ENTRY + assert result["title"] == "OpenSky" + assert result["data"] == { + CONF_LATITUDE: 0.0, + CONF_LONGITUDE: 0.0, + } + assert result["options"] == { + CONF_ALTITUDE: 0.0, + CONF_RADIUS: 10.0, + } @pytest.mark.parametrize( @@ -79,92 +76,77 @@ async def test_full_user_flow(hass: HomeAssistant) -> None: ) async def test_options_flow_failures( hass: HomeAssistant, - setup_integration: ComponentSetup, + mock_setup_entry: AsyncMock, + opensky_client: AsyncMock, config_entry: MockConfigEntry, user_input: dict[str, Any], error: str, ) -> None: """Test load and unload entry.""" - await setup_integration(config_entry) - entry = hass.config_entries.async_entries(DOMAIN)[0] - with patch( - "python_opensky.OpenSky.authenticate", - side_effect=OpenSkyUnauthenticatedError(), - ): - result = await hass.config_entries.options.async_init(entry.entry_id) - await hass.async_block_till_done() + await setup_integration(hass, config_entry) - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "init" + opensky_client.authenticate.side_effect = OpenSkyUnauthenticatedError + result = await hass.config_entries.options.async_init(config_entry.entry_id) + await hass.async_block_till_done() - result = await hass.config_entries.options.async_configure( - result["flow_id"], - user_input={CONF_RADIUS: 10000, **user_input}, - ) - await hass.async_block_till_done() + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "init" - assert result["type"] == data_entry_flow.FlowResultType.FORM - assert result["step_id"] == "init" - assert result["errors"]["base"] == error - with ( - patch("python_opensky.OpenSky.authenticate"), - patch( - "python_opensky.OpenSky.get_states", - return_value=get_states_response_fixture("opensky/states_1.json"), - ), - ): - result = await hass.config_entries.options.async_configure( - result["flow_id"], - user_input={ - CONF_RADIUS: 10000, - CONF_USERNAME: "homeassistant", - CONF_PASSWORD: "secret", - CONF_CONTRIBUTING_USER: True, - }, - ) - await hass.async_block_till_done() + result = await hass.config_entries.options.async_configure( + result["flow_id"], + user_input={CONF_RADIUS: 10000, **user_input}, + ) + await hass.async_block_till_done() - assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY - assert result["data"] == { + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "init" + assert result["errors"]["base"] == error + opensky_client.authenticate.side_effect = None + result = await hass.config_entries.options.async_configure( + result["flow_id"], + user_input={ CONF_RADIUS: 10000, CONF_USERNAME: "homeassistant", CONF_PASSWORD: "secret", CONF_CONTRIBUTING_USER: True, - } + }, + ) + await hass.async_block_till_done() + + assert result["type"] == FlowResultType.CREATE_ENTRY + assert result["data"] == { + CONF_RADIUS: 10000, + CONF_USERNAME: "homeassistant", + CONF_PASSWORD: "secret", + CONF_CONTRIBUTING_USER: True, + } async def test_options_flow( hass: HomeAssistant, - setup_integration: ComponentSetup, + mock_setup_entry: AsyncMock, + opensky_client: AsyncMock, config_entry: MockConfigEntry, ) -> None: """Test options flow.""" - await setup_integration(config_entry) - entry = hass.config_entries.async_entries(DOMAIN)[0] - result = await hass.config_entries.options.async_init(entry.entry_id) + await setup_integration(hass, config_entry) + result = await hass.config_entries.options.async_init(config_entry.entry_id) await hass.async_block_till_done() - with ( - patch("python_opensky.OpenSky.authenticate"), - patch( - "python_opensky.OpenSky.get_states", - return_value=get_states_response_fixture("opensky/states_1.json"), - ), - ): - result = await hass.config_entries.options.async_configure( - result["flow_id"], - user_input={ - CONF_RADIUS: 10000, - CONF_USERNAME: "homeassistant", - CONF_PASSWORD: "secret", - CONF_CONTRIBUTING_USER: True, - }, - ) - await hass.async_block_till_done() - - assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY - assert result["data"] == { + result = await hass.config_entries.options.async_configure( + result["flow_id"], + user_input={ CONF_RADIUS: 10000, CONF_USERNAME: "homeassistant", CONF_PASSWORD: "secret", CONF_CONTRIBUTING_USER: True, - } + }, + ) + await hass.async_block_till_done() + + assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY + assert result["data"] == { + CONF_RADIUS: 10000, + CONF_USERNAME: "homeassistant", + CONF_PASSWORD: "secret", + CONF_CONTRIBUTING_USER: True, + } diff --git a/tests/components/opensky/test_init.py b/tests/components/opensky/test_init.py index a9e1668d026..f5acf7479a2 100644 --- a/tests/components/opensky/test_init.py +++ b/tests/components/opensky/test_init.py @@ -2,67 +2,59 @@ from __future__ import annotations -from unittest.mock import patch +from unittest.mock import AsyncMock from python_opensky import OpenSkyError from python_opensky.exceptions import OpenSkyUnauthenticatedError -from homeassistant.components.opensky.const import DOMAIN from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant -from homeassistant.setup import async_setup_component - -from .conftest import ComponentSetup from tests.common import MockConfigEntry +from tests.components.opensky import setup_integration async def test_load_unload_entry( hass: HomeAssistant, - setup_integration: ComponentSetup, config_entry: MockConfigEntry, + opensky_client: AsyncMock, ) -> None: """Test load and unload entry.""" - await setup_integration(config_entry) - entry = hass.config_entries.async_entries(DOMAIN)[0] + await setup_integration(hass, config_entry) - state = hass.states.get("sensor.opensky") - assert state + assert config_entry.state is ConfigEntryState.LOADED - await hass.config_entries.async_remove(entry.entry_id) + await hass.config_entries.async_unload(config_entry.entry_id) await hass.async_block_till_done() - state = hass.states.get("sensor.opensky") - assert not state + assert config_entry.state is ConfigEntryState.NOT_LOADED async def test_load_entry_failure( hass: HomeAssistant, config_entry: MockConfigEntry, + opensky_client: AsyncMock, ) -> None: """Test failure while loading.""" + opensky_client.get_states.side_effect = OpenSkyError() config_entry.add_to_hass(hass) - with patch( - "python_opensky.OpenSky.get_states", - side_effect=OpenSkyError(), - ): - assert await async_setup_component(hass, DOMAIN, {}) - await hass.async_block_till_done() - entry = hass.config_entries.async_entries(DOMAIN)[0] - assert entry.state == ConfigEntryState.SETUP_RETRY + assert not await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.SETUP_RETRY async def test_load_entry_authentication_failure( hass: HomeAssistant, config_entry_authenticated: MockConfigEntry, + opensky_client: AsyncMock, ) -> None: """Test auth failure while loading.""" + opensky_client.authenticate.side_effect = OpenSkyUnauthenticatedError() config_entry_authenticated.add_to_hass(hass) - with patch( - "python_opensky.OpenSky.authenticate", - side_effect=OpenSkyUnauthenticatedError(), - ): - assert await async_setup_component(hass, DOMAIN, {}) - await hass.async_block_till_done() - entry = hass.config_entries.async_entries(DOMAIN)[0] - assert entry.state == ConfigEntryState.SETUP_RETRY + assert not await hass.config_entries.async_setup( + config_entry_authenticated.entry_id + ) + await hass.async_block_till_done() + + assert config_entry_authenticated.state is ConfigEntryState.SETUP_RETRY diff --git a/tests/components/opensky/test_sensor.py b/tests/components/opensky/test_sensor.py index df4faaa3e4a..801980ec5b9 100644 --- a/tests/components/opensky/test_sensor.py +++ b/tests/components/opensky/test_sensor.py @@ -1,31 +1,35 @@ """OpenSky sensor tests.""" from datetime import timedelta -from unittest.mock import patch +from unittest.mock import AsyncMock from freezegun.api import FrozenDateTimeFactory +from python_opensky import StatesResponse from syrupy import SnapshotAssertion from homeassistant.components.opensky.const import ( + DOMAIN, EVENT_OPENSKY_ENTRY, EVENT_OPENSKY_EXIT, ) from homeassistant.core import Event, HomeAssistant -from . import get_states_response_fixture -from .conftest import ComponentSetup - -from tests.common import MockConfigEntry, async_fire_time_changed +from tests.common import ( + MockConfigEntry, + async_fire_time_changed, + load_json_object_fixture, +) +from tests.components.opensky import setup_integration async def test_sensor( hass: HomeAssistant, config_entry: MockConfigEntry, - setup_integration: ComponentSetup, snapshot: SnapshotAssertion, + opensky_client: AsyncMock, ): """Test setup sensor.""" - await setup_integration(config_entry) + await setup_integration(hass, config_entry) state = hass.states.get("sensor.opensky") assert state == snapshot @@ -42,11 +46,11 @@ async def test_sensor( async def test_sensor_altitude( hass: HomeAssistant, config_entry_altitude: MockConfigEntry, - setup_integration: ComponentSetup, + opensky_client: AsyncMock, snapshot: SnapshotAssertion, ): """Test setup sensor with a set altitude.""" - await setup_integration(config_entry_altitude) + await setup_integration(hass, config_entry_altitude) state = hass.states.get("sensor.opensky") assert state == snapshot @@ -55,12 +59,12 @@ async def test_sensor_altitude( async def test_sensor_updating( hass: HomeAssistant, config_entry: MockConfigEntry, + opensky_client: AsyncMock, freezer: FrozenDateTimeFactory, - setup_integration: ComponentSetup, snapshot: SnapshotAssertion, ): """Test updating sensor.""" - await setup_integration(config_entry) + await setup_integration(hass, config_entry) events = [] @@ -77,13 +81,11 @@ async def test_sensor_updating( assert events == snapshot - with patch( - "python_opensky.OpenSky.get_states", - return_value=get_states_response_fixture("opensky/states_1.json"), - ): - await skip_time_and_check_events() - with patch( - "python_opensky.OpenSky.get_states", - return_value=get_states_response_fixture("opensky/states.json"), - ): - await skip_time_and_check_events() + opensky_client.get_states.return_value = StatesResponse.from_api( + load_json_object_fixture("states_1.json", DOMAIN) + ) + await skip_time_and_check_events() + opensky_client.get_states.return_value = StatesResponse.from_api( + load_json_object_fixture("states.json", DOMAIN) + ) + await skip_time_and_check_events()