1
0
mirror of https://github.com/home-assistant/core.git synced 2026-07-03 12:46:09 +01:00
Files
Paulus Schoutsen 8198aa263b Lazy load repairs platforms (#174374)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 15:08:30 -05:00

218 lines
7.3 KiB
Python

"""Test the Teslemetry repairs."""
from copy import deepcopy
from typing import Any
from unittest.mock import patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant.components.repairs import ConfirmRepairFlow
from homeassistant.components.teslemetry.const import DOMAIN
from homeassistant.components.teslemetry.coordinator import METADATA_INTERVAL
from homeassistant.components.teslemetry.repairs import async_create_fix_flow
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers import issue_registry as ir
from homeassistant.setup import async_setup_component
from . import setup_platform
from .const import METADATA
from tests.common import async_fire_time_changed
from tests.components.repairs import process_repair_fix_flow, start_repair_fix_flow
from tests.typing import ClientSessionGenerator
VEHICLE_VIN = "LRW3F7EK4NC700000"
def _metadata_with_issue(issue: str | None) -> dict[str, Any]:
"""Return a copy of the metadata with the vehicle issue set."""
metadata = deepcopy(METADATA)
metadata["vehicles"][VEHICLE_VIN]["issue"] = issue
return metadata
def _metadata_without_vehicle() -> dict[str, Any]:
"""Return a copy of the metadata without the vehicle."""
metadata = deepcopy(METADATA)
del metadata["vehicles"][VEHICLE_VIN]
return metadata
def _metadata_with_vehicle_access(access: bool) -> dict[str, Any]:
"""Return a copy of the metadata with the vehicle access set."""
metadata = _metadata_with_issue("key")
metadata["vehicles"][VEHICLE_VIN]["access"] = access
return metadata
@pytest.mark.parametrize("issue_type", ["key", "streaming_toggle"])
async def test_repair_issue_created(
hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
issue_type: str,
) -> None:
"""Test a repair issue is created for an unresolved vehicle metadata issue."""
with patch(
"tesla_fleet_api.teslemetry.Teslemetry.metadata",
return_value=_metadata_with_issue(issue_type),
):
entry = await setup_platform(hass)
assert entry.state is ConfigEntryState.LOADED
issue = issue_registry.async_get_issue(DOMAIN, f"{issue_type}_{VEHICLE_VIN}")
assert issue is not None
assert issue.translation_key == issue_type
assert issue.data == {
"entry_id": entry.entry_id,
"vin": VEHICLE_VIN,
"issue_type": issue_type,
"vehicle": "Home Assistant",
}
@pytest.mark.parametrize("issue", [None, "no_data"])
async def test_no_repair_issue(
hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
issue: str | None,
) -> None:
"""Test no repair issue is created when there is no actionable issue."""
with patch(
"tesla_fleet_api.teslemetry.Teslemetry.metadata",
return_value=_metadata_with_issue(issue),
):
entry = await setup_platform(hass)
assert entry.state is ConfigEntryState.LOADED
assert issue_registry.async_get_issue(DOMAIN, f"key_{VEHICLE_VIN}") is None
assert (
issue_registry.async_get_issue(DOMAIN, f"streaming_toggle_{VEHICLE_VIN}")
is None
)
async def test_repair_issue_auto_resolves(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
issue_registry: ir.IssueRegistry,
) -> None:
"""Test a repair issue is removed once the metadata issue clears."""
with patch(
"tesla_fleet_api.teslemetry.Teslemetry.metadata",
return_value=_metadata_with_issue("key"),
):
entry = await setup_platform(hass)
assert entry.state is ConfigEntryState.LOADED
assert issue_registry.async_get_issue(DOMAIN, f"key_{VEHICLE_VIN}") is not None
with patch(
"tesla_fleet_api.teslemetry.Teslemetry.metadata",
return_value=_metadata_with_issue(None),
):
freezer.tick(METADATA_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert issue_registry.async_get_issue(DOMAIN, f"key_{VEHICLE_VIN}") is None
@pytest.mark.parametrize(
"metadata",
[
pytest.param(_metadata_without_vehicle(), id="removed"),
pytest.param(
_metadata_with_vehicle_access(False),
id="access_revoked",
),
],
)
async def test_repair_issue_removed_when_vehicle_no_longer_available(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
issue_registry: ir.IssueRegistry,
metadata: dict[str, Any],
) -> None:
"""Test a repair issue is removed once the vehicle is no longer available."""
with patch(
"tesla_fleet_api.teslemetry.Teslemetry.metadata",
return_value=_metadata_with_issue("key"),
):
entry = await setup_platform(hass)
assert entry.state is ConfigEntryState.LOADED
assert issue_registry.async_get_issue(DOMAIN, f"key_{VEHICLE_VIN}") is not None
with patch(
"tesla_fleet_api.teslemetry.Teslemetry.metadata",
return_value=metadata,
):
freezer.tick(METADATA_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert issue_registry.async_get_issue(DOMAIN, f"key_{VEHICLE_VIN}") is None
async def test_repair_fix_flow(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
issue_registry: ir.IssueRegistry,
) -> None:
"""Test the fix flow re-checks metadata and resolves once fixed."""
assert await async_setup_component(hass, "repairs", {})
client = await hass_client()
with patch(
"tesla_fleet_api.teslemetry.Teslemetry.metadata",
return_value=_metadata_with_issue("key"),
):
entry = await setup_platform(hass)
assert entry.state is ConfigEntryState.LOADED
issue_id = f"key_{VEHICLE_VIN}"
assert issue_registry.async_get_issue(DOMAIN, issue_id) is not None
result = await start_repair_fix_flow(client, DOMAIN, issue_id)
flow_id = result["flow_id"]
assert result["type"] == FlowResultType.FORM
assert result["step_id"] == "confirm"
# Submitting while the key is still unpaired keeps the form open
with patch(
"tesla_fleet_api.teslemetry.Teslemetry.metadata",
return_value=_metadata_with_issue("key"),
):
result = await process_repair_fix_flow(client, flow_id, json={})
assert result["type"] == FlowResultType.FORM
assert result["step_id"] == "confirm"
assert result["errors"] == {"base": "not_resolved"}
assert issue_registry.async_get_issue(DOMAIN, issue_id) is not None
# Once the key is paired, re-checking resolves the issue
with patch(
"tesla_fleet_api.teslemetry.Teslemetry.metadata",
return_value=_metadata_with_issue(None),
):
result = await process_repair_fix_flow(client, flow_id, json={})
assert result["type"] == FlowResultType.CREATE_ENTRY
assert issue_registry.async_get_issue(DOMAIN, issue_id) is None
@pytest.mark.parametrize(
"data",
[
None,
{"entry_id": "missing"},
{"entry_id": 123, "vin": VEHICLE_VIN, "issue_type": "key", "vehicle": "Car"},
],
)
async def test_repair_invalid_data_returns_confirm_flow(
hass: HomeAssistant,
data: dict[str, Any] | None,
) -> None:
"""Test invalid repair flow data falls back to a confirm flow."""
flow = await async_create_fix_flow(hass, "key_VIN", data)
assert isinstance(flow, ConfirmRepairFlow)