feat: brand-new interface

This was initally generated by ai, but later has been heavily edited.
The reason why it has been implemented is that there are plans to
implement more features to ui, but it becomes hard to add new features
to plain js, so I decided to rewrite it in typescript.

Yet because it is still ai slop, it is still possible to enable old
interface via configuration, even though new interface is turned on by
default to get feedback
This commit is contained in:
2026-02-25 22:49:38 +02:00
parent 49ebbc34fa
commit d71dbde30b
153 changed files with 5754 additions and 132 deletions

View File

@@ -549,9 +549,6 @@ def test_walk(resource_path_root: Path) -> None:
must traverse directory recursively
"""
expected = sorted([
resource_path_root / "core" / "ahriman.ini",
resource_path_root / "core" / "arcanisrepo.files.tar.gz",
resource_path_root / "core" / "logging.ini",
resource_path_root / "models" / "aur_error",
resource_path_root / "models" / "big_file_checksum",
resource_path_root / "models" / "empty_file_checksum",
@@ -569,26 +566,6 @@ def test_walk(resource_path_root: Path) -> None:
resource_path_root / "models" / "package_yay_pkgbuild",
resource_path_root / "models" / "pkgbuild",
resource_path_root / "models" / "utf8",
resource_path_root / "web" / "templates" / "build-status" / "alerts.jinja2",
resource_path_root / "web" / "templates" / "build-status" / "dashboard.jinja2",
resource_path_root / "web" / "templates" / "build-status" / "key-import-modal.jinja2",
resource_path_root / "web" / "templates" / "build-status" / "login-modal.jinja2",
resource_path_root / "web" / "templates" / "build-status" / "package-add-modal.jinja2",
resource_path_root / "web" / "templates" / "build-status" / "package-info-modal.jinja2",
resource_path_root / "web" / "templates" / "build-status" / "package-rebuild-modal.jinja2",
resource_path_root / "web" / "templates" / "build-status" / "table.jinja2",
resource_path_root / "web" / "templates" / "static" / "favicon.ico",
resource_path_root / "web" / "templates" / "static" / "logo.svg",
resource_path_root / "web" / "templates" / "utils" / "bootstrap-scripts.jinja2",
resource_path_root / "web" / "templates" / "utils" / "style.jinja2",
resource_path_root / "web" / "templates" / "api.jinja2",
resource_path_root / "web" / "templates" / "build-status.jinja2",
resource_path_root / "web" / "templates" / "email-index.jinja2",
resource_path_root / "web" / "templates" / "error.jinja2",
resource_path_root / "web" / "templates" / "repo-index.jinja2",
resource_path_root / "web" / "templates" / "rss.jinja2",
resource_path_root / "web" / "templates" / "shell",
resource_path_root / "web" / "templates" / "telegram-index.jinja2",
])
local_files = list(sorted(walk(resource_path_root)))
local_files = list(path for path in sorted(walk(resource_path_root)) if path.parent.name == "models")
assert local_files == expected

View File

@@ -0,0 +1 @@
# schema testing goes in view class tests

View File

@@ -0,0 +1 @@
# schema testing goes in view class tests

View File

@@ -0,0 +1 @@
# schema testing goes in view class tests

View File

@@ -0,0 +1,26 @@
import pytest
from aiohttp.web import Application
from ahriman import __version__
from ahriman.models.repository_id import RepositoryId
from ahriman.web.server_info import server_info
from ahriman.web.views.index import IndexView
async def test_server_info(application: Application, repository_id: RepositoryId) -> None:
"""
must generate server info
"""
request = pytest.helpers.request(application, "", "GET")
view = IndexView(request)
result = await server_info(view)
assert result["repositories"] == [{"id": repository_id.id, **repository_id.view()}]
assert not result["auth"]["enabled"]
assert result["auth"]["username"] is None
assert result["auth"]["control"]
assert result["version"] == __version__
assert result["autorefresh_intervals"] == []
assert result["docs_enabled"]
assert result["index_url"] is None

View File

@@ -35,6 +35,6 @@ async def test_get(client: TestClient, repository_id: RepositoryId) -> None:
json = await response.json()
assert not response_schema.validate(json)
assert json["repositories"] == [repository_id.view()]
assert json["repositories"] == [{"id": repository_id.id, **repository_id.view()}]
assert not json["auth"]
assert json["version"] == __version__

View File

@@ -0,0 +1,43 @@
import pytest
from aiohttp.test_utils import TestClient
from ahriman import __version__
from ahriman.models.repository_id import RepositoryId
from ahriman.models.user_access import UserAccess
from ahriman.web.views.v2.status.info import InfoView
async def test_get_permission() -> None:
"""
must return correct permission for the request
"""
for method in ("GET",):
request = pytest.helpers.request("", "", method)
assert await InfoView.get_permission(request) == UserAccess.Unauthorized
def test_routes() -> None:
"""
must return correct routes
"""
assert InfoView.ROUTES == ["/api/v2/info"]
async def test_get(client: TestClient, repository_id: RepositoryId) -> None:
"""
must return service information
"""
response_schema = pytest.helpers.schema_response(InfoView.get)
response = await client.get("/api/v2/info")
assert response.ok
json = await response.json()
assert not response_schema.validate(json)
assert json["repositories"] == [{"id": repository_id.id, **repository_id.view()}]
assert not json["auth"]["enabled"]
assert json["auth"]["control"]
assert json["version"] == __version__
assert json["autorefresh_intervals"] == []
assert json["docs_enabled"]