mirror of
https://github.com/home-assistant/core.git
synced 2025-11-15 14:00:24 +00:00
157 lines
5.5 KiB
Python
157 lines
5.5 KiB
Python
"""ESPHome set up tests."""
|
|
|
|
from unittest.mock import AsyncMock
|
|
|
|
from aioesphomeapi import APIConnectionError
|
|
import pytest
|
|
|
|
from homeassistant.components.esphome import DOMAIN
|
|
from homeassistant.components.esphome.const import CONF_NOISE_PSK
|
|
from homeassistant.components.esphome.encryption_key_storage import (
|
|
async_get_encryption_key_storage,
|
|
)
|
|
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from tests.common import MockConfigEntry
|
|
|
|
|
|
@pytest.mark.usefixtures("mock_client", "mock_zeroconf")
|
|
async def test_remove_entry(hass: HomeAssistant) -> None:
|
|
"""Test we can remove an entry without error."""
|
|
entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={CONF_HOST: "test.local", CONF_PORT: 6053, CONF_PASSWORD: ""},
|
|
unique_id="mock-config-name",
|
|
)
|
|
entry.add_to_hass(hass)
|
|
await hass.config_entries.async_setup(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
assert await hass.config_entries.async_remove(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
@pytest.mark.usefixtures("mock_zeroconf")
|
|
async def test_remove_entry_clears_dynamic_encryption_key(
|
|
hass: HomeAssistant,
|
|
mock_client,
|
|
mock_config_entry: MockConfigEntry,
|
|
) -> None:
|
|
"""Test that removing an entry clears the dynamic encryption key from device and storage."""
|
|
# Store the encryption key to simulate it was dynamically generated
|
|
storage = await async_get_encryption_key_storage(hass)
|
|
await storage.async_store_key(
|
|
mock_config_entry.unique_id, mock_config_entry.data[CONF_NOISE_PSK]
|
|
)
|
|
assert (
|
|
await storage.async_get_key(mock_config_entry.unique_id)
|
|
== mock_config_entry.data[CONF_NOISE_PSK]
|
|
)
|
|
|
|
mock_client.noise_encryption_set_key = AsyncMock(return_value=True)
|
|
|
|
assert await hass.config_entries.async_remove(mock_config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
mock_client.connect.assert_called_once()
|
|
mock_client.noise_encryption_set_key.assert_called_once_with(b"")
|
|
mock_client.disconnect.assert_called_once()
|
|
|
|
assert await storage.async_get_key(mock_config_entry.unique_id) is None
|
|
|
|
|
|
@pytest.mark.usefixtures("mock_zeroconf")
|
|
async def test_remove_entry_no_noise_psk(hass: HomeAssistant, mock_client) -> None:
|
|
"""Test that removing an entry without noise_psk does not attempt to clear encryption key."""
|
|
mock_config_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
data={
|
|
CONF_HOST: "test.local",
|
|
CONF_PORT: 6053,
|
|
# No CONF_NOISE_PSK
|
|
},
|
|
unique_id="11:22:33:44:55:aa",
|
|
)
|
|
mock_config_entry.add_to_hass(hass)
|
|
|
|
mock_client.noise_encryption_set_key = AsyncMock(return_value=True)
|
|
|
|
assert await hass.config_entries.async_remove(mock_config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
mock_client.noise_encryption_set_key.assert_not_called()
|
|
|
|
|
|
@pytest.mark.usefixtures("mock_zeroconf")
|
|
async def test_remove_entry_user_provided_key(
|
|
hass: HomeAssistant,
|
|
mock_client,
|
|
mock_config_entry: MockConfigEntry,
|
|
) -> None:
|
|
"""Test that removing an entry with user-provided key does not clear it."""
|
|
# Do not store the key in storage - simulates user-provided key
|
|
storage = await async_get_encryption_key_storage(hass)
|
|
assert await storage.async_get_key(mock_config_entry.unique_id) is None
|
|
|
|
mock_client.noise_encryption_set_key = AsyncMock(return_value=True)
|
|
|
|
assert await hass.config_entries.async_remove(mock_config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
mock_client.noise_encryption_set_key.assert_not_called()
|
|
|
|
|
|
@pytest.mark.usefixtures("mock_zeroconf")
|
|
async def test_remove_entry_device_rejects_key_removal(
|
|
hass: HomeAssistant,
|
|
mock_client,
|
|
mock_config_entry: MockConfigEntry,
|
|
) -> None:
|
|
"""Test that when device rejects key removal, key remains in storage."""
|
|
# Store the encryption key to simulate it was dynamically generated
|
|
storage = await async_get_encryption_key_storage(hass)
|
|
await storage.async_store_key(
|
|
mock_config_entry.unique_id, mock_config_entry.data[CONF_NOISE_PSK]
|
|
)
|
|
|
|
mock_client.noise_encryption_set_key = AsyncMock(return_value=False)
|
|
|
|
assert await hass.config_entries.async_remove(mock_config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
mock_client.connect.assert_called_once()
|
|
mock_client.noise_encryption_set_key.assert_called_once_with(b"")
|
|
mock_client.disconnect.assert_called_once()
|
|
|
|
assert (
|
|
await storage.async_get_key(mock_config_entry.unique_id)
|
|
== mock_config_entry.data[CONF_NOISE_PSK]
|
|
)
|
|
|
|
|
|
@pytest.mark.usefixtures("mock_zeroconf")
|
|
async def test_remove_entry_connection_error(
|
|
hass: HomeAssistant,
|
|
mock_client,
|
|
mock_config_entry: MockConfigEntry,
|
|
) -> None:
|
|
"""Test that connection error during key clearing does not remove key from storage."""
|
|
# Store the encryption key to simulate it was dynamically generated
|
|
storage = await async_get_encryption_key_storage(hass)
|
|
await storage.async_store_key(
|
|
mock_config_entry.unique_id, mock_config_entry.data[CONF_NOISE_PSK]
|
|
)
|
|
|
|
mock_client.connect = AsyncMock(side_effect=APIConnectionError("Connection failed"))
|
|
|
|
assert await hass.config_entries.async_remove(mock_config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
mock_client.connect.assert_called_once()
|
|
mock_client.disconnect.assert_called_once()
|
|
|
|
assert (
|
|
await storage.async_get_key(mock_config_entry.unique_id)
|
|
== mock_config_entry.data[CONF_NOISE_PSK]
|
|
)
|