"""Integration tests for channels dashboard_router endpoints.""" from __future__ import annotations import httpx import pytest from .conftest import BASE_URL, DEFAULT_CHANNEL_TYPE, ISO_TIME_END, ISO_TIME_START pytestmark = [pytest.mark.asyncio, pytest.mark.integration] DASHBOARD_URL = f"{BASE_URL}/dashboard" # ============================================================================= # === Auth three-tier for /dashboard/overview === # ============================================================================= async def test_get_dashboard_overview_requires_auth(test_client: httpx.AsyncClient): # Act response = await test_client.get(f"{DASHBOARD_URL}/overview") # Assert assert response.status_code == 401, response.text async def test_get_dashboard_overview_requires_admin(test_client: httpx.AsyncClient, standard_user): # Act response = await test_client.get(f"{DASHBOARD_URL}/overview", headers=standard_user["headers"]) # Assert assert response.status_code == 403, response.text async def test_admin_can_get_dashboard_overview(test_client: httpx.AsyncClient, admin_headers): # Act response = await test_client.get(f"{DASHBOARD_URL}/overview", headers=admin_headers) # Assert assert response.status_code == 200, response.text payload = response.json() assert payload["success"] is True assert "data" in payload # ============================================================================= # === All dashboard endpoints with admin return 200 === # ============================================================================= async def test_admin_can_get_dashboard_accounts(test_client: httpx.AsyncClient, admin_headers): # Act response = await test_client.get( f"{DASHBOARD_URL}/accounts", params={"channel_type": DEFAULT_CHANNEL_TYPE}, headers=admin_headers, ) # Assert assert response.status_code == 200, response.text payload = response.json() assert payload["success"] is True assert "data" in payload async def test_admin_can_get_dashboard_messages(test_client: httpx.AsyncClient, admin_headers): # Act response = await test_client.get( f"{DASHBOARD_URL}/messages", params={ "channel_type": DEFAULT_CHANNEL_TYPE, "start_time": ISO_TIME_START, "end_time": ISO_TIME_END, }, headers=admin_headers, ) # Assert assert response.status_code == 200, response.text payload = response.json() assert payload["success"] is True assert "data" in payload async def test_admin_can_get_dashboard_sessions(test_client: httpx.AsyncClient, admin_headers): # Act response = await test_client.get( f"{DASHBOARD_URL}/sessions", params={"channel_type": DEFAULT_CHANNEL_TYPE}, headers=admin_headers, ) # Assert assert response.status_code == 200, response.text payload = response.json() assert payload["success"] is True assert "data" in payload async def test_admin_can_get_dashboard_delivery(test_client: httpx.AsyncClient, admin_headers): # Act response = await test_client.get( f"{DASHBOARD_URL}/delivery", params={ "channel_type": DEFAULT_CHANNEL_TYPE, "start_time": ISO_TIME_START, "end_time": ISO_TIME_END, }, headers=admin_headers, ) # Assert assert response.status_code == 200, response.text payload = response.json() assert payload["success"] is True assert "data" in payload async def test_admin_can_get_dashboard_realtime(test_client: httpx.AsyncClient, admin_headers): # Act response = await test_client.get( f"{DASHBOARD_URL}/realtime", params={"channel_type": DEFAULT_CHANNEL_TYPE}, headers=admin_headers, ) # Assert assert response.status_code == 200, response.text payload = response.json() assert payload["success"] is True assert "data" in payload # ============================================================================= # === /dashboard/realtime window_seconds validation === # ============================================================================= async def test_dashboard_realtime_rejects_window_below_min(test_client: httpx.AsyncClient, admin_headers): # Act — window_seconds=9 violates ge=10 response = await test_client.get( f"{DASHBOARD_URL}/realtime", params={"window_seconds": 9}, headers=admin_headers, ) # Assert assert response.status_code == 422, response.text async def test_dashboard_realtime_rejects_window_above_max(test_client: httpx.AsyncClient, admin_headers): # Act — window_seconds=301 violates le=300 response = await test_client.get( f"{DASHBOARD_URL}/realtime", params={"window_seconds": 301}, headers=admin_headers, ) # Assert assert response.status_code == 422, response.text # ============================================================================= # === /dashboard/delivery invalid time format === # ============================================================================= async def test_dashboard_delivery_rejects_invalid_start_time_format(test_client: httpx.AsyncClient, admin_headers): # Act — "not-a-date" is not ISO 8601, parse_datetime raises ValidationError (400) response = await test_client.get( f"{DASHBOARD_URL}/delivery", params={"start_time": "not-a-date"}, headers=admin_headers, ) # Assert assert response.status_code == 400, response.text