"""Test the habitica module.""" import datetime import logging from unittest.mock import AsyncMock from aiohttp import ClientError from freezegun.api import FrozenDateTimeFactory from habiticalib import HabiticaUserResponse import pytest from homeassistant.components.habitica.const import DOMAIN from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr from .conftest import ( ERROR_BAD_REQUEST, ERROR_NOT_AUTHORIZED, ERROR_NOT_FOUND, ERROR_TOO_MANY_REQUESTS, ) from tests.common import MockConfigEntry, async_fire_time_changed, async_load_fixture @pytest.mark.usefixtures("habitica") async def test_entry_setup_unload( hass: HomeAssistant, config_entry: MockConfigEntry ) -> None: """Test integration setup and unload.""" config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.LOADED assert await hass.config_entries.async_unload(config_entry.entry_id) assert config_entry.state is ConfigEntryState.NOT_LOADED @pytest.mark.parametrize( ("exception"), [ERROR_BAD_REQUEST, ERROR_TOO_MANY_REQUESTS, ClientError], ids=[ "BadRequestError", "TooManyRequestsError", "ClientError", ], ) async def test_config_entry_not_ready( hass: HomeAssistant, config_entry: MockConfigEntry, habitica: AsyncMock, exception: Exception, ) -> None: """Test config entry not ready.""" habitica.get_user.side_effect = exception config_entry.add_to_hass(hass) 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_config_entry_auth_failed( hass: HomeAssistant, config_entry: MockConfigEntry, habitica: AsyncMock ) -> None: """Test config entry auth failed setup error.""" habitica.get_user.side_effect = ERROR_NOT_AUTHORIZED config_entry.add_to_hass(hass) await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.SETUP_ERROR flows = hass.config_entries.flow.async_progress() assert len(flows) == 1 flow = flows[0] assert flow.get("step_id") == "reauth_confirm" assert flow.get("handler") == DOMAIN assert "context" in flow assert flow["context"].get("source") == SOURCE_REAUTH assert flow["context"].get("entry_id") == config_entry.entry_id @pytest.mark.parametrize("exception", [ERROR_NOT_FOUND, ClientError]) async def test_coordinator_update_failed( hass: HomeAssistant, config_entry: MockConfigEntry, habitica: AsyncMock, exception: Exception, ) -> None: """Test coordinator update failed.""" habitica.get_tasks.side_effect = exception config_entry.add_to_hass(hass) 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_coordinator_rate_limited( hass: HomeAssistant, config_entry: MockConfigEntry, habitica: AsyncMock, caplog: pytest.LogCaptureFixture, freezer: FrozenDateTimeFactory, ) -> None: """Test coordinator when rate limited.""" config_entry.add_to_hass(hass) await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.LOADED habitica.get_user.side_effect = ERROR_TOO_MANY_REQUESTS with caplog.at_level(logging.DEBUG): freezer.tick(datetime.timedelta(seconds=60)) async_fire_time_changed(hass) await hass.async_block_till_done() assert "Rate limit exceeded, will try again later" in caplog.text async def test_remove_party_and_reload( hass: HomeAssistant, config_entry: MockConfigEntry, habitica: AsyncMock, freezer: FrozenDateTimeFactory, device_registry: dr.DeviceRegistry, ) -> None: """Test we leave the party and device is removed.""" group_id = "1e87097c-4c03-4f8c-a475-67cc7da7f409" config_entry.add_to_hass(hass) await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.LOADED assert ( device_registry.async_get_device( {(DOMAIN, f"{config_entry.unique_id}_{group_id}")} ) is not None ) habitica.get_user.return_value = HabiticaUserResponse.from_json( await async_load_fixture(hass, "user_no_party.json", DOMAIN) ) freezer.tick(datetime.timedelta(seconds=60)) async_fire_time_changed(hass) await hass.async_block_till_done() assert ( device_registry.async_get_device( {(DOMAIN, f"{config_entry.unique_id}_{group_id}")} ) is None )