"""Test setting up and unloading PrusaLink.""" from datetime import timedelta from unittest.mock import patch from pyprusalink.types import InvalidAuth, PrusaLinkError import pytest from homeassistant.components.prusalink import DOMAIN from homeassistant.components.prusalink.config_flow import ConfigFlow from homeassistant.config_entries import ConfigEntry, ConfigEntryState from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.helpers import issue_registry as ir from homeassistant.util.dt import utcnow from tests.common import MockConfigEntry, async_fire_time_changed pytestmark = pytest.mark.usefixtures("mock_api") async def test_unloading( hass: HomeAssistant, mock_config_entry: ConfigEntry, ) -> None: """Test unloading prusalink.""" assert await hass.config_entries.async_setup(mock_config_entry.entry_id) assert mock_config_entry.state == ConfigEntryState.LOADED assert hass.states.async_entity_ids_count() > 0 assert await hass.config_entries.async_unload(mock_config_entry.entry_id) assert mock_config_entry.state == ConfigEntryState.NOT_LOADED for state in hass.states.async_all(): assert state.state == "unavailable" @pytest.mark.parametrize("exception", [InvalidAuth, PrusaLinkError]) async def test_failed_update( hass: HomeAssistant, mock_config_entry: ConfigEntry, exception ) -> None: """Test failed update marks prusalink unavailable.""" assert await hass.config_entries.async_setup(mock_config_entry.entry_id) assert mock_config_entry.state == ConfigEntryState.LOADED with patch( "homeassistant.components.prusalink.PrusaLink.get_version", side_effect=exception, ), patch( "homeassistant.components.prusalink.PrusaLink.get_status", side_effect=exception, ), patch( "homeassistant.components.prusalink.PrusaLink.get_legacy_printer", side_effect=exception, ), patch( "homeassistant.components.prusalink.PrusaLink.get_job", side_effect=exception, ): async_fire_time_changed(hass, utcnow() + timedelta(seconds=30), fire_all=True) await hass.async_block_till_done() for state in hass.states.async_all(): assert state.state == "unavailable" async def test_migration_from_1_1_to_1_2( hass: HomeAssistant, issue_registry: ir.IssueRegistry ) -> None: """Test migrating from version 1 to 2.""" data = { CONF_HOST: "http://prusaxl.local", CONF_API_KEY: "api-key", } entry = MockConfigEntry( domain=DOMAIN, data=data, version=1, ) entry.add_to_hass(hass) assert await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() config_entries = hass.config_entries.async_entries(DOMAIN) # Ensure that we have username, password after migration assert len(config_entries) == 1 assert config_entries[0].data == { **data, CONF_USERNAME: "maker", CONF_PASSWORD: "api-key", } # Make sure that we don't have any issues assert len(issue_registry.issues) == 0 async def test_migration_from_1_1_to_1_2_outdated_firmware( hass: HomeAssistant, issue_registry: ir.IssueRegistry ) -> None: """Test migrating from version 1.1 to 1.2.""" entry = MockConfigEntry( domain=DOMAIN, data={ CONF_HOST: "http://prusaxl.local", CONF_API_KEY: "api-key", }, version=1, ) entry.add_to_hass(hass) with patch( "pyprusalink.PrusaLink.get_info", side_effect=InvalidAuth, # Simulate firmware update required ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state == ConfigEntryState.SETUP_ERROR assert entry.minor_version == 1 assert (DOMAIN, "firmware_5_1_required") in issue_registry.issues # Reloading the integration with a working API (e.g. User updated firmware) await hass.config_entries.async_reload(entry.entry_id) await hass.async_block_till_done() # Integration should be running now, the issue should be gone assert entry.state == ConfigEntryState.LOADED assert entry.minor_version == 2 assert (DOMAIN, "firmware_5_1_required") not in issue_registry.issues async def test_migration_fails_on_future_version( hass: HomeAssistant, issue_registry: ir.IssueRegistry ) -> None: """Test migrating fails on a version higher than the current one.""" entry = MockConfigEntry( domain=DOMAIN, data={}, version=ConfigFlow.VERSION + 1, ) entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state == ConfigEntryState.MIGRATION_ERROR