core/tests/components/analytics/test_analytics.py

336 lines
12 KiB
Python

"""The tests for the analytics ."""
from unittest.mock import AsyncMock, Mock, PropertyMock, patch
import aiohttp
import pytest
from homeassistant.components.analytics.analytics import Analytics
from homeassistant.components.analytics.const import (
ANALYTICS_ENDPOINT_URL,
ATTR_BASE,
ATTR_DIAGNOSTICS,
ATTR_PREFERENCES,
ATTR_STATISTICS,
ATTR_USAGE,
)
from homeassistant.components.api import ATTR_UUID
from homeassistant.const import ATTR_DOMAIN, __version__ as HA_VERSION
from homeassistant.loader import IntegrationNotFound
from homeassistant.setup import async_setup_component
MOCK_UUID = "abcdefg"
async def test_no_send(hass, caplog, aioclient_mock):
"""Test send when no prefrences are defined."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
with patch(
"homeassistant.components.hassio.is_hassio",
side_effect=Mock(return_value=False),
):
assert not analytics.preferences[ATTR_BASE]
await analytics.send_analytics()
assert "Nothing to submit" in caplog.text
assert len(aioclient_mock.mock_calls) == 0
async def test_load_with_supervisor_diagnostics(hass):
"""Test loading with a supervisor that has diagnostics enabled."""
analytics = Analytics(hass)
assert not analytics.preferences[ATTR_DIAGNOSTICS]
with patch(
"homeassistant.components.hassio.get_supervisor_info",
side_effect=Mock(return_value={"diagnostics": True}),
), patch(
"homeassistant.components.hassio.is_hassio",
side_effect=Mock(return_value=True),
):
await analytics.load()
assert analytics.preferences[ATTR_DIAGNOSTICS]
async def test_load_with_supervisor_without_diagnostics(hass):
"""Test loading with a supervisor that has not diagnostics enabled."""
analytics = Analytics(hass)
analytics._data[ATTR_PREFERENCES][ATTR_DIAGNOSTICS] = True
assert analytics.preferences[ATTR_DIAGNOSTICS]
with patch(
"homeassistant.components.hassio.get_supervisor_info",
side_effect=Mock(return_value={"diagnostics": False}),
), patch(
"homeassistant.components.hassio.is_hassio",
side_effect=Mock(return_value=True),
):
await analytics.load()
assert not analytics.preferences[ATTR_DIAGNOSTICS]
async def test_failed_to_send(hass, caplog, aioclient_mock):
"""Test failed to send payload."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=400)
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True})
assert analytics.preferences[ATTR_BASE]
await analytics.send_analytics()
assert "Sending analytics failed with statuscode 400" in caplog.text
async def test_failed_to_send_raises(hass, caplog, aioclient_mock):
"""Test raises when failed to send payload."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, exc=aiohttp.ClientError())
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True})
assert analytics.preferences[ATTR_BASE]
await analytics.send_analytics()
assert "Error sending analytics" in caplog.text
async def test_send_base(hass, caplog, aioclient_mock):
"""Test send base prefrences are defined."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True})
assert analytics.preferences[ATTR_BASE]
with patch("uuid.UUID.hex", new_callable=PropertyMock) as hex:
hex.return_value = MOCK_UUID
await analytics.send_analytics()
assert f"'uuid': '{MOCK_UUID}'" in caplog.text
assert f"'version': '{HA_VERSION}'" in caplog.text
assert "'installation_type':" in caplog.text
assert "'integration_count':" not in caplog.text
assert "'integrations':" not in caplog.text
async def test_send_base_with_supervisor(hass, caplog, aioclient_mock):
"""Test send base prefrences are defined."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True})
assert analytics.preferences[ATTR_BASE]
with patch(
"homeassistant.components.hassio.get_supervisor_info",
side_effect=Mock(return_value={"supported": True, "healthy": True}),
), patch(
"homeassistant.components.hassio.get_info",
side_effect=Mock(return_value={}),
), patch(
"homeassistant.components.hassio.get_host_info",
side_effect=Mock(return_value={}),
), patch(
"homeassistant.components.hassio.is_hassio",
side_effect=Mock(return_value=True),
), patch(
"uuid.UUID.hex", new_callable=PropertyMock
) as hex:
hex.return_value = MOCK_UUID
await analytics.load()
await analytics.send_analytics()
assert f"'uuid': '{MOCK_UUID}'" in caplog.text
assert f"'version': '{HA_VERSION}'" in caplog.text
assert "'supervisor': {'healthy': True, 'supported': True}}" in caplog.text
assert "'installation_type':" in caplog.text
assert "'integration_count':" not in caplog.text
assert "'integrations':" not in caplog.text
async def test_send_usage(hass, caplog, aioclient_mock):
"""Test send usage prefrences are defined."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True, ATTR_USAGE: True})
assert analytics.preferences[ATTR_BASE]
assert analytics.preferences[ATTR_USAGE]
hass.config.components = ["default_config"]
await analytics.send_analytics()
assert "'integrations': ['default_config']" in caplog.text
assert "'integration_count':" not in caplog.text
async def test_send_usage_with_supervisor(hass, caplog, aioclient_mock):
"""Test send usage with supervisor prefrences are defined."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True, ATTR_USAGE: True})
assert analytics.preferences[ATTR_BASE]
assert analytics.preferences[ATTR_USAGE]
hass.config.components = ["default_config"]
with patch(
"homeassistant.components.hassio.get_supervisor_info",
side_effect=Mock(
return_value={
"healthy": True,
"supported": True,
"addons": [{"slug": "test_addon"}],
}
),
), patch(
"homeassistant.components.hassio.get_info",
side_effect=Mock(return_value={}),
), patch(
"homeassistant.components.hassio.get_host_info",
side_effect=Mock(return_value={}),
), patch(
"homeassistant.components.hassio.async_get_addon_info",
side_effect=AsyncMock(
return_value={
"slug": "test_addon",
"protected": True,
"version": "1",
"auto_update": False,
}
),
), patch(
"homeassistant.components.hassio.is_hassio",
side_effect=Mock(return_value=True),
):
await analytics.send_analytics()
assert (
"'addons': [{'slug': 'test_addon', 'protected': True, 'version': '1', 'auto_update': False}]"
in caplog.text
)
assert "'addon_count':" not in caplog.text
async def test_send_statistics(hass, caplog, aioclient_mock):
"""Test send statistics prefrences are defined."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True, ATTR_STATISTICS: True})
assert analytics.preferences[ATTR_BASE]
assert analytics.preferences[ATTR_STATISTICS]
hass.config.components = ["default_config"]
await analytics.send_analytics()
assert (
"'state_count': 0, 'automation_count': 0, 'integration_count': 1, 'user_count': 0"
in caplog.text
)
assert "'integrations':" not in caplog.text
async def test_send_statistics_one_integration_fails(hass, caplog, aioclient_mock):
"""Test send statistics prefrences are defined."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True, ATTR_STATISTICS: True})
assert analytics.preferences[ATTR_BASE]
assert analytics.preferences[ATTR_STATISTICS]
hass.config.components = ["default_config"]
with patch(
"homeassistant.components.analytics.analytics.async_get_integration",
side_effect=IntegrationNotFound("any"),
):
await analytics.send_analytics()
post_call = aioclient_mock.mock_calls[0]
assert "uuid" in post_call[2]
assert post_call[2]["integration_count"] == 0
async def test_send_statistics_async_get_integration_unknown_exception(
hass, caplog, aioclient_mock
):
"""Test send statistics prefrences are defined."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True, ATTR_STATISTICS: True})
assert analytics.preferences[ATTR_BASE]
assert analytics.preferences[ATTR_STATISTICS]
hass.config.components = ["default_config"]
with pytest.raises(ValueError), patch(
"homeassistant.components.analytics.analytics.async_get_integration",
side_effect=ValueError,
):
await analytics.send_analytics()
async def test_send_statistics_with_supervisor(hass, caplog, aioclient_mock):
"""Test send statistics prefrences are defined."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
await analytics.save_preferences({ATTR_BASE: True, ATTR_STATISTICS: True})
assert analytics.preferences[ATTR_BASE]
assert analytics.preferences[ATTR_STATISTICS]
with patch(
"homeassistant.components.hassio.get_supervisor_info",
side_effect=Mock(
return_value={
"healthy": True,
"supported": True,
"addons": [{"slug": "test_addon"}],
}
),
), patch(
"homeassistant.components.hassio.get_info",
side_effect=Mock(return_value={}),
), patch(
"homeassistant.components.hassio.get_host_info",
side_effect=Mock(return_value={}),
), patch(
"homeassistant.components.hassio.async_get_addon_info",
side_effect=AsyncMock(
return_value={
"slug": "test_addon",
"protected": True,
"version": "1",
"auto_update": False,
}
),
), patch(
"homeassistant.components.hassio.is_hassio",
side_effect=Mock(return_value=True),
):
await analytics.send_analytics()
assert "'addon_count': 1" in caplog.text
assert "'integrations':" not in caplog.text
async def test_reusing_uuid(hass, aioclient_mock):
"""Test reusing the stored UUID."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
analytics._data[ATTR_UUID] = "NOT_MOCK_UUID"
await analytics.save_preferences({ATTR_BASE: True})
with patch("uuid.UUID.hex", new_callable=PropertyMock) as hex:
# This is not actually called but that in itself prove the test
hex.return_value = MOCK_UUID
await analytics.send_analytics()
assert analytics.uuid == "NOT_MOCK_UUID"
async def test_custom_integrations(hass, aioclient_mock):
"""Test sending custom integrations."""
aioclient_mock.post(ANALYTICS_ENDPOINT_URL, status=200)
analytics = Analytics(hass)
assert await async_setup_component(hass, "test_package", {"test_package": {}})
await analytics.save_preferences({ATTR_BASE: True, ATTR_USAGE: True})
await analytics.send_analytics()
payload = aioclient_mock.mock_calls[0][2]
assert payload["custom_integrations"][0][ATTR_DOMAIN] == "test_package"