Features: - FastAPI backend with JWT authentication - MySQL database with SQLAlchemy ORM - KPI workflow: draft → pending → approved → evaluation → completed - Ollama LLM API integration for AI features - Gitea API integration for version control - Complete API endpoints for KPI, dashboard, notifications Tables: KPI_D_* prefix naming convention 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
141 lines
3.8 KiB
Python
141 lines
3.8 KiB
Python
"""
|
|
KPI API 測試
|
|
"""
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from sqlalchemy.orm import Session
|
|
|
|
from tests.factories import (
|
|
EmployeeFactory,
|
|
KPIPeriodFactory,
|
|
KPISheetFactory,
|
|
)
|
|
|
|
|
|
class TestKPISheetAPI:
|
|
"""KPI 表單 API 測試"""
|
|
|
|
def test_create_sheet_success(
|
|
self, client: TestClient, db: Session, auth_headers: dict
|
|
):
|
|
"""測試:建立 KPI 表單"""
|
|
# Arrange
|
|
period = KPIPeriodFactory.create(db, status="setting")
|
|
db.commit()
|
|
|
|
payload = {
|
|
"period_id": period.id,
|
|
"items": [
|
|
{
|
|
"name": "營收達成率",
|
|
"category": "financial",
|
|
"weight": 50,
|
|
},
|
|
{
|
|
"name": "客戶滿意度",
|
|
"category": "customer",
|
|
"weight": 50,
|
|
},
|
|
],
|
|
}
|
|
|
|
# Act
|
|
response = client.post(
|
|
"/api/kpi/sheets",
|
|
json=payload,
|
|
headers=auth_headers,
|
|
)
|
|
|
|
# Assert
|
|
assert response.status_code == 201
|
|
data = response.json()
|
|
assert data["status"] == "draft"
|
|
assert len(data["items"]) == 2
|
|
|
|
def test_get_my_sheets(
|
|
self, client: TestClient, db: Session, auth_headers: dict, test_employee
|
|
):
|
|
"""測試:取得我的 KPI 表單"""
|
|
# Arrange
|
|
period = KPIPeriodFactory.create(db)
|
|
KPISheetFactory.create(db, employee=test_employee, period=period)
|
|
db.commit()
|
|
|
|
# Act
|
|
response = client.get("/api/kpi/sheets/my", headers=auth_headers)
|
|
|
|
# Assert
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data) >= 1
|
|
|
|
def test_get_sheet_not_found(self, client: TestClient, auth_headers: dict):
|
|
"""測試:查詢不存在的表單"""
|
|
response = client.get("/api/kpi/sheets/99999", headers=auth_headers)
|
|
|
|
assert response.status_code == 404
|
|
|
|
def test_submit_sheet_success(
|
|
self, client: TestClient, db: Session, auth_headers: dict, test_employee
|
|
):
|
|
"""測試:提交 KPI 審核"""
|
|
# Arrange
|
|
period = KPIPeriodFactory.create(db, status="setting")
|
|
sheet = KPISheetFactory.create(
|
|
db, employee=test_employee, period=period, status="draft", with_items=True
|
|
)
|
|
db.commit()
|
|
|
|
# Act
|
|
response = client.post(
|
|
f"/api/kpi/sheets/{sheet.id}/submit",
|
|
headers=auth_headers,
|
|
)
|
|
|
|
# Assert
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "pending"
|
|
|
|
def test_submit_sheet_weight_invalid(
|
|
self, client: TestClient, db: Session, auth_headers: dict, test_employee
|
|
):
|
|
"""測試:權重不正確提交應失敗"""
|
|
# Arrange
|
|
period = KPIPeriodFactory.create(db, status="setting")
|
|
sheet = KPISheetFactory.create(
|
|
db,
|
|
employee=test_employee,
|
|
period=period,
|
|
status="draft",
|
|
with_items=False, # 不建立項目
|
|
)
|
|
db.commit()
|
|
|
|
# Act
|
|
response = client.post(
|
|
f"/api/kpi/sheets/{sheet.id}/submit",
|
|
headers=auth_headers,
|
|
)
|
|
|
|
# Assert
|
|
assert response.status_code == 400
|
|
|
|
|
|
class TestKPIPeriodAPI:
|
|
"""KPI 期間 API 測試"""
|
|
|
|
def test_list_periods(self, client: TestClient, db: Session, auth_headers: dict):
|
|
"""測試:取得期間列表"""
|
|
# Arrange
|
|
KPIPeriodFactory.create(db)
|
|
db.commit()
|
|
|
|
# Act
|
|
response = client.get("/api/kpi/periods", headers=auth_headers)
|
|
|
|
# Assert
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data) >= 1
|