Build and Push / build (release) Successful in 1m28s
- Dashboard domain with Quick Links CRUD + reorder endpoints - Dashboard widgets management endpoints - Database migrations for quick_links and dashboard_widgets tables - Static file controller for Organizr widgets - Default local user when OIDC is disabled - Domain-based architecture refactor (src/domains/, src/shared/) - Test suite updated for new structure (285 tests passing) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
200 lines
7.3 KiB
Python
200 lines
7.3 KiB
Python
"""Tests for dashboard endpoints registration and OpenAPI spec."""
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
from src.main import app
|
|
|
|
|
|
@pytest.fixture
|
|
def client():
|
|
"""Create a test client."""
|
|
return TestClient(app)
|
|
|
|
|
|
class TestDashboardOpenAPISpec:
|
|
"""Test that dashboard endpoints are documented in OpenAPI spec."""
|
|
|
|
def test_quick_links_list_in_openapi(self, client):
|
|
"""Quick links list endpoint should be in OpenAPI spec."""
|
|
response = client.get("/openapi.json")
|
|
assert response.status_code == 200
|
|
spec = response.json()
|
|
assert "/dashboard/quick-links" in spec["paths"]
|
|
|
|
def test_quick_links_get_in_openapi(self, client):
|
|
"""Quick links get endpoint should be in OpenAPI spec."""
|
|
response = client.get("/openapi.json")
|
|
assert response.status_code == 200
|
|
spec = response.json()
|
|
assert "/dashboard/quick-links/{link_id}" in spec["paths"]
|
|
|
|
def test_quick_links_reorder_in_openapi(self, client):
|
|
"""Quick links reorder endpoint should be in OpenAPI spec."""
|
|
response = client.get("/openapi.json")
|
|
assert response.status_code == 200
|
|
spec = response.json()
|
|
assert "/dashboard/quick-links/reorder" in spec["paths"]
|
|
|
|
def test_widgets_list_in_openapi(self, client):
|
|
"""Widgets list endpoint should be in OpenAPI spec."""
|
|
response = client.get("/openapi.json")
|
|
assert response.status_code == 200
|
|
spec = response.json()
|
|
assert "/dashboard/widgets" in spec["paths"]
|
|
|
|
def test_widgets_get_in_openapi(self, client):
|
|
"""Widgets get endpoint should be in OpenAPI spec."""
|
|
response = client.get("/openapi.json")
|
|
assert response.status_code == 200
|
|
spec = response.json()
|
|
assert "/dashboard/widgets/{widget_id}" in spec["paths"]
|
|
|
|
def test_quick_links_supports_crud_operations(self, client):
|
|
"""Quick links should support all CRUD operations."""
|
|
response = client.get("/openapi.json")
|
|
spec = response.json()
|
|
|
|
# List endpoint
|
|
list_path = spec["paths"].get("/dashboard/quick-links", {})
|
|
assert "get" in list_path # List
|
|
assert "post" in list_path # Create
|
|
|
|
# Item endpoint
|
|
item_path = spec["paths"].get("/dashboard/quick-links/{link_id}", {})
|
|
assert "get" in item_path # Read
|
|
assert "put" in item_path # Update
|
|
assert "delete" in item_path # Delete
|
|
|
|
def test_widgets_supports_crud_operations(self, client):
|
|
"""Widgets should support all CRUD operations."""
|
|
response = client.get("/openapi.json")
|
|
spec = response.json()
|
|
|
|
# List endpoint
|
|
list_path = spec["paths"].get("/dashboard/widgets", {})
|
|
assert "get" in list_path # List
|
|
assert "post" in list_path # Create
|
|
|
|
# Item endpoint
|
|
item_path = spec["paths"].get("/dashboard/widgets/{widget_id}", {})
|
|
assert "get" in item_path # Read
|
|
assert "put" in item_path # Update
|
|
assert "delete" in item_path # Delete
|
|
|
|
|
|
class TestDashboardSchemaValidation:
|
|
"""Test that request validation works correctly."""
|
|
|
|
def test_create_quick_link_requires_title(self, client):
|
|
"""Create quick link should require title (422 for validation)."""
|
|
response = client.post(
|
|
"/dashboard/quick-links",
|
|
json={
|
|
"url": "https://example.com",
|
|
},
|
|
)
|
|
# Either 422 for validation or 401/403/500 for auth
|
|
assert response.status_code in [401, 403, 422, 500]
|
|
|
|
def test_create_widget_requires_widget_type(self, client):
|
|
"""Create widget should require widget_type (422 for validation)."""
|
|
response = client.post(
|
|
"/dashboard/widgets",
|
|
json={},
|
|
)
|
|
assert response.status_code in [401, 403, 422, 500]
|
|
|
|
def test_reorder_requires_link_ids(self, client):
|
|
"""Reorder should require link_ids list (422 for validation)."""
|
|
response = client.post(
|
|
"/dashboard/quick-links/reorder",
|
|
json={},
|
|
)
|
|
assert response.status_code in [401, 403, 422, 500]
|
|
|
|
|
|
class TestDashboardControllerInit:
|
|
"""Test dashboard controller initialization."""
|
|
|
|
def test_controller_module_imports(self):
|
|
"""Dashboard controller should be importable."""
|
|
from src.domains.dashboard.controller import DashboardController, dashboard_controller
|
|
assert DashboardController is not None
|
|
assert dashboard_controller is not None
|
|
|
|
def test_controller_has_correct_prefix(self):
|
|
"""Dashboard controller should have correct prefix."""
|
|
from src.domains.dashboard.controller import dashboard_controller
|
|
assert dashboard_controller.prefix == "/dashboard"
|
|
|
|
def test_controller_has_correct_tags(self):
|
|
"""Dashboard controller should have correct tags."""
|
|
from src.domains.dashboard.controller import dashboard_controller
|
|
assert "Dashboard" in dashboard_controller.tags
|
|
|
|
|
|
class TestDashboardServiceInit:
|
|
"""Test dashboard service initialization."""
|
|
|
|
def test_service_module_imports(self):
|
|
"""Dashboard service should be importable."""
|
|
from src.domains.dashboard.service import DashboardService, get_dashboard_service
|
|
assert DashboardService is not None
|
|
assert get_dashboard_service is not None
|
|
|
|
def test_service_singleton(self):
|
|
"""get_dashboard_service should return singleton."""
|
|
from src.domains.dashboard.service import get_dashboard_service
|
|
|
|
service1 = get_dashboard_service()
|
|
service2 = get_dashboard_service()
|
|
assert service1 is service2
|
|
|
|
|
|
class TestDashboardModels:
|
|
"""Test dashboard models."""
|
|
|
|
def test_quick_link_model_imports(self):
|
|
"""QuickLink model should be importable."""
|
|
from src.domains.dashboard.models import QuickLink
|
|
assert QuickLink is not None
|
|
|
|
def test_dashboard_widget_model_imports(self):
|
|
"""DashboardWidget model should be importable."""
|
|
from src.domains.dashboard.models import DashboardWidget
|
|
assert DashboardWidget is not None
|
|
|
|
|
|
class TestDashboardSchemas:
|
|
"""Test dashboard schemas."""
|
|
|
|
def test_quick_link_schemas_import(self):
|
|
"""QuickLink schemas should be importable."""
|
|
from src.domains.dashboard.schemas import (
|
|
QuickLinkCreate,
|
|
QuickLinkUpdate,
|
|
QuickLinkResponse,
|
|
QuickLinkListResponse,
|
|
QuickLinkReorderRequest,
|
|
QuickLinkReorderResponse,
|
|
)
|
|
assert QuickLinkCreate is not None
|
|
assert QuickLinkUpdate is not None
|
|
assert QuickLinkResponse is not None
|
|
assert QuickLinkListResponse is not None
|
|
assert QuickLinkReorderRequest is not None
|
|
assert QuickLinkReorderResponse is not None
|
|
|
|
def test_dashboard_widget_schemas_import(self):
|
|
"""DashboardWidget schemas should be importable."""
|
|
from src.domains.dashboard.schemas import (
|
|
DashboardWidgetCreate,
|
|
DashboardWidgetUpdate,
|
|
DashboardWidgetResponse,
|
|
DashboardWidgetListResponse,
|
|
)
|
|
assert DashboardWidgetCreate is not None
|
|
assert DashboardWidgetUpdate is not None
|
|
assert DashboardWidgetResponse is not None
|
|
assert DashboardWidgetListResponse is not None
|