core/tests/components/zwave_js/test_repairs.py

214 lines
6.5 KiB
Python

"""Test the Z-Wave JS repairs module."""
from copy import deepcopy
from http import HTTPStatus
from unittest.mock import patch
from zwave_js_server.event import Event
from zwave_js_server.model.node import Node
from homeassistant.components.repairs.issue_handler import (
async_process_repairs_platforms,
)
from homeassistant.components.repairs.websocket_api import (
RepairsFlowIndexView,
RepairsFlowResourceView,
)
from homeassistant.components.zwave_js import DOMAIN
from homeassistant.components.zwave_js.helpers import get_device_id
from homeassistant.core import HomeAssistant
import homeassistant.helpers.device_registry as dr
import homeassistant.helpers.issue_registry as ir
from tests.typing import ClientSessionGenerator, WebSocketGenerator
async def _trigger_repair_issue(
hass: HomeAssistant, client, multisensor_6_state
) -> Node:
"""Trigger repair issue."""
# Create a node
node_state = deepcopy(multisensor_6_state)
node = Node(client, node_state)
event = Event(
"node added",
{
"source": "controller",
"event": "node added",
"node": node_state,
"result": "",
},
)
with patch(
"zwave_js_server.model.node.Node.async_has_device_config_changed",
return_value=True,
):
client.driver.controller.receive_event(event)
await hass.async_block_till_done()
client.async_send_command_no_wait.reset_mock()
return node
async def test_device_config_file_changed(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
hass_ws_client: WebSocketGenerator,
client,
multisensor_6_state,
integration,
) -> None:
"""Test the device_config_file_changed issue."""
dev_reg = dr.async_get(hass)
node = await _trigger_repair_issue(hass, client, multisensor_6_state)
client.async_send_command_no_wait.reset_mock()
device = dev_reg.async_get_device(identifiers={get_device_id(client.driver, node)})
assert device
issue_id = f"device_config_file_changed.{device.id}"
await async_process_repairs_platforms(hass)
ws_client = await hass_ws_client(hass)
http_client = await hass_client()
# Assert the issue is present
await ws_client.send_json({"id": 1, "type": "repairs/list_issues"})
msg = await ws_client.receive_json()
assert msg["success"]
assert len(msg["result"]["issues"]) == 1
issue = msg["result"]["issues"][0]
assert issue["issue_id"] == issue_id
assert issue["translation_placeholders"] == {"device_name": device.name}
url = RepairsFlowIndexView.url
resp = await http_client.post(url, json={"handler": DOMAIN, "issue_id": issue_id})
assert resp.status == HTTPStatus.OK
data = await resp.json()
flow_id = data["flow_id"]
assert data["step_id"] == "confirm"
assert data["description_placeholders"] == {"device_name": device.name}
# Apply fix
url = RepairsFlowResourceView.url.format(flow_id=flow_id)
resp = await http_client.post(url)
assert resp.status == HTTPStatus.OK
data = await resp.json()
assert data["type"] == "create_entry"
await hass.async_block_till_done()
assert len(client.async_send_command_no_wait.call_args_list) == 1
assert client.async_send_command_no_wait.call_args[0][0] == {
"command": "node.refresh_info",
"nodeId": node.node_id,
}
# Assert the issue is resolved
await ws_client.send_json({"id": 2, "type": "repairs/list_issues"})
msg = await ws_client.receive_json()
assert msg["success"]
assert len(msg["result"]["issues"]) == 0
async def test_invalid_issue(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
hass_ws_client: WebSocketGenerator,
integration,
) -> None:
"""Test the invalid issue."""
ir.async_create_issue(
hass,
DOMAIN,
"invalid_issue_id",
is_fixable=True,
severity=ir.IssueSeverity.ERROR,
translation_key="invalid_issue",
)
await async_process_repairs_platforms(hass)
ws_client = await hass_ws_client(hass)
http_client = await hass_client()
# Assert the issue is present
await ws_client.send_json({"id": 1, "type": "repairs/list_issues"})
msg = await ws_client.receive_json()
assert msg["success"]
assert len(msg["result"]["issues"]) == 1
issue = msg["result"]["issues"][0]
assert issue["issue_id"] == "invalid_issue_id"
url = RepairsFlowIndexView.url
resp = await http_client.post(
url, json={"handler": DOMAIN, "issue_id": "invalid_issue_id"}
)
assert resp.status == HTTPStatus.OK
data = await resp.json()
flow_id = data["flow_id"]
assert data["step_id"] == "confirm"
# Apply fix
url = RepairsFlowResourceView.url.format(flow_id=flow_id)
resp = await http_client.post(url)
assert resp.status == HTTPStatus.OK
data = await resp.json()
assert data["type"] == "create_entry"
await hass.async_block_till_done()
# Assert the issue is resolved
await ws_client.send_json({"id": 2, "type": "repairs/list_issues"})
msg = await ws_client.receive_json()
assert msg["success"]
assert len(msg["result"]["issues"]) == 0
async def test_abort_confirm(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
hass_ws_client: WebSocketGenerator,
client,
multisensor_6_state,
integration,
) -> None:
"""Test aborting device_config_file_changed issue in confirm step."""
dev_reg = dr.async_get(hass)
node = await _trigger_repair_issue(hass, client, multisensor_6_state)
device = dev_reg.async_get_device(identifiers={get_device_id(client.driver, node)})
assert device
issue_id = f"device_config_file_changed.{device.id}"
await async_process_repairs_platforms(hass)
await hass_ws_client(hass)
http_client = await hass_client()
url = RepairsFlowIndexView.url
resp = await http_client.post(url, json={"handler": DOMAIN, "issue_id": issue_id})
assert resp.status == HTTPStatus.OK
data = await resp.json()
flow_id = data["flow_id"]
assert data["step_id"] == "confirm"
# Unload config entry so we can't connect to the node
await hass.config_entries.async_unload(integration.entry_id)
# Apply fix
url = RepairsFlowResourceView.url.format(flow_id=flow_id)
resp = await http_client.post(url)
assert resp.status == HTTPStatus.OK
data = await resp.json()
assert data["type"] == "abort"
assert data["reason"] == "cannot_connect"
assert data["description_placeholders"] == {"device_name": device.name}