style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 51s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m22s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m48s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m51s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m18s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 6m1s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 6m1s
AI Code Review / AI Code Review (pull_request) Successful in 6m42s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 13m1s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 13m27s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 9m20s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 29s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 49s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 51s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m22s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m48s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m51s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m18s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 6m1s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 6m1s
AI Code Review / AI Code Review (pull_request) Successful in 6m42s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 13m1s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 13m27s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 9m20s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 29s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 49s
This commit is contained in:
@@ -158,10 +158,18 @@ class TestResolveVideoDimensions:
|
||||
from packages.domain.points_rules import resolve_video_dimensions
|
||||
|
||||
cases = [
|
||||
("普清", 480), ("sd", 480), ("low", 480), ("default", 480),
|
||||
("高清", 720), ("medium", 720), ("hd", 720),
|
||||
("超清", 1080), ("fhd", 1080), ("ultra", 1080),
|
||||
("全能", 1080), ("high", 1080),
|
||||
("普清", 480),
|
||||
("sd", 480),
|
||||
("low", 480),
|
||||
("default", 480),
|
||||
("高清", 720),
|
||||
("medium", 720),
|
||||
("hd", 720),
|
||||
("超清", 1080),
|
||||
("fhd", 1080),
|
||||
("ultra", 1080),
|
||||
("全能", 1080),
|
||||
("high", 1080),
|
||||
]
|
||||
for alias, expected_h in cases:
|
||||
_, h = resolve_video_dimensions(alias, "1:1")
|
||||
@@ -307,7 +315,9 @@ class TestCalculateViralVideoCredits:
|
||||
|
||||
price = VIRAL_VIDEO_MODEL_PRICES[("seedance-2.5", "720p", False)]
|
||||
actual_tokens = 2_000_000
|
||||
expected = round((actual_tokens / 1_000_000 * price + VIRAL_VIDEO_FIXED_COST) * VIRAL_VIDEO_PROFIT_MULTIPLIER, 2)
|
||||
expected = round(
|
||||
(actual_tokens / 1_000_000 * price + VIRAL_VIDEO_FIXED_COST) * VIRAL_VIDEO_PROFIT_MULTIPLIER, 2
|
||||
)
|
||||
credits = calculate_viral_video_credits(15, 1280, 720, actual_tokens=actual_tokens)
|
||||
assert credits == expected
|
||||
|
||||
@@ -373,7 +383,6 @@ class TestCalculateViralVideoCredits:
|
||||
credits = calculate_viral_video_credits(dur, w, h, model="seedance-2.0", has_video_input=True)
|
||||
assert credits == expected
|
||||
|
||||
|
||||
def test_fps_zero_or_none_falls_back_to_default(self):
|
||||
"""fps=0/None 时 int(fps or 24) 兜底到默认 24,结果与 fps=24 一致。"""
|
||||
from packages.domain.points_rules import calculate_viral_video_credits
|
||||
|
||||
@@ -189,7 +189,7 @@ class TestDeductViralVideo:
|
||||
|
||||
def test_delegates_to_deduct_points_with_correct_args(self, service, db_session, user_id):
|
||||
"""deduct_viral_video 应以 source='viral_video', ref_id=job_id 调用 deduct_points。"""
|
||||
from unittest.mock import MagicMock, patch
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
expected = {"success": True, "balance": 50.0, "transaction_id": "t1"}
|
||||
with patch.object(service, "deduct_points", return_value=expected) as mock_dp:
|
||||
@@ -207,9 +207,10 @@ class TestDeductViralVideo:
|
||||
|
||||
def test_none_credits_coerced_to_zero(self, service, db_session, user_id):
|
||||
"""credits=None 时应被 float(credits or 0) 转为 0,不抛异常。"""
|
||||
from unittest.mock import patch
|
||||
|
||||
with patch.object(service, "deduct_points", return_value={"success": True, "balance": 0, "transaction_id": "t"}) as mock_dp:
|
||||
with patch.object(
|
||||
service, "deduct_points", return_value={"success": True, "balance": 0, "transaction_id": "t"}
|
||||
) as mock_dp:
|
||||
service.deduct_viral_video(user_id, None, "job-nil", db_session)
|
||||
assert mock_dp.call_args.kwargs["amount"] == 0.0
|
||||
|
||||
@@ -219,7 +220,6 @@ class TestSettleViralVideo:
|
||||
|
||||
def test_no_action_when_diff_below_epsilon(self, service, db_session, user_id):
|
||||
"""|diff|<0.01 时返回 action=none,不调 refund/deduct。"""
|
||||
from unittest.mock import patch
|
||||
|
||||
with (
|
||||
patch.object(service, "refund_points") as mock_refund,
|
||||
@@ -235,7 +235,6 @@ class TestSettleViralVideo:
|
||||
|
||||
def test_refund_when_actual_less_than_estimated(self, service, db_session, user_id):
|
||||
"""actual<estimated 时走 refund_points,返回 action=refund。"""
|
||||
from unittest.mock import patch
|
||||
|
||||
refund_res = {"success": True, "balance": 60.0, "transaction_id": "tr-1"}
|
||||
with patch.object(service, "refund_points", return_value=refund_res) as mock_refund:
|
||||
@@ -255,7 +254,6 @@ class TestSettleViralVideo:
|
||||
|
||||
def test_refund_exception_returns_failure(self, service, db_session, user_id):
|
||||
"""refund_points 抛异常时,应捕获并返回 success=False。"""
|
||||
from unittest.mock import patch
|
||||
|
||||
with patch.object(service, "refund_points", side_effect=RuntimeError("db down")):
|
||||
result = service.settle_viral_video(user_id, estimated=20.0, actual=10.0, txn_id="t3", db=db_session)
|
||||
@@ -265,7 +263,6 @@ class TestSettleViralVideo:
|
||||
|
||||
def test_deduct_when_actual_greater_than_estimated_success(self, service, db_session, user_id):
|
||||
"""actual>estimated 且补扣成功 → action=deduct, success=True。"""
|
||||
from unittest.mock import patch
|
||||
|
||||
deduct_res = {"success": True, "balance": 40.0, "transaction_id": "td-1"}
|
||||
with patch.object(service, "deduct_points", return_value=deduct_res) as mock_deduct:
|
||||
@@ -284,7 +281,6 @@ class TestSettleViralVideo:
|
||||
def test_deduct_insufficient_balance_returns_success_false_not_raise(self, service, db_session, user_id):
|
||||
"""actual>estimated 补扣时余额不足(success=False)应记录 warning 但不抛异常。"""
|
||||
import logging
|
||||
from unittest.mock import patch
|
||||
|
||||
deduct_res = {"success": False, "balance": 2.0, "transaction_id": None}
|
||||
with (
|
||||
@@ -302,7 +298,6 @@ class TestSettleViralVideo:
|
||||
|
||||
def test_deduct_exception_returns_failure(self, service, db_session, user_id):
|
||||
"""deduct_points 抛异常时应捕获并返回 success=False。"""
|
||||
from unittest.mock import patch
|
||||
|
||||
with patch.object(service, "deduct_points", side_effect=RuntimeError("db boom")):
|
||||
result = service.settle_viral_video(user_id, estimated=10.0, actual=20.0, txn_id="t6", db=db_session)
|
||||
@@ -317,7 +312,6 @@ class TestRefundViralVideo:
|
||||
|
||||
def test_zero_amount_returns_none_action(self, service, db_session, user_id):
|
||||
"""amount<=0 直接返回 none action,不调 refund_points。"""
|
||||
from unittest.mock import patch
|
||||
|
||||
with patch.object(service, "refund_points") as mock_refund:
|
||||
r1 = service.refund_viral_video(user_id, 0, "t0", db_session)
|
||||
@@ -331,7 +325,6 @@ class TestRefundViralVideo:
|
||||
|
||||
def test_success_path_delegates_to_refund_points(self, service, db_session, user_id):
|
||||
"""成功路径:透传 user_id/amount/ref_id=txn_id/source=viral_video。"""
|
||||
from unittest.mock import patch
|
||||
|
||||
expected = {"success": True, "balance": 80.0, "transaction_id": "rf-1"}
|
||||
with patch.object(service, "refund_points", return_value=expected) as mock_refund:
|
||||
@@ -348,7 +341,6 @@ class TestRefundViralVideo:
|
||||
|
||||
def test_exception_returns_failure(self, service, db_session, user_id):
|
||||
"""refund_points 抛异常时返回 success=False/action=refund。"""
|
||||
from unittest.mock import patch
|
||||
|
||||
with patch.object(service, "refund_points", side_effect=RuntimeError("conn lost")):
|
||||
result = service.refund_viral_video(user_id, 25.0, "txn-err", db_session)
|
||||
|
||||
@@ -412,10 +412,9 @@ class TestConfirmCopyPointsDeduction:
|
||||
|
||||
def test_points_enabled_deducts_successfully(self):
|
||||
"""points_enabled=True + 未预付 → 计算预估积分 → deduct_viral_video → 写入 credits_prepaid。"""
|
||||
from fastapi import HTTPException
|
||||
|
||||
from app.api.routes import viral_video as vv_mod
|
||||
from app.schemas.viral_video import ConfirmCopyRequest
|
||||
from fastapi import HTTPException
|
||||
|
||||
from packages.domain.viral_video import ViralVideoStatus
|
||||
|
||||
@@ -458,10 +457,9 @@ class TestConfirmCopyPointsDeduction:
|
||||
def test_points_enabled_insufficient_balance_raises_402(self):
|
||||
"""余额不足(deduct_viral_video 返回 success=False)→ HTTP 402。"""
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
|
||||
from app.api.routes import viral_video as vv_mod
|
||||
from app.schemas.viral_video import ConfirmCopyRequest
|
||||
from fastapi import HTTPException
|
||||
|
||||
from packages.domain.viral_video import ViralVideoStatus
|
||||
|
||||
|
||||
Reference in New Issue
Block a user