主要更新: - 更新代理商端文档,明确项目由品牌方分配流程 - 新增Brief配置详情页(已配置)设计稿 - 完善工作台紧急待办中品牌新任务功能 - 整理Pencil设计文件中代理商端页面顺序 - 新增后端FastAPI框架及核心API - 新增前端Next.js页面和组件库 - 添加.gitignore排除构建和缓存文件 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
63 lines
2.6 KiB
Python
63 lines
2.6 KiB
Python
"""
|
|
一致性指标 API 测试 (TDD - 红色阶段)
|
|
双轨制: Rolling 30 Days + Snapshot 周/月
|
|
维度: Influencer + Rule Type
|
|
"""
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
|
|
from app.schemas.review import ConsistencyMetricsResponse, ConsistencyWindow, ViolationType
|
|
|
|
|
|
class TestConsistencyMetrics:
|
|
"""一致性指标查询"""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_requires_influencer_id(self, client: AsyncClient):
|
|
"""缺少 influencer_id 返回 422"""
|
|
response = await client.get("/api/v1/metrics/consistency?window=rolling_30d")
|
|
assert response.status_code == 422
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_rolling_30d_returns_metrics(self, client: AsyncClient, influencer_id: str):
|
|
"""Rolling 30 Days 返回指标"""
|
|
response = await client.get(
|
|
f"/api/v1/metrics/consistency?influencer_id={influencer_id}&window=rolling_30d"
|
|
)
|
|
assert response.status_code == 200
|
|
parsed = ConsistencyMetricsResponse.model_validate(response.json())
|
|
assert parsed.influencer_id == influencer_id
|
|
assert parsed.window == ConsistencyWindow.ROLLING_30D
|
|
assert parsed.period_start < parsed.period_end
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_snapshot_week_returns_metrics(self, client: AsyncClient, influencer_id: str):
|
|
"""Snapshot 周度返回指标"""
|
|
response = await client.get(
|
|
f"/api/v1/metrics/consistency?influencer_id={influencer_id}&window=snapshot_week"
|
|
)
|
|
assert response.status_code == 200
|
|
parsed = ConsistencyMetricsResponse.model_validate(response.json())
|
|
assert parsed.window == ConsistencyWindow.SNAPSHOT_WEEK
|
|
assert parsed.period_start < parsed.period_end
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_filter_by_rule_type(self, client: AsyncClient, influencer_id: str):
|
|
"""按规则类型筛选"""
|
|
response = await client.get(
|
|
f"/api/v1/metrics/consistency?influencer_id={influencer_id}"
|
|
"&window=rolling_30d&rule_type=forbidden_word"
|
|
)
|
|
assert response.status_code == 200
|
|
parsed = ConsistencyMetricsResponse.model_validate(response.json())
|
|
if parsed.metrics:
|
|
assert all(m.rule_type == ViolationType.FORBIDDEN_WORD for m in parsed.metrics)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_invalid_window_returns_422(self, client: AsyncClient, influencer_id: str):
|
|
"""非法窗口返回 422"""
|
|
response = await client.get(
|
|
f"/api/v1/metrics/consistency?influencer_id={influencer_id}&window=invalid_window"
|
|
)
|
|
assert response.status_code == 422
|