core/tests/components/updater/test_init.py

282 lines
9.9 KiB
Python

"""The tests for the Updater component."""
import asyncio
from datetime import timedelta
from unittest.mock import Mock, patch
import pytest
from homeassistant.components import updater
from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util
from tests.common import (
MockDependency,
async_fire_time_changed,
mock_component,
mock_coro,
)
NEW_VERSION = "10000.0"
MOCK_VERSION = "10.0"
MOCK_DEV_VERSION = "10.0.dev0"
MOCK_HUUID = "abcdefg"
MOCK_RESPONSE = {"version": "0.15", "release-notes": "https://home-assistant.io"}
MOCK_CONFIG = {updater.DOMAIN: {"reporting": True}}
RELEASE_NOTES = "test release notes"
@pytest.fixture(autouse=True)
def mock_distro():
"""Mock distro dep."""
with MockDependency("distro"):
yield
@pytest.fixture(name="mock_get_newest_version")
def mock_get_newest_version_fixture():
"""Fixture to mock get_newest_version."""
with patch("homeassistant.components.updater.get_newest_version") as mock:
yield mock
@pytest.fixture(name="mock_get_uuid")
def mock_get_uuid_fixture():
"""Fixture to mock get_uuid."""
with patch("homeassistant.components.updater._load_uuid") as mock:
yield mock
@pytest.fixture(name="mock_utcnow")
def mock_utcnow_fixture():
"""Fixture to mock utcnow."""
with patch("homeassistant.components.updater.dt_util") as mock:
yield mock.utcnow
async def test_new_version_shows_entity_startup(
hass, mock_get_uuid, mock_get_newest_version
):
"""Test if binary sensor is unavailable at first."""
mock_get_uuid.return_value = MOCK_HUUID
mock_get_newest_version.return_value = mock_coro((NEW_VERSION, RELEASE_NOTES))
res = await async_setup_component(hass, updater.DOMAIN, {updater.DOMAIN: {}})
assert res, "Updater failed to set up"
await hass.async_block_till_done()
assert hass.states.is_state("binary_sensor.updater", "unavailable")
assert "newest_version" not in hass.states.get("binary_sensor.updater").attributes
assert "release_notes" not in hass.states.get("binary_sensor.updater").attributes
async def test_rename_entity(hass, mock_get_uuid, mock_get_newest_version, mock_utcnow):
"""Test if renaming the binary sensor works correctly."""
mock_get_uuid.return_value = MOCK_HUUID
mock_get_newest_version.return_value = mock_coro((NEW_VERSION, RELEASE_NOTES))
now = dt_util.utcnow()
later = now + timedelta(hours=1)
mock_utcnow.return_value = now
res = await async_setup_component(hass, updater.DOMAIN, {updater.DOMAIN: {}})
assert res, "Updater failed to set up"
await hass.async_block_till_done()
assert hass.states.is_state("binary_sensor.updater", "unavailable")
assert hass.states.get("binary_sensor.new_entity_id") is None
entity_registry = await hass.helpers.entity_registry.async_get_registry()
entity_registry.async_update_entity(
"binary_sensor.updater", new_entity_id="binary_sensor.new_entity_id"
)
await hass.async_block_till_done()
assert hass.states.is_state("binary_sensor.new_entity_id", "unavailable")
assert hass.states.get("binary_sensor.updater") is None
with patch("homeassistant.components.updater.current_version", MOCK_VERSION):
async_fire_time_changed(hass, later)
await hass.async_block_till_done()
assert hass.states.is_state("binary_sensor.new_entity_id", "on")
assert hass.states.get("binary_sensor.updater") is None
async def test_new_version_shows_entity_true(
hass, mock_get_uuid, mock_get_newest_version, mock_utcnow
):
"""Test if sensor is true if new version is available."""
mock_get_uuid.return_value = MOCK_HUUID
mock_get_newest_version.return_value = mock_coro((NEW_VERSION, RELEASE_NOTES))
now = dt_util.utcnow()
later = now + timedelta(hours=1)
mock_utcnow.return_value = now
res = await async_setup_component(hass, updater.DOMAIN, {updater.DOMAIN: {}})
assert res, "Updater failed to set up"
await hass.async_block_till_done()
with patch("homeassistant.components.updater.current_version", MOCK_VERSION):
async_fire_time_changed(hass, later)
await hass.async_block_till_done()
assert hass.states.is_state("binary_sensor.updater", "on")
assert (
hass.states.get("binary_sensor.updater").attributes["newest_version"]
== NEW_VERSION
)
assert (
hass.states.get("binary_sensor.updater").attributes["release_notes"]
== RELEASE_NOTES
)
async def test_same_version_shows_entity_false(
hass, mock_get_uuid, mock_get_newest_version, mock_utcnow
):
"""Test if sensor is false if no new version is available."""
mock_get_uuid.return_value = MOCK_HUUID
mock_get_newest_version.return_value = mock_coro((MOCK_VERSION, ""))
now = dt_util.utcnow()
later = now + timedelta(hours=1)
mock_utcnow.return_value = now
res = await async_setup_component(hass, updater.DOMAIN, {updater.DOMAIN: {}})
assert res, "Updater failed to set up"
await hass.async_block_till_done()
with patch("homeassistant.components.updater.current_version", MOCK_VERSION):
async_fire_time_changed(hass, later)
await hass.async_block_till_done()
assert hass.states.is_state("binary_sensor.updater", "off")
assert (
hass.states.get("binary_sensor.updater").attributes["newest_version"]
== MOCK_VERSION
)
assert "release_notes" not in hass.states.get("binary_sensor.updater").attributes
async def test_disable_reporting(
hass, mock_get_uuid, mock_get_newest_version, mock_utcnow
):
"""Test we do not gather analytics when disable reporting is active."""
mock_get_uuid.return_value = MOCK_HUUID
mock_get_newest_version.return_value = mock_coro((MOCK_VERSION, ""))
now = dt_util.utcnow()
later = now + timedelta(hours=1)
mock_utcnow.return_value = now
res = await async_setup_component(
hass, updater.DOMAIN, {updater.DOMAIN: {"reporting": False}}
)
assert res, "Updater failed to set up"
await hass.async_block_till_done()
with patch("homeassistant.components.updater.current_version", MOCK_VERSION):
async_fire_time_changed(hass, later)
await hass.async_block_till_done()
assert hass.states.is_state("binary_sensor.updater", "off")
res = await updater.get_newest_version(hass, MOCK_HUUID, MOCK_CONFIG)
call = mock_get_newest_version.mock_calls[0][1]
assert call[0] is hass
assert call[1] is None
async def test_get_newest_version_no_analytics_when_no_huuid(hass, aioclient_mock):
"""Test we do not gather analytics when no huuid is passed in."""
aioclient_mock.post(updater.UPDATER_URL, json=MOCK_RESPONSE)
with patch(
"homeassistant.helpers.system_info.async_get_system_info", side_effect=Exception
):
res = await updater.get_newest_version(hass, None, False)
assert res == (MOCK_RESPONSE["version"], MOCK_RESPONSE["release-notes"])
async def test_get_newest_version_analytics_when_huuid(hass, aioclient_mock):
"""Test we gather analytics when huuid is passed in."""
aioclient_mock.post(updater.UPDATER_URL, json=MOCK_RESPONSE)
with patch(
"homeassistant.helpers.system_info.async_get_system_info",
Mock(return_value=mock_coro({"fake": "bla"})),
):
res = await updater.get_newest_version(hass, MOCK_HUUID, False)
assert res == (MOCK_RESPONSE["version"], MOCK_RESPONSE["release-notes"])
async def test_error_fetching_new_version_timeout(hass):
"""Test we handle timeout error while fetching new version."""
with patch(
"homeassistant.helpers.system_info.async_get_system_info",
Mock(return_value=mock_coro({"fake": "bla"})),
), patch("async_timeout.timeout", side_effect=asyncio.TimeoutError):
res = await updater.get_newest_version(hass, MOCK_HUUID, False)
assert res is None
async def test_error_fetching_new_version_bad_json(hass, aioclient_mock):
"""Test we handle json error while fetching new version."""
aioclient_mock.post(updater.UPDATER_URL, text="not json")
with patch(
"homeassistant.helpers.system_info.async_get_system_info",
Mock(return_value=mock_coro({"fake": "bla"})),
):
res = await updater.get_newest_version(hass, MOCK_HUUID, False)
assert res is None
async def test_error_fetching_new_version_invalid_response(hass, aioclient_mock):
"""Test we handle response error while fetching new version."""
aioclient_mock.post(
updater.UPDATER_URL,
json={
"version": "0.15"
# 'release-notes' is missing
},
)
with patch(
"homeassistant.helpers.system_info.async_get_system_info",
Mock(return_value=mock_coro({"fake": "bla"})),
):
res = await updater.get_newest_version(hass, MOCK_HUUID, False)
assert res is None
async def test_new_version_shows_entity_after_hour_hassio(
hass, mock_get_uuid, mock_get_newest_version, mock_utcnow
):
"""Test if binary sensor gets updated if new version is available / hass.io."""
mock_get_uuid.return_value = MOCK_HUUID
mock_get_newest_version.return_value = mock_coro((NEW_VERSION, RELEASE_NOTES))
mock_component(hass, "hassio")
hass.data["hassio_hass_version"] = "999.0"
now = dt_util.utcnow()
later = now + timedelta(hours=1)
mock_utcnow.return_value = now
res = await async_setup_component(hass, updater.DOMAIN, {updater.DOMAIN: {}})
assert res, "Updater failed to set up"
await hass.async_block_till_done()
with patch("homeassistant.components.updater.current_version", MOCK_VERSION):
async_fire_time_changed(hass, later)
await hass.async_block_till_done()
assert hass.states.is_state("binary_sensor.updater", "on")
assert (
hass.states.get("binary_sensor.updater").attributes["newest_version"] == "999.0"
)
assert (
hass.states.get("binary_sensor.updater").attributes["release_notes"]
== RELEASE_NOTES
)