"""Unit tests for the bring integration.""" from datetime import timedelta from unittest.mock import AsyncMock from bring_api import BringAuthException, BringParseException, BringRequestException from freezegun.api import FrozenDateTimeFactory import pytest from homeassistant.components.bring import async_setup_entry from homeassistant.components.bring.const import DOMAIN from homeassistant.config_entries import ConfigEntryDisabler, ConfigEntryState from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers import device_registry as dr from .conftest import UUID from tests.common import MockConfigEntry, async_fire_time_changed async def setup_integration( hass: HomeAssistant, bring_config_entry: MockConfigEntry, ) -> None: """Mock setup of the bring integration.""" bring_config_entry.add_to_hass(hass) await hass.config_entries.async_setup(bring_config_entry.entry_id) await hass.async_block_till_done() @pytest.mark.usefixtures("mock_bring_client") async def test_load_unload( hass: HomeAssistant, bring_config_entry: MockConfigEntry, ) -> None: """Test loading and unloading of the config entry.""" await setup_integration(hass, bring_config_entry) entries = hass.config_entries.async_entries(DOMAIN) assert len(entries) == 1 assert bring_config_entry.state is ConfigEntryState.LOADED assert await hass.config_entries.async_unload(bring_config_entry.entry_id) assert bring_config_entry.state is ConfigEntryState.NOT_LOADED @pytest.mark.parametrize( ("exception", "status"), [ (BringRequestException, ConfigEntryState.SETUP_RETRY), (BringAuthException, ConfigEntryState.SETUP_ERROR), (BringParseException, ConfigEntryState.SETUP_RETRY), ], ) async def test_init_failure( hass: HomeAssistant, mock_bring_client: AsyncMock, status: ConfigEntryState, exception: Exception, bring_config_entry: MockConfigEntry, ) -> None: """Test an initialization error on integration load.""" mock_bring_client.login.side_effect = exception await setup_integration(hass, bring_config_entry) assert bring_config_entry.state == status @pytest.mark.parametrize( ("exception", "expected"), [ (BringRequestException, ConfigEntryNotReady), (BringAuthException, ConfigEntryAuthFailed), (BringParseException, ConfigEntryNotReady), ], ) async def test_init_exceptions( hass: HomeAssistant, mock_bring_client: AsyncMock, exception: Exception, expected: Exception, bring_config_entry: MockConfigEntry, ) -> None: """Test an initialization error on integration load.""" bring_config_entry.add_to_hass(hass) mock_bring_client.login.side_effect = exception with pytest.raises(expected): await async_setup_entry(hass, bring_config_entry) @pytest.mark.parametrize("exception", [BringRequestException, BringParseException]) @pytest.mark.parametrize( "bring_method", [ "load_lists", "get_list", "get_all_user_settings", ], ) async def test_config_entry_not_ready( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, exception: Exception, bring_method: str, ) -> None: """Test config entry not ready.""" getattr(mock_bring_client, bring_method).side_effect = exception bring_config_entry.add_to_hass(hass) await hass.config_entries.async_setup(bring_config_entry.entry_id) await hass.async_block_till_done() assert bring_config_entry.state is ConfigEntryState.SETUP_RETRY @pytest.mark.parametrize( ("exception", "state"), [ (None, ConfigEntryState.LOADED), (BringAuthException, ConfigEntryState.SETUP_ERROR), (BringRequestException, ConfigEntryState.SETUP_RETRY), (BringParseException, ConfigEntryState.SETUP_RETRY), ], ) async def test_config_entry_not_ready_auth_error( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, exception: Exception | None, state: ConfigEntryState, ) -> None: """Test config entry not ready from authentication error.""" mock_bring_client.load_lists.side_effect = BringAuthException mock_bring_client.retrieve_new_access_token.side_effect = exception bring_config_entry.add_to_hass(hass) await hass.config_entries.async_setup(bring_config_entry.entry_id) await hass.async_block_till_done() assert bring_config_entry.state is state @pytest.mark.usefixtures("mock_bring_client") async def test_coordinator_skips_deactivated( hass: HomeAssistant, bring_config_entry: MockConfigEntry, freezer: FrozenDateTimeFactory, mock_bring_client: AsyncMock, device_registry: dr.DeviceRegistry, ) -> None: """Test the coordinator skips fetching lists for deactivated lists.""" await setup_integration(hass, bring_config_entry) assert bring_config_entry.state is ConfigEntryState.LOADED assert mock_bring_client.get_list.await_count == 2 device = device_registry.async_get_device( identifiers={(DOMAIN, f"{UUID}_b4776778-7f6c-496e-951b-92a35d3db0dd")} ) device_registry.async_update_device(device.id, disabled_by=ConfigEntryDisabler.USER) mock_bring_client.get_list.reset_mock() freezer.tick(timedelta(seconds=90)) async_fire_time_changed(hass) await hass.async_block_till_done() assert mock_bring_client.get_list.await_count == 1