Skip to content

Commit

Permalink
Fix doc and changelog API response for orphaned addons (#5082)
Browse files Browse the repository at this point in the history
* Fix doc and changelog API response for orphaned addons

* Use correct terminology in tests
  • Loading branch information
mdegat01 authored May 21, 2024
1 parent be6e39f commit c0c0c4b
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 3 deletions.
16 changes: 13 additions & 3 deletions supervisor/api/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,12 @@ async def addons_addon_logo(self, request: web.Request) -> bytes:
@api_process_raw(CONTENT_TYPE_TEXT)
async def addons_addon_changelog(self, request: web.Request) -> str:
"""Return changelog from add-on."""
addon = self._extract_addon(request)
# Frontend can't handle error response here, need to return 200 and error as text for now
try:
addon = self._extract_addon(request)
except APIError as err:
return str(err)

if not addon.with_changelog:
return f"No changelog found for add-on {addon.slug}!"

Expand All @@ -259,9 +264,14 @@ async def addons_addon_changelog(self, request: web.Request) -> str:
@api_process_raw(CONTENT_TYPE_TEXT)
async def addons_addon_documentation(self, request: web.Request) -> str:
"""Return documentation from add-on."""
addon = self._extract_addon(request)
# Frontend can't handle error response here, need to return 200 and error as text for now
try:
addon = self._extract_addon(request)
except APIError as err:
return str(err)

if not addon.with_documentation:
raise APIError(f"No documentation found for add-on {addon.slug}!")
return f"No documentation found for add-on {addon.slug}!"

with addon.path_documentation.open("r") as documentation:
return documentation.read()
Expand Down
75 changes: 75 additions & 0 deletions tests/api/test_store.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
"""Test Store API."""

import asyncio
from pathlib import Path
from unittest.mock import MagicMock, PropertyMock, patch

from aiohttp.test_utils import TestClient
import pytest

from supervisor.addons.addon import Addon
from supervisor.arch import CpuArch
from supervisor.config import CoreConfig
from supervisor.const import AddonState
from supervisor.coresys import CoreSys
from supervisor.docker.addon import DockerAddon
Expand Down Expand Up @@ -199,7 +201,80 @@ async def test_api_store_addons_no_changelog(
Currently the frontend expects a valid body even in the error case. Make sure that is
what the API returns.
"""
assert store_addon.with_changelog is False
resp = await api_client.get(f"/{resource}/{store_addon.slug}/changelog")
assert resp.status == 200
result = await resp.text()
assert result == "No changelog found for add-on test_store_addon!"


@pytest.mark.parametrize("resource", ["store/addons", "addons"])
async def test_api_detached_addon_changelog(
api_client: TestClient,
coresys: CoreSys,
install_addon_ssh: Addon,
tmp_supervisor_data: Path,
resource: str,
):
"""Test /store/addons/{addon}/changelog for an detached addon.
Currently the frontend expects a valid body even in the error case. Make sure that is
what the API returns.
"""
(addons_dir := tmp_supervisor_data / "addons" / "local").mkdir()
with patch.object(
CoreConfig, "path_addons_local", new=PropertyMock(return_value=addons_dir)
):
await coresys.store.load()

assert install_addon_ssh.is_detached is True
assert install_addon_ssh.with_changelog is False

resp = await api_client.get(f"/{resource}/{install_addon_ssh.slug}/changelog")
assert resp.status == 200
result = await resp.text()
assert result == "Addon local_ssh with version latest does not exist in the store"


@pytest.mark.parametrize("resource", ["store/addons", "addons"])
async def test_api_store_addons_no_documentation(
api_client: TestClient, coresys: CoreSys, store_addon: AddonStore, resource: str
):
"""Test /store/addons/{addon}/documentation REST API.
Currently the frontend expects a valid body even in the error case. Make sure that is
what the API returns.
"""
assert store_addon.with_documentation is False
resp = await api_client.get(f"/{resource}/{store_addon.slug}/documentation")
assert resp.status == 200
result = await resp.text()
assert result == "No documentation found for add-on test_store_addon!"


@pytest.mark.parametrize("resource", ["store/addons", "addons"])
async def test_api_detached_addon_documentation(
api_client: TestClient,
coresys: CoreSys,
install_addon_ssh: Addon,
tmp_supervisor_data: Path,
resource: str,
):
"""Test /store/addons/{addon}/changelog for an detached addon.
Currently the frontend expects a valid body even in the error case. Make sure that is
what the API returns.
"""
(addons_dir := tmp_supervisor_data / "addons" / "local").mkdir()
with patch.object(
CoreConfig, "path_addons_local", new=PropertyMock(return_value=addons_dir)
):
await coresys.store.load()

assert install_addon_ssh.is_detached is True
assert install_addon_ssh.with_documentation is False

resp = await api_client.get(f"/{resource}/{install_addon_ssh.slug}/documentation")
assert resp.status == 200
result = await resp.text()
assert result == "Addon local_ssh with version latest does not exist in the store"

0 comments on commit c0c0c4b

Please sign in to comment.