mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-11-14 05:20:21 +00:00
Add verification that the frontend is actually accessible at "/" after core updates to ensure the web interface is serving properly, not just that the API endpoints respond. Previously, the update verification only checked API endpoints and whether the frontend component was loaded. This could miss cases where the API is responsive but the frontend fails to serve the UI. Changes: - Add check_frontend_available() method to HomeAssistantAPI that fetches the root path and verifies it returns HTML content - Integrate frontend check into core update verification flow after confirming the frontend component is loaded - Trigger automatic rollback if frontend is inaccessible after update - Fix blocking I/O calls in rollback log file handling to use async executor 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
111 lines
3.5 KiB
Python
111 lines
3.5 KiB
Python
"""Test Home Assistant API."""
|
|
|
|
from contextlib import asynccontextmanager
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from aiohttp import hdrs
|
|
from awesomeversion import AwesomeVersion
|
|
import pytest
|
|
|
|
from supervisor.coresys import CoreSys
|
|
from supervisor.exceptions import HomeAssistantAPIError
|
|
from supervisor.homeassistant.const import LANDINGPAGE
|
|
|
|
|
|
async def test_check_frontend_available_success(coresys: CoreSys):
|
|
"""Test frontend availability check succeeds with valid HTML response."""
|
|
coresys.homeassistant.version = AwesomeVersion("2025.8.0")
|
|
|
|
mock_response = MagicMock()
|
|
mock_response.status = 200
|
|
mock_response.headers = {hdrs.CONTENT_TYPE: "text/html; charset=utf-8"}
|
|
|
|
@asynccontextmanager
|
|
async def mock_make_request(*args, **kwargs):
|
|
yield mock_response
|
|
|
|
with patch.object(
|
|
type(coresys.homeassistant.api), "make_request", new=mock_make_request
|
|
):
|
|
result = await coresys.homeassistant.api.check_frontend_available()
|
|
|
|
assert result is True
|
|
|
|
|
|
async def test_check_frontend_available_wrong_status(coresys: CoreSys):
|
|
"""Test frontend availability check fails with non-200 status."""
|
|
coresys.homeassistant.version = AwesomeVersion("2025.8.0")
|
|
|
|
mock_response = MagicMock()
|
|
mock_response.status = 404
|
|
mock_response.headers = {hdrs.CONTENT_TYPE: "text/html"}
|
|
|
|
@asynccontextmanager
|
|
async def mock_make_request(*args, **kwargs):
|
|
yield mock_response
|
|
|
|
with patch.object(
|
|
type(coresys.homeassistant.api), "make_request", new=mock_make_request
|
|
):
|
|
result = await coresys.homeassistant.api.check_frontend_available()
|
|
|
|
assert result is False
|
|
|
|
|
|
async def test_check_frontend_available_wrong_content_type(
|
|
coresys: CoreSys, caplog: pytest.LogCaptureFixture
|
|
):
|
|
"""Test frontend availability check fails with wrong content type."""
|
|
coresys.homeassistant.version = AwesomeVersion("2025.8.0")
|
|
|
|
mock_response = MagicMock()
|
|
mock_response.status = 200
|
|
mock_response.headers = {hdrs.CONTENT_TYPE: "application/json"}
|
|
|
|
@asynccontextmanager
|
|
async def mock_make_request(*args, **kwargs):
|
|
yield mock_response
|
|
|
|
with patch.object(
|
|
type(coresys.homeassistant.api), "make_request", new=mock_make_request
|
|
):
|
|
result = await coresys.homeassistant.api.check_frontend_available()
|
|
|
|
assert result is False
|
|
assert "unexpected content type" in caplog.text
|
|
|
|
|
|
async def test_check_frontend_available_api_error(coresys: CoreSys):
|
|
"""Test frontend availability check handles API errors gracefully."""
|
|
coresys.homeassistant.version = AwesomeVersion("2025.8.0")
|
|
|
|
@asynccontextmanager
|
|
async def mock_make_request(*args, **kwargs):
|
|
raise HomeAssistantAPIError("Connection failed")
|
|
yield # pragma: no cover
|
|
|
|
with patch.object(
|
|
type(coresys.homeassistant.api), "make_request", new=mock_make_request
|
|
):
|
|
result = await coresys.homeassistant.api.check_frontend_available()
|
|
|
|
assert result is False
|
|
|
|
|
|
async def test_check_frontend_available_landingpage(coresys: CoreSys):
|
|
"""Test frontend availability check returns False for landingpage."""
|
|
coresys.homeassistant.version = LANDINGPAGE
|
|
|
|
result = await coresys.homeassistant.api.check_frontend_available()
|
|
|
|
assert result is False
|
|
|
|
|
|
async def test_check_frontend_available_no_version(coresys: CoreSys):
|
|
"""Test frontend availability check returns False when no version set."""
|
|
coresys.homeassistant.version = None
|
|
|
|
result = await coresys.homeassistant.api.check_frontend_available()
|
|
|
|
assert result is False
|