47 lines
1.7 KiB
Python
47 lines
1.7 KiB
Python
|
|
"""Dashboard widget API tests — Task 5.25."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from httpx import AsyncClient
|
||
|
|
|
||
|
|
from tests.conftest import ORIGIN_HEADER, login_client, seed_tenant_and_users
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
class TestDashboardWidgets:
|
||
|
|
"""GET /api/v1/dashboard/widgets — list available widgets."""
|
||
|
|
|
||
|
|
async def test_list_widgets_returns_200(self, client: AsyncClient, db_session):
|
||
|
|
"""Dashboard widgets endpoint returns 200 with items list."""
|
||
|
|
await seed_tenant_and_users(db_session)
|
||
|
|
await login_client(client, "admin@tenanta.com")
|
||
|
|
|
||
|
|
resp = await client.get("/api/v1/dashboard/widgets", headers=ORIGIN_HEADER)
|
||
|
|
assert resp.status_code == 200
|
||
|
|
data = resp.json()
|
||
|
|
assert "items" in data
|
||
|
|
assert "total" in data
|
||
|
|
assert isinstance(data["items"], list)
|
||
|
|
|
||
|
|
async def test_list_widgets_requires_auth(self, client: AsyncClient, db_session):
|
||
|
|
"""Dashboard widgets endpoint requires authentication."""
|
||
|
|
await seed_tenant_and_users(db_session)
|
||
|
|
|
||
|
|
resp = await client.get("/api/v1/dashboard/widgets", headers=ORIGIN_HEADER)
|
||
|
|
assert resp.status_code == 401
|
||
|
|
|
||
|
|
async def test_list_widgets_has_plugin_name(self, client: AsyncClient, db_session):
|
||
|
|
"""Each widget should include the contributing plugin name."""
|
||
|
|
await seed_tenant_and_users(db_session)
|
||
|
|
await login_client(client, "admin@tenanta.com")
|
||
|
|
|
||
|
|
resp = await client.get("/api/v1/dashboard/widgets", headers=ORIGIN_HEADER)
|
||
|
|
assert resp.status_code == 200
|
||
|
|
data = resp.json()
|
||
|
|
for widget in data["items"]:
|
||
|
|
assert "plugin_name" in widget
|
||
|
|
assert "id" in widget
|
||
|
|
assert "component" in widget
|
||
|
|
assert "label_key" in widget
|