mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-09-24 22:05:20 +01:00
- Added notification support via Apprise dependency - Notifications can be configured globally or per user, with full customization of events and notification type. - Added expanded ActivityCard for increased detail of each request, file info, and managing the attached file. - Enhanced tests
126 lines
5.3 KiB
Python
126 lines
5.3 KiB
Python
"""API-level tests for notifications settings and action routes."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
import uuid
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def main_module():
|
|
"""Import `shelfmark.main` with background startup disabled."""
|
|
with patch("shelfmark.download.orchestrator.start"):
|
|
import shelfmark.main as main
|
|
|
|
importlib.reload(main)
|
|
return main
|
|
|
|
|
|
@pytest.fixture
|
|
def client(main_module):
|
|
return main_module.app.test_client()
|
|
|
|
|
|
def _create_user(main_module, *, prefix: str, role: str) -> dict:
|
|
username = f"{prefix}-{uuid.uuid4().hex[:8]}"
|
|
return main_module.user_db.create_user(username=username, role=role)
|
|
|
|
|
|
def _set_session(client, *, user_id: str, db_user_id: int, is_admin: bool) -> None:
|
|
with client.session_transaction() as sess:
|
|
sess["user_id"] = user_id
|
|
sess["db_user_id"] = db_user_id
|
|
sess["is_admin"] = is_admin
|
|
|
|
|
|
class TestNotificationsSettingsApi:
|
|
def test_notifications_action_requires_admin(self, main_module, client):
|
|
user = _create_user(main_module, prefix="reader", role="user")
|
|
_set_session(client, user_id=user["username"], db_user_id=user["id"], is_admin=False)
|
|
|
|
with patch.object(main_module, "get_auth_mode", return_value="builtin"):
|
|
resp = client.post(
|
|
"/api/settings/notifications/action/test_admin_notification",
|
|
json={"ADMIN_NOTIFICATION_ROUTES": [{"event": "all", "url": "ntfys://ntfy.sh/demo"}]},
|
|
)
|
|
|
|
assert resp.status_code == 403
|
|
assert resp.json["error"] == "Admin access required"
|
|
|
|
def test_notifications_action_returns_400_when_no_routes(self, main_module, client):
|
|
admin = _create_user(main_module, prefix="admin", role="admin")
|
|
_set_session(client, user_id=admin["username"], db_user_id=admin["id"], is_admin=True)
|
|
|
|
with patch.object(main_module, "get_auth_mode", return_value="builtin"):
|
|
with patch("shelfmark.config.notifications_settings.load_config_file", return_value={}):
|
|
resp = client.post(
|
|
"/api/settings/notifications/action/test_admin_notification",
|
|
json={"ADMIN_NOTIFICATION_ROUTES": []},
|
|
)
|
|
|
|
assert resp.status_code == 400
|
|
assert resp.json["success"] is False
|
|
assert "Add at least one global notification URL route" in resp.json["message"]
|
|
|
|
def test_notifications_action_uses_unsaved_values(self, main_module, client):
|
|
admin = _create_user(main_module, prefix="admin", role="admin")
|
|
_set_session(client, user_id=admin["username"], db_user_id=admin["id"], is_admin=True)
|
|
|
|
captured: dict[str, object] = {}
|
|
|
|
def _fake_send_test_notification(urls):
|
|
captured["urls"] = urls
|
|
return {"success": True, "message": "test sent"}
|
|
|
|
with patch.object(main_module, "get_auth_mode", return_value="builtin"):
|
|
with patch("shelfmark.config.notifications_settings.load_config_file", return_value={}):
|
|
with patch(
|
|
"shelfmark.config.notifications_settings.send_test_notification",
|
|
side_effect=_fake_send_test_notification,
|
|
):
|
|
resp = client.post(
|
|
"/api/settings/notifications/action/test_admin_notification",
|
|
json={
|
|
"ADMIN_NOTIFICATION_ROUTES": [
|
|
{"event": "all", "url": " ntfys://ntfy.sh/shelfmark "},
|
|
{"event": "download_failed", "url": "ntfys://ntfy.sh/errors"},
|
|
{"event": "download_failed", "url": "ntfys://ntfy.sh/errors"},
|
|
],
|
|
},
|
|
)
|
|
|
|
assert resp.status_code == 200
|
|
assert resp.json["success"] is True
|
|
assert captured["urls"] == ["ntfys://ntfy.sh/shelfmark", "ntfys://ntfy.sh/errors"]
|
|
|
|
def test_notifications_put_and_get_round_trip_normalizes_values(self, main_module, client):
|
|
admin = _create_user(main_module, prefix="admin", role="admin")
|
|
_set_session(client, user_id=admin["username"], db_user_id=admin["id"], is_admin=True)
|
|
|
|
payload = {
|
|
"ADMIN_NOTIFICATION_ROUTES": [
|
|
{"event": "all", "url": " ntfys://ntfy.sh/shelfmark "},
|
|
{"event": "request_created", "url": ""},
|
|
{"event": "download_failed", "url": "ntfys://ntfy.sh/errors"},
|
|
{"event": "download_failed", "url": "ntfys://ntfy.sh/errors"},
|
|
],
|
|
}
|
|
|
|
with patch.object(main_module, "get_auth_mode", return_value="builtin"):
|
|
put_resp = client.put("/api/settings/notifications", json=payload)
|
|
get_resp = client.get("/api/settings/notifications")
|
|
|
|
assert put_resp.status_code == 200
|
|
assert put_resp.json["success"] is True
|
|
assert get_resp.status_code == 200
|
|
|
|
fields = {field["key"]: field for field in get_resp.json["fields"] if "key" in field}
|
|
assert fields["ADMIN_NOTIFICATION_ROUTES"]["value"] == [
|
|
{"event": ["all"], "url": "ntfys://ntfy.sh/shelfmark"},
|
|
{"event": ["request_created"], "url": ""},
|
|
{"event": ["download_failed"], "url": "ntfys://ntfy.sh/errors"},
|
|
]
|