diff --git a/homeassistant/components/resolution_center/issue_registry.py b/homeassistant/components/resolution_center/issue_registry.py index d9042d891dd..aed1cd51b10 100644 --- a/homeassistant/components/resolution_center/issue_registry.py +++ b/homeassistant/components/resolution_center/issue_registry.py @@ -2,11 +2,13 @@ from __future__ import annotations import dataclasses +from datetime import datetime from typing import Optional, cast from homeassistant.const import __version__ as ha_version from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.storage import Store +import homeassistant.util.dt as dt_util from .models import IssueSeverity @@ -14,7 +16,6 @@ DATA_REGISTRY = "issue_registry" STORAGE_KEY = "resolution_center.issue_registry" STORAGE_VERSION = 1 SAVE_DELAY = 10 -SAVED_FIELDS = ("dismissed_version", "domain", "issue_id") @dataclasses.dataclass(frozen=True) @@ -23,6 +24,7 @@ class IssueEntry: active: bool breaks_in_ha_version: str | None + created: datetime dismissed_version: str | None domain: str is_fixable: bool | None @@ -68,6 +70,7 @@ class IssueRegistry: issue = IssueEntry( active=True, breaks_in_ha_version=breaks_in_ha_version, + created=dt_util.utcnow(), dismissed_version=None, domain=domain, is_fixable=is_fixable, @@ -125,10 +128,11 @@ class IssueRegistry: if isinstance(data, dict): for issue in data["issues"]: - assert issue["domain"] and issue["issue_id"] + assert issue["created"] and issue["domain"] and issue["issue_id"] issues[(issue["domain"], issue["issue_id"])] = IssueEntry( active=False, breaks_in_ha_version=None, + created=cast(datetime, dt_util.parse_datetime(issue["created"])), dismissed_version=issue["dismissed_version"], domain=issue["domain"], is_fixable=None, @@ -152,7 +156,12 @@ class IssueRegistry: data = {} data["issues"] = [ - {field: getattr(entry, field) for field in SAVED_FIELDS} + { + "created": entry.created.isoformat(), + "dismissed_version": entry.dismissed_version, + "domain": entry.domain, + "issue_id": entry.issue_id, + } for entry in self.issues.values() ] diff --git a/homeassistant/components/resolution_center/websocket_api.py b/homeassistant/components/resolution_center/websocket_api.py index dfa4f1903d9..314df009118 100644 --- a/homeassistant/components/resolution_center/websocket_api.py +++ b/homeassistant/components/resolution_center/websocket_api.py @@ -67,8 +67,9 @@ def ws_list_issues( """Return a list of issues.""" def ws_dict(kv_pairs: list[tuple[Any, Any]]) -> dict[Any, Any]: - result = {k: v for k, v in kv_pairs if k != "active"} + result = {k: v for k, v in kv_pairs if k not in ("active")} result["dismissed"] = result["dismissed_version"] is not None + result["created"] = result["created"].isoformat() return result issue_registry = async_get_issue_registry(hass) diff --git a/tests/components/resolution_center/test_init.py b/tests/components/resolution_center/test_init.py index 66f9bc42935..a707c3845fe 100644 --- a/tests/components/resolution_center/test_init.py +++ b/tests/components/resolution_center/test_init.py @@ -1,6 +1,7 @@ """Test the resolution center websocket API.""" from unittest.mock import AsyncMock, Mock +from freezegun import freeze_time import pytest from homeassistant.components.resolution_center import ( @@ -19,6 +20,7 @@ from homeassistant.setup import async_setup_component from tests.common import mock_platform +@freeze_time("2022-07-19 07:53:05") async def test_create_update_issue(hass: HomeAssistant, hass_ws_client) -> None: """Test creating and updating issues.""" assert await async_setup_component(hass, DOMAIN, {}) @@ -75,6 +77,7 @@ async def test_create_update_issue(hass: HomeAssistant, hass_ws_client) -> None: "issues": [ dict( issue, + created="2022-07-19T07:53:05+00:00", dismissed=False, dismissed_version=None, ) @@ -101,6 +104,7 @@ async def test_create_update_issue(hass: HomeAssistant, hass_ws_client) -> None: assert msg["success"] assert msg["result"]["issues"][0] == dict( issues[0], + created="2022-07-19T07:53:05+00:00", dismissed=False, dismissed_version=None, learn_more_url="blablabla", @@ -147,6 +151,7 @@ async def test_create_issue_invalid_version( assert msg["result"] == {"issues": []} +@freeze_time("2022-07-19 07:53:05") async def test_dismiss_issue(hass: HomeAssistant, hass_ws_client) -> None: """Test dismissing issues.""" assert await async_setup_component(hass, DOMAIN, {}) @@ -193,6 +198,7 @@ async def test_dismiss_issue(hass: HomeAssistant, hass_ws_client) -> None: "issues": [ dict( issue, + created="2022-07-19T07:53:05+00:00", dismissed=False, dismissed_version=None, ) @@ -212,6 +218,7 @@ async def test_dismiss_issue(hass: HomeAssistant, hass_ws_client) -> None: "issues": [ dict( issue, + created="2022-07-19T07:53:05+00:00", dismissed=False, dismissed_version=None, ) @@ -230,6 +237,7 @@ async def test_dismiss_issue(hass: HomeAssistant, hass_ws_client) -> None: "issues": [ dict( issue, + created="2022-07-19T07:53:05+00:00", dismissed=True, dismissed_version=ha_version, ) @@ -248,6 +256,7 @@ async def test_dismiss_issue(hass: HomeAssistant, hass_ws_client) -> None: "issues": [ dict( issue, + created="2022-07-19T07:53:05+00:00", dismissed=True, dismissed_version=ha_version, ) @@ -274,14 +283,16 @@ async def test_dismiss_issue(hass: HomeAssistant, hass_ws_client) -> None: assert msg["success"] assert msg["result"]["issues"][0] == dict( issues[0], + created="2022-07-19T07:53:05+00:00", dismissed=True, dismissed_version=ha_version, learn_more_url="blablabla", ) -async def test_delete_issue(hass: HomeAssistant, hass_ws_client) -> None: +async def test_delete_issue(hass: HomeAssistant, hass_ws_client, freezer) -> None: """Test we can delete an issue.""" + freezer.move_to("2022-07-19 07:53:05") assert await async_setup_component(hass, DOMAIN, {}) client = await hass_ws_client(hass) @@ -320,6 +331,7 @@ async def test_delete_issue(hass: HomeAssistant, hass_ws_client) -> None: "issues": [ dict( issue, + created="2022-07-19T07:53:05+00:00", dismissed=False, dismissed_version=None, ) @@ -338,6 +350,7 @@ async def test_delete_issue(hass: HomeAssistant, hass_ws_client) -> None: "issues": [ dict( issue, + created="2022-07-19T07:53:05+00:00", dismissed=False, dismissed_version=None, ) @@ -363,6 +376,38 @@ async def test_delete_issue(hass: HomeAssistant, hass_ws_client) -> None: assert msg["success"] assert msg["result"] == {"issues": []} + # Create the same issues again created timestamp should change + freezer.move_to("2022-07-19 08:53:05") + + for issue in issues: + async_create_issue( + hass, + issue["domain"], + issue["issue_id"], + breaks_in_ha_version=issue["breaks_in_ha_version"], + is_fixable=issue["is_fixable"], + learn_more_url=issue["learn_more_url"], + severity=issue["severity"], + translation_key=issue["translation_key"], + translation_placeholders=issue["translation_placeholders"], + ) + + await client.send_json({"id": 5, "type": "resolution_center/list_issues"}) + msg = await client.receive_json() + + assert msg["success"] + assert msg["result"] == { + "issues": [ + dict( + issue, + created="2022-07-19T08:53:05+00:00", + dismissed=False, + dismissed_version=None, + ) + for issue in issues + ] + } + async def test_non_compliant_platform(hass: HomeAssistant, hass_ws_client) -> None: """Test non-compliant platforms are not registered.""" diff --git a/tests/components/resolution_center/test_issue_registry.py b/tests/components/resolution_center/test_issue_registry.py index a0dffaacc8f..3f5cc235a19 100644 --- a/tests/components/resolution_center/test_issue_registry.py +++ b/tests/components/resolution_center/test_issue_registry.py @@ -64,8 +64,10 @@ async def test_load_issues(hass: HomeAssistant) -> None: assert list(registry.issues) == list(registry2.issues) issue1_registry2 = registry2.async_get_issue("test", "issue_1") + assert issue1_registry2.created == issue1.created assert issue1_registry2.dismissed_version == issue1.dismissed_version issue2_registry2 = registry2.async_get_issue("test", "issue_2") + assert issue2_registry2.created == issue2.created assert issue2_registry2.dismissed_version == issue2.dismissed_version @@ -76,11 +78,13 @@ async def test_loading_issues_from_storage(hass: HomeAssistant, hass_storage) -> "data": { "issues": [ { + "created": "2022-07-19T09:41:13.746514+00:00", "dismissed_version": "2022.7.0.dev0", "domain": "test", "issue_id": "issue_1", }, { + "created": "2022-07-19T19:41:13.746514+00:00", "dismissed_version": None, "domain": "test", "issue_id": "issue_2", diff --git a/tests/components/resolution_center/test_websocket_api.py b/tests/components/resolution_center/test_websocket_api.py index 42899065121..8701996a535 100644 --- a/tests/components/resolution_center/test_websocket_api.py +++ b/tests/components/resolution_center/test_websocket_api.py @@ -4,6 +4,7 @@ from __future__ import annotations from http import HTTPStatus from unittest.mock import ANY, AsyncMock, Mock +from freezegun import freeze_time import pytest import voluptuous as vol @@ -56,6 +57,7 @@ async def create_issues(hass, ws_client): "issues": [ dict( issue, + created=ANY, dismissed=False, dismissed_version=None, ) @@ -146,6 +148,7 @@ async def test_dismiss_issue(hass: HomeAssistant, hass_ws_client) -> None: "issues": [ dict( issue, + created=ANY, dismissed=True, dismissed_version=ha_version, ) @@ -188,6 +191,7 @@ async def test_fix_non_existing_issue( "issues": [ dict( issue, + created=ANY, dismissed=False, dismissed_version=None, ) @@ -333,6 +337,7 @@ async def test_step_unauth( assert resp.status == HTTPStatus.UNAUTHORIZED +@freeze_time("2022-07-19 07:53:05") async def test_list_issues(hass: HomeAssistant, hass_ws_client) -> None: """Test we can list issues.""" assert await async_setup_component(hass, DOMAIN, {}) @@ -389,6 +394,7 @@ async def test_list_issues(hass: HomeAssistant, hass_ws_client) -> None: "issues": [ dict( issue, + created="2022-07-19T07:53:05+00:00", dismissed=False, dismissed_version=None, )