baseline: Clover 独立仓库首次基线提交

将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。
当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包),
M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
yangqianqian
2026-06-16 11:30:22 +08:00
commit 6a2632da70
253 changed files with 27467 additions and 0 deletions

56
backend/tests/conftest.py Normal file
View File

@@ -0,0 +1,56 @@
"""
conftest.py — 测试环境 stub
在任何模块 import 之前注入环境变量,让 Settings 校验通过。
只用于本地单元/集成测试,不影响生产。
"""
import os
import sys
import types
# ── 1. 注入最小可用配置(全假值,只让 Settings 构建通过)────────
_TEST_ENV = {
"FERNET_KEY": "test-fernet-key-at-least-32-chars-long!!",
"JWT_SECRET": "test-jwt-secret-at-least-32-chars-long!!",
"DATABASE_URL": "mysql+pymysql://test:test@localhost/test",
"MONGO_URI": "mongodb://localhost:27017/test",
"REDIS_URL": "redis://localhost:6379/0",
"APP_ENV": "test",
}
for k, v in _TEST_ENV.items():
os.environ.setdefault(k, v)
# ── 2. 清掉 lru_cache让 Settings 用刚注入的 env vars 重建 ─────
from app.core import config as _cfg
_cfg.get_settings.cache_clear()
# ── 3. Stub motorMongoDB client本地没装──────────────────────
if "motor" not in sys.modules:
motor_mod = types.ModuleType("motor")
motor_async = types.ModuleType("motor.motor_asyncio")
motor_async.AsyncIOMotorClient = object
sys.modules["motor"] = motor_mod
sys.modules["motor.motor_asyncio"] = motor_async
# ── 4. Stub database engineMySQL URL 但不连接)──────────────────
# database.py 顶层调 create_enginepytest 环境没有 MySQL。
# 只 stub engine 和 SessionLocal不影响任何逻辑测试。
import unittest.mock as _mock
import sqlalchemy
_fake_engine = _mock.MagicMock()
_fake_session_class = _mock.MagicMock()
_fake_session_class.return_value.__enter__ = _mock.MagicMock(return_value=_mock.MagicMock())
_fake_session_class.return_value.__exit__ = _mock.MagicMock(return_value=False)
# 只在 database 模块还未 import 时 patch若已 import 则直接替换属性
if "app.core.database" not in sys.modules:
with _mock.patch("sqlalchemy.create_engine", return_value=_fake_engine):
with _mock.patch("sqlalchemy.orm.sessionmaker", return_value=_fake_session_class):
import app.core.database as _db_mod
else:
_db_mod = sys.modules["app.core.database"]
# 确保 engine/SessionLocal 是 mock防止实际连接
_db_mod.engine = _fake_engine
_db_mod.SessionLocal = _fake_session_class