ForcePilot/backend/test/integration/api/channels/test_analytics_router.py
Kris 04a2472014 test(channel): add full integration test suite for channels module
1. 新增channels模块集成测试目录与基础fixture
2. 为capability、doctor、reports、dashboard、directory、webhook、wizard、health、analytics、allowlist、config等路由编写完整的鉴权、参数校验与异常场景测试
3. 修复基础集成测试setup,新增external/scheduler/channel数据库schema初始化步骤
2026-07-02 03:25:27 +08:00

272 lines
7.6 KiB
Python

"""Integration tests for channels analytics_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]
ANALYTICS_URL = f"{BASE_URL}/analytics"
def _valid_params(**overrides) -> dict:
"""Build valid query params (start_time + end_time) for analytics endpoints."""
params = {"start_time": ISO_TIME_START, "end_time": ISO_TIME_END}
params.update(overrides)
return params
# =============================================================================
# === Auth three-tier for /analytics/messages ===
# =============================================================================
async def test_analyze_messages_requires_auth(test_client: httpx.AsyncClient):
# Act
response = await test_client.get(f"{ANALYTICS_URL}/messages", params=_valid_params())
# Assert
assert response.status_code == 401, response.text
async def test_analyze_messages_requires_admin(
test_client: httpx.AsyncClient, standard_user
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/messages",
params=_valid_params(),
headers=standard_user["headers"],
)
# Assert
assert response.status_code == 403, response.text
async def test_admin_can_analyze_messages(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/messages",
params=_valid_params(),
headers=admin_headers,
)
# Assert
assert response.status_code == 200, response.text
payload = response.json()
assert payload["success"] is True
assert "data" in payload
# =============================================================================
# === Parameter validation for /analytics/messages ===
# =============================================================================
async def test_analyze_messages_rejects_missing_start_time(
test_client: httpx.AsyncClient, admin_headers
):
# Arrange — omit start_time
params = {"end_time": ISO_TIME_END}
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/messages", params=params, headers=admin_headers
)
# Assert
assert response.status_code == 422, response.text
async def test_analyze_messages_rejects_missing_end_time(
test_client: httpx.AsyncClient, admin_headers
):
# Arrange — omit end_time
params = {"start_time": ISO_TIME_START}
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/messages", params=params, headers=admin_headers
)
# Assert
assert response.status_code == 422, response.text
# =============================================================================
# === All analytics endpoints with valid params return 200 ===
# =============================================================================
async def test_admin_can_get_message_distribution(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/messages/distribution",
params=_valid_params(),
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_analyze_sessions(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/sessions",
params=_valid_params(),
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_analyze_delivery(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/delivery",
params=_valid_params(),
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_delivery_latency(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/delivery/latency",
params=_valid_params(),
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_delivery_funnel(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/delivery/funnel",
params=_valid_params(),
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_analyze_accounts(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/accounts",
params=_valid_params(),
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_analyze_peers(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/peers",
params=_valid_params(),
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_analyze_content_review(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/content-review",
params=_valid_params(),
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_analyze_messages_with_channel_type(
test_client: httpx.AsyncClient, admin_headers
):
# Act
response = await test_client.get(
f"{ANALYTICS_URL}/messages",
params=_valid_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
# =============================================================================
# === /analytics/peers limit validation ===
# =============================================================================
async def test_analyze_peers_rejects_limit_zero(
test_client: httpx.AsyncClient, admin_headers
):
# Act — limit=0 violates ge=1
response = await test_client.get(
f"{ANALYTICS_URL}/peers",
params=_valid_params(limit=0),
headers=admin_headers,
)
# Assert
assert response.status_code == 422, response.text
async def test_analyze_peers_rejects_limit_over_max(
test_client: httpx.AsyncClient, admin_headers
):
# Act — limit=501 violates le=500
response = await test_client.get(
f"{ANALYTICS_URL}/peers",
params=_valid_params(limit=501),
headers=admin_headers,
)
# Assert
assert response.status_code == 422, response.text