## 根因 `apps.api.src.*` 需倉庫根目錄在 sys.path 才能透過 PEP 420 namespace package 解析(因 apps/ 和 apps/api/ 無 __init__.py)。 - CI rootdir=repo root → 可解析(但脆弱依賴) - 本地 pytest rootdir=apps/api → 解析失敗 → 整個 src.models.__init__ 炸 - CI 錯誤: `test_secret_redactor.py` 無法 import module ## 修復 src.models.__init__ 的 3 處 `apps.api.src.*` 改 `src.*` src.models.incident 的 1 處 `apps.api.src.*` 改 `src.*` tests/test_aider_event_models.py import path 統一 tests/test_secret_redactor.py import path 統一 ## 驗證 138 個 pytest test 全過(drift + rule_engine + approval_execution + aider_event + incident + secret_redactor) 所有 test 都用 `from src.*` 風格(codebase 既有慣例,pytest rootdir=apps/api 提供 src/ 作 import root) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
58 lines
1.4 KiB
Python
58 lines
1.4 KiB
Python
# apps/api/tests/test_aider_event_models.py | 2026-04-20 @ Asia/Taipei
|
|
from datetime import datetime, timezone, timedelta
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
from src.models.aider import AiderEventIn, AiderBatchIn
|
|
|
|
TAIPEI = timezone(timedelta(hours=8))
|
|
|
|
|
|
def _base(t="session_start", payload=None):
|
|
return {
|
|
"ts": datetime(2026, 4, 20, 10, 0, tzinfo=TAIPEI).isoformat(),
|
|
"session_id": "01J7XYZABC",
|
|
"host": "ogt-mac",
|
|
"type": t,
|
|
"payload": payload or {},
|
|
}
|
|
|
|
|
|
def test_accepts_all_7_types():
|
|
for t in ("session_start", "file_edit", "error", "commit",
|
|
"silent_timeout", "session_end", "raw"):
|
|
ev = AiderEventIn(**_base(t=t))
|
|
assert ev.type == t
|
|
|
|
|
|
def test_rejects_unknown_type():
|
|
with pytest.raises(ValidationError):
|
|
AiderEventIn(**_base(t="bogus"))
|
|
|
|
|
|
def test_rejects_missing_session_id():
|
|
d = _base(); del d["session_id"]
|
|
with pytest.raises(ValidationError):
|
|
AiderEventIn(**d)
|
|
|
|
|
|
def test_rejects_missing_ts():
|
|
d = _base(); del d["ts"]
|
|
with pytest.raises(ValidationError):
|
|
AiderEventIn(**d)
|
|
|
|
|
|
def test_batch_max_50():
|
|
with pytest.raises(ValidationError):
|
|
AiderBatchIn(events=[_base() for _ in range(51)])
|
|
|
|
|
|
def test_batch_accepts_1():
|
|
b = AiderBatchIn(events=[_base()])
|
|
assert len(b.events) == 1
|
|
|
|
|
|
def test_host_default():
|
|
d = _base(); del d["host"]
|
|
ev = AiderEventIn(**d)
|
|
assert ev.host == "ogt-mac"
|