Create issues in demo integration (#75081)

* Create issues in demo integration

* Add unfixable non-expiring issue

* Update test

* Adjust tests

* update translations

* add hassfest translation schema

* Update homeassistant/components/demo/translations/en.json

Co-authored-by: Zack Barett <zackbarett@hey.com>

* Rename Resolution Center -> Repairs

* Update homeassistant/components/demo/strings.json

Co-authored-by: Zack Barett <zackbarett@hey.com>

* Adjust hassfest to require description or fix_flow

* Update homeassistant/components/demo/repairs.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Update tests/components/demo/test_init.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Add missing translation strings

* black

* Adjust repairs imports

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Zack Barett <zackbarett@hey.com>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Erik Montnemery 2022-07-20 14:46:06 +02:00 committed by GitHub
parent 3920844dca
commit fb4aff25a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 266 additions and 4 deletions

View file

@ -10,6 +10,7 @@ from homeassistant.components.recorder.statistics import (
async_add_external_statistics, async_add_external_statistics,
get_last_statistics, get_last_statistics,
) )
from homeassistant.components.repairs import IssueSeverity, async_create_issue
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
@ -177,6 +178,39 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
hass.bus.async_listen(EVENT_HOMEASSISTANT_START, demo_start_listener) hass.bus.async_listen(EVENT_HOMEASSISTANT_START, demo_start_listener)
# Create issues
async_create_issue(
hass,
DOMAIN,
"transmogrifier_deprecated",
breaks_in_ha_version="2023.1.1",
is_fixable=False,
learn_more_url="https://en.wiktionary.org/wiki/transmogrifier",
severity=IssueSeverity.WARNING,
translation_key="transmogrifier_deprecated",
)
async_create_issue(
hass,
DOMAIN,
"out_of_blinker_fluid",
breaks_in_ha_version="2023.1.1",
is_fixable=True,
learn_more_url="https://www.youtube.com/watch?v=b9rntRxLlbU",
severity=IssueSeverity.CRITICAL,
translation_key="out_of_blinker_fluid",
)
async_create_issue(
hass,
DOMAIN,
"unfixable_problem",
is_fixable=False,
learn_more_url="https://www.youtube.com/watch?v=dQw4w9WgXcQ",
severity=IssueSeverity.WARNING,
translation_key="unfixable_problem",
)
return True return True

View file

@ -3,7 +3,7 @@
"name": "Demo", "name": "Demo",
"documentation": "https://www.home-assistant.io/integrations/demo", "documentation": "https://www.home-assistant.io/integrations/demo",
"after_dependencies": ["recorder"], "after_dependencies": ["recorder"],
"dependencies": ["conversation", "group", "zone"], "dependencies": ["conversation", "group", "repairs", "zone"],
"codeowners": ["@home-assistant/core"], "codeowners": ["@home-assistant/core"],
"quality_scale": "internal", "quality_scale": "internal",
"iot_class": "calculated" "iot_class": "calculated"

View file

@ -0,0 +1,33 @@
"""Repairs platform for the demo integration."""
from __future__ import annotations
import voluptuous as vol
from homeassistant import data_entry_flow
from homeassistant.components.repairs import RepairsFlow
class DemoFixFlow(RepairsFlow):
"""Handler for an issue fixing flow."""
async def async_step_init(
self, user_input: dict[str, str] | None = None
) -> data_entry_flow.FlowResult:
"""Handle the first step of a fix flow."""
return await (self.async_step_confirm())
async def async_step_confirm(
self, user_input: dict[str, str] | None = None
) -> data_entry_flow.FlowResult:
"""Handle the confirm step of a fix flow."""
if user_input is not None:
return self.async_create_entry(title="Fixed issue", data={})
return self.async_show_form(step_id="confirm", data_schema=vol.Schema({}))
async def async_create_fix_flow(hass, issue_id):
"""Create flow."""
return DemoFixFlow()

View file

