Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions custom_components/hacs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,11 @@ async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->

unload_ok = await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS)

hacs.set_stage(None)
hacs.disable_hacs(HacsDisabledReason.REMOVED)

hass.data.pop(DOMAIN, None)
# Only clean up if unload was successful
if unload_ok:
hacs.set_stage(None)
hacs.disable_hacs(HacsDisabledReason.REMOVED)
hass.data.pop(DOMAIN, None)

return unload_ok

Expand Down
5 changes: 4 additions & 1 deletion custom_components/hacs/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback,
) -> None:
"""Setup switch platform."""
hacs: HacsBase = hass.data[DOMAIN]
if (hacs := hass.data.get(DOMAIN)) is None:
# HACS is not properly initialized
return

async_add_entities(
HacsRepositoryPreReleaseSwitchEntity(hacs=hacs, repository=repository)
for repository in hacs.repositories.list_downloaded
Expand Down
5 changes: 4 additions & 1 deletion custom_components/hacs/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Setup update platform."""
hacs: HacsBase = hass.data[DOMAIN]
if (hacs := hass.data.get(DOMAIN)) is None:
# HACS is not properly initialized
return

async_add_entities(
HacsRepositoryUpdateEntity(hacs=hacs, repository=repository)
for repository in hacs.repositories.list_downloaded
Expand Down
29 changes: 24 additions & 5 deletions custom_components/hacs/websocket/repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ async def hacs_repositories_list(
msg: dict[str, Any],
) -> None:
"""List repositories."""
hacs: HacsBase = hass.data.get(DOMAIN)
if (hacs := hass.data.get(DOMAIN)) is None:
# HACS is not properly initialized
connection.send_error(msg["id"], "hacs_not_initialized", "HACS is not properly initialized")
return

connection.send_message(
websocket_api.result_message(
msg["id"],
Expand Down Expand Up @@ -91,7 +95,10 @@ async def hacs_repositories_clear_new(
msg: dict[str, Any],
) -> None:
"""Clear new repositories for specific categories."""
hacs: HacsBase = hass.data.get(DOMAIN)
if (hacs := hass.data.get(DOMAIN)) is None:
# HACS is not properly initialized
connection.send_error(msg["id"], "hacs_not_initialized", "HACS is not properly initialized")
return

if repo := msg.get("repository"):
repository = hacs.repositories.get_by_id(repo)
Expand Down Expand Up @@ -123,7 +130,11 @@ async def hacs_repositories_removed(
msg: dict[str, Any],
) -> None:
"""Get information about removed repositories."""
hacs: HacsBase = hass.data.get(DOMAIN)
if (hacs := hass.data.get(DOMAIN)) is None:
# HACS is not properly initialized
connection.send_error(msg["id"], "hacs_not_initialized", "HACS is not properly initialized")
return

content = []
for repo in hacs.repositories.list_removed:
if repo.repository not in hacs.common.ignored_repositories:
Expand All @@ -146,7 +157,11 @@ async def hacs_repositories_add(
msg: dict[str, Any],
) -> None:
"""Add custom repositoriy."""
hacs: HacsBase = hass.data.get(DOMAIN)
if (hacs := hass.data.get(DOMAIN)) is None:
# HACS is not properly initialized
connection.send_error(msg["id"], "hacs_not_initialized", "HACS is not properly initialized")
return

repository = regex.extract_repository_from_url(msg["repository"])
category = msg["category"]

Expand Down Expand Up @@ -207,7 +222,11 @@ async def hacs_repositories_remove(
msg: dict[str, Any],
) -> None:
"""Remove custom repositoriy."""
hacs: HacsBase = hass.data.get(DOMAIN)
if (hacs := hass.data.get(DOMAIN)) is None:
# HACS is not properly initialized
connection.send_error(msg["id"], "hacs_not_initialized", "HACS is not properly initialized")
return

repository = hacs.repositories.get_by_id(msg["repository"])

repository.remove()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/websocket/test_repositories_not_initialized.py::test_websocket_repositories_commands_hacs_not_initialized[hacs/repositories/add-payload6]": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/websocket/test_repositories_not_initialized.py::test_websocket_repositories_commands_hacs_not_initialized[hacs/repositories/clear_new-payload2]": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/websocket/test_repositories_not_initialized.py::test_websocket_repositories_commands_hacs_not_initialized[hacs/repositories/clear_new-payload3]": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/websocket/test_repositories_not_initialized.py::test_websocket_repositories_commands_hacs_not_initialized[hacs/repositories/clear_new-payload4]": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/websocket/test_repositories_not_initialized.py::test_websocket_repositories_commands_hacs_not_initialized[hacs/repositories/list-payload0]": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/websocket/test_repositories_not_initialized.py::test_websocket_repositories_commands_hacs_not_initialized[hacs/repositories/list-payload1]": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/websocket/test_repositories_not_initialized.py::test_websocket_repositories_commands_hacs_not_initialized[hacs/repositories/remove-payload7]": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/websocket/test_repositories_not_initialized.py::test_websocket_repositories_commands_hacs_not_initialized[hacs/repositories/removed-payload5]": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/websocket/test_repositories_not_initialized.py::test_websocket_repositories_list_with_hacs_initialized": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}
1 change: 1 addition & 0 deletions tests/websocket/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests for websocket when HACS is not initialized."""
62 changes: 62 additions & 0 deletions tests/websocket/test_repositories_not_initialized.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Tests for websocket repositories commands when HACS is not initialized."""

from collections.abc import Generator

from homeassistant.core import HomeAssistant
import pytest

from custom_components.hacs.const import DOMAIN

from tests.common import WSClient, get_hacs


@pytest.mark.parametrize(
"command,payload",
[
("hacs/repositories/list", {}),
("hacs/repositories/list", {"categories": ["integration"]}),
("hacs/repositories/clear_new", {}),
("hacs/repositories/clear_new", {"categories": ["plugin"]}),
("hacs/repositories/clear_new", {"repository": "test/repo"}),
("hacs/repositories/removed", {}),
("hacs/repositories/add", {"repository": "test/repo", "category": "integration"}),
("hacs/repositories/remove", {"repository": "123"}),
],
)
async def test_websocket_repositories_commands_hacs_not_initialized(
hass: HomeAssistant,
setup_integration: Generator, # Need this to register websocket commands
ws_client: WSClient,
command: str,
payload: dict,
):
"""Test that websocket repository commands return proper errors when HACS is not initialized."""
# Ensure HACS is not in hass.data (not initialized)
hass.data.pop(DOMAIN, None)

# Send websocket command
response = await ws_client.send_and_receive_json(command, payload)

# Verify error response
assert response["success"] is False
assert response["error"]["code"] == "hacs_not_initialized"
assert response["error"]["message"] == "HACS is not properly initialized"


async def test_websocket_repositories_list_with_hacs_initialized(
hass: HomeAssistant,
setup_integration: Generator, # This sets up HACS properly
ws_client: WSClient,
):
"""Test that websocket works normally when HACS is properly initialized."""
# Verify HACS is properly initialized
hacs = get_hacs(hass)
assert hacs is not None

# Send websocket command - should work normally
response = await ws_client.send_and_receive_json("hacs/repositories/list", {})

# Verify successful response (should be a list, not an error)
assert response["success"] is True
assert "result" in response
assert isinstance(response["result"], list)