@ -1,5 +1,26 @@
{ {
"title": "Demo", "title": "Demo",
"issues": {
"out_of_blinker_fluid": {
"title": "The blinker fluid is empty and needs to be refilled",
"fix_flow": {
"step": {
"confirm": {
"title": "Blinker fluid needs to be refilled",
"description": "Press OK when blinker fluid has been refilled"
}
}
}
},
"transmogrifier_deprecated": {
"title": "The transmogrifier component is deprecated",
"description": "The transmogrifier component is now deprecated due to the lack of local control available in the new API"
},
"unfixable_problem": {
"title": "This is not a fixable problem",
"description": "This issue is never going to give up."
}
},
"options": { "options": {
"step": { "step": {
"init": { "init": {

View file

@ -1,6 +1,30 @@
{ {
"issues": {
"out_of_blinker_fluid": {
"fix_flow": {
"step": {
"confirm": {
"description": "Press OK when blinker fluid has been refilled",
"title": "Blinker fluid needs to be refilled"
}
}
},
"title": "The blinker fluid is empty and needs to be refilled"
},
"transmogrifier_deprecated": {
"description": "The transmogrifier component is now deprecated due to the lack of local control available in the new API",
"title": "The transmogrifier component is deprecated"
},
"unfixable_problem": {
"description": "This issue is never going to give up.",
"title": "This is not a fixable problem"
}
},
"options": { "options": {
"step": { "step": {
"init": {
"data": {}
},
"options_1": { "options_1": {
"data": { "data": {
"bool": "Optional boolean", "bool": "Optional boolean",

View file

@ -21,7 +21,7 @@ REMOVED = 2
RE_REFERENCE = r"\[\%key:(.+)\%\]" RE_REFERENCE = r"\[\%key:(.+)\%\]"
# Only allow translatino of integration names if they contain non-brand names # Only allow translation of integration names if they contain non-brand names
ALLOW_NAME_TRANSLATION = { ALLOW_NAME_TRANSLATION = {
"cert_expiry", "cert_expiry",
"cpuspeed", "cpuspeed",
@ -185,7 +185,7 @@ def gen_data_entry_schema(
return vol.All(*validators) return vol.All(*validators)
def gen_strings_schema(config: Config, integration: Integration): def gen_strings_schema(config: Config, integration: Integration) -> vol.Schema:
"""Generate a strings schema.""" """Generate a strings schema."""
return vol.Schema( return vol.Schema(
{ {
@ -227,6 +227,25 @@ def gen_strings_schema(config: Config, integration: Integration):
vol.Optional("application_credentials"): { vol.Optional("application_credentials"): {
vol.Optional("description"): cv.string_with_no_html, vol.Optional("description"): cv.string_with_no_html,
}, },
vol.Optional("issues"): {
str: vol.All(
cv.has_at_least_one_key("description", "fix_flow"),
vol.Schema(
{
vol.Required("title"): cv.string_with_no_html,
vol.Exclusive(
"description", "fixable"
): cv.string_with_no_html,
vol.Exclusive("fix_flow", "fixable"): gen_data_entry_schema(
config=config,
integration=integration,
flow_title=UNDEFINED,
require_step_title=False,
),
},
),
)
},
} }
) )

View file

@ -1,6 +1,7 @@
"""The tests for the Demo component.""" """The tests for the Demo component."""
from http import HTTPStatus
import json import json
from unittest.mock import patch from unittest.mock import ANY, patch
import pytest import pytest
@ -69,3 +70,133 @@ async def test_demo_statistics(hass, recorder_mock):
"statistic_id": "demo:energy_consumption", "statistic_id": "demo:energy_consumption",
"unit_of_measurement": "kWh", "unit_of_measurement": "kWh",
} in statistic_ids } in statistic_ids
async def test_issues_created(hass, hass_client, hass_ws_client):
"""Test issues are created and can be fixed."""
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
await hass.async_block_till_done()
await hass.async_start()
ws_client = await hass_ws_client(hass)
client = await hass_client()
await ws_client.send_json({"id": 1, "type": "repairs/list_issues"})
msg = await ws_client.receive_json()
assert msg["success"]
assert msg["result"] == {
"issues": [
{
"breaks_in_ha_version": "2023.1.1",
"created": ANY,
"dismissed_version": None,
"domain": "demo",
"ignored": False,
"is_fixable": False,
"issue_id": "transmogrifier_deprecated",
"learn_more_url": "https://en.wiktionary.org/wiki/transmogrifier",
"severity": "warning",
"translation_key": "transmogrifier_deprecated",
"translation_placeholders": None,
},
{
"breaks_in_ha_version": "2023.1.1",
"created": ANY,
"dismissed_version": None,
"domain": "demo",
"ignored": False,
"is_fixable": True,
"issue_id": "out_of_blinker_fluid",
"learn_more_url": "https://www.youtube.com/watch?v=b9rntRxLlbU",
"severity": "critical",
"translation_key": "out_of_blinker_fluid",
"translation_placeholders": None,
},
{
"breaks_in_ha_version": None,
"created": ANY,
"dismissed_version": None,
"domain": "demo",
"ignored": False,
"is_fixable": False,
"issue_id": "unfixable_problem",
"learn_more_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"severity": "warning",
"translation_key": "unfixable_problem",
"translation_placeholders": None,
},
]
}
url = "/api/repairs/issues/fix"
resp = await client.post(
url, json={"handler": "demo", "issue_id": "out_of_blinker_fluid"}
)
assert resp.status == HTTPStatus.OK
data = await resp.json()
flow_id = data["flow_id"]
assert data == {
"data_schema": [],
"description_placeholders": None,
"errors": None,
"flow_id": ANY,
"handler": "demo",
"last_step": None,
"step_id": "confirm",
"type": "form",
}
url = f"/api/repairs/issues/fix/{flow_id}"
resp = await client.post(url)
assert resp.status == HTTPStatus.OK
data = await resp.json()
flow_id = data["flow_id"]
assert data == {
"description": None,
"description_placeholders": None,
"flow_id": flow_id,
"handler": "demo",
"title": "Fixed issue",
"type": "create_entry",
"version": 1,
}
await ws_client.send_json({"id": 4, "type": "repairs/list_issues"})
msg = await ws_client.receive_json()
assert msg["success"]
assert msg["result"] == {
"issues": [
{
"breaks_in_ha_version": "2023.1.1",
"created": ANY,
"dismissed_version": None,
"domain": "demo",
"ignored": False,
"is_fixable": False,
"issue_id": "transmogrifier_deprecated",
"learn_more_url": "https://en.wiktionary.org/wiki/transmogrifier",
"severity": "warning",
"translation_key": "transmogrifier_deprecated",
"translation_placeholders": None,
},
{
"breaks_in_ha_version": None,
"created": ANY,
"dismissed_version": None,
"domain": "demo",
"ignored": False,
"is_fixable": False,
"issue_id": "unfixable_problem",
"learn_more_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"severity": "warning",
"translation_key": "unfixable_problem",
"translation_placeholders": None,
},
]
}