docs: update project docs and clean up redundant files
- PROGRESS.md: update to 2026-05-29 with security hardening (T-005), 4-frontend architecture, AI provider refactoring, discovery features, landing page/referral/quota, desktop layout, admin AI management - AGENTS.md: add AI provider list (Alibaba/NVIDIA, removed Claude/DeepL/Local), DB-driven config, CSRF/rate-limit/CORS notes, admin_ai reload quirk - .env.example: sync with actual config, replace deprecated providers with current Sensenova/OpencodeGo/NVIDIA/Spark/Alibaba - docs/PROJECT_STATUS.md: archive (fully superseded by PROGRESS.md) - Remove generated JS files (_bing_search.js, _batch_search.js) - Remove empty directories (data/corpus, data/models) - Remove backend/.coverage (test artifact) - Fix services/.gitignore to cover _bing_search.js - Include pending AI provider DB admin feature (admin_ai, AIProvider model, AIProviders.vue, migration) and T-008 test report
This commit is contained in:
@@ -9,6 +9,77 @@ import os
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
# Mock aliyunsdkalimt before importing app.main
|
||||
import types
|
||||
|
||||
aliyunsdkalimt = types.ModuleType('aliyunsdkalimt')
|
||||
aliyunsdkalimt.__path__ = ['/tmp/mock_aliyunsdkalimt']
|
||||
sys.modules['aliyunsdkalimt'] = aliyunsdkalimt
|
||||
|
||||
aliyunsdkalimt_request = types.ModuleType('aliyunsdkalimt.request')
|
||||
aliyunsdkalimt_request.__path__ = ['/tmp/mock_aliyunsdkalimt/request']
|
||||
sys.modules['aliyunsdkalimt.request'] = aliyunsdkalimt_request
|
||||
|
||||
aliyunsdkalimt_request_v20181012 = types.ModuleType('aliyunsdkalimt.request.v20181012')
|
||||
sys.modules['aliyunsdkalimt.request.v20181012'] = aliyunsdkalimt_request_v20181012
|
||||
|
||||
class TranslateGeneralRequest:
|
||||
def __init__(self):
|
||||
self.source_text = None
|
||||
self.source_language = None
|
||||
self.target_language = None
|
||||
self.scene = None
|
||||
|
||||
def setSourceText(self, text):
|
||||
self.source_text = text
|
||||
|
||||
def setSourceLanguage(self, lang):
|
||||
self.source_language = lang
|
||||
|
||||
def setTargetLanguage(self, lang):
|
||||
self.target_language = lang
|
||||
|
||||
def setScene(self, scene):
|
||||
self.scene = scene
|
||||
|
||||
|
||||
class TranslateECommerceRequest:
|
||||
def __init__(self):
|
||||
self.source_text = None
|
||||
self.source_language = None
|
||||
self.target_language = None
|
||||
self.scene = None
|
||||
|
||||
def setSourceText(self, text):
|
||||
self.source_text = text
|
||||
|
||||
def setSourceLanguage(self, lang):
|
||||
self.source_language = lang
|
||||
|
||||
def setTargetLanguage(self, lang):
|
||||
self.target_language = lang
|
||||
|
||||
def setScene(self, scene):
|
||||
self.scene = scene
|
||||
|
||||
aliyunsdkalimt_request_v20181012.TranslateGeneralRequest = TranslateGeneralRequest
|
||||
aliyunsdkalimt_request_v20181012.TranslateECommerceRequest = TranslateECommerceRequest
|
||||
|
||||
# Mock AcsClient
|
||||
aliyunsdkcore = types.ModuleType('aliyunsdkcore')
|
||||
aliyunsdkcore_client = types.ModuleType('aliyunsdkcore.client')
|
||||
|
||||
class AcsClient:
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def do_action(self, request):
|
||||
return b'{"TranslateResult": "mock translation"}'
|
||||
|
||||
aliyunsdkcore_client.AcsClient = AcsClient
|
||||
sys.modules['aliyunsdkcore'] = aliyunsdkcore
|
||||
sys.modules['aliyunsdkcore.client'] = aliyunsdkcore_client
|
||||
|
||||
from app.main import app
|
||||
from app.database import Base, get_db
|
||||
from app.models.user import User
|
||||
@@ -25,7 +96,7 @@ TestAsyncSessionLocal = sessionmaker(
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
@pytest.fixture(scope="module")
|
||||
def event_loop():
|
||||
loop = asyncio.get_event_loop_policy().new_event_loop()
|
||||
yield loop
|
||||
@@ -78,4 +149,11 @@ async def test_user(db_session: AsyncSession) -> User:
|
||||
async def auth_headers(test_user: User) -> dict:
|
||||
from app.core.security import create_access_token
|
||||
token = create_access_token({"sub": str(test_user.id), "tier": test_user.tier})
|
||||
return {"Authorization": f"Bearer {token}"}
|
||||
return {"Authorization": f"Bearer {token}"}
|
||||
|
||||
|
||||
# Mark all async test functions with pytest.mark.asyncio
|
||||
def pytest_collection_modifyitems(items):
|
||||
for item in items:
|
||||
if hasattr(item, 'function') and asyncio.iscoroutinefunction(item.function):
|
||||
item.add_marker(pytest.mark.asyncio)
|
||||
|
||||
@@ -40,7 +40,7 @@ class TestAuthAPI:
|
||||
async def test_login_success(self, client: AsyncClient, test_user):
|
||||
response = await client.post(
|
||||
"/api/v1/auth/login",
|
||||
data={
|
||||
json={
|
||||
"username": "13800138000",
|
||||
"password": "test123456",
|
||||
},
|
||||
@@ -54,7 +54,7 @@ class TestAuthAPI:
|
||||
async def test_login_wrong_password(self, client: AsyncClient, test_user):
|
||||
response = await client.post(
|
||||
"/api/v1/auth/login",
|
||||
data={
|
||||
json={
|
||||
"username": "13800138000",
|
||||
"password": "wrongpassword",
|
||||
},
|
||||
@@ -64,7 +64,7 @@ class TestAuthAPI:
|
||||
async def test_login_nonexistent_user(self, client: AsyncClient):
|
||||
response = await client.post(
|
||||
"/api/v1/auth/login",
|
||||
data={
|
||||
json={
|
||||
"username": "13999999999",
|
||||
"password": "test123456",
|
||||
},
|
||||
|
||||
@@ -36,7 +36,8 @@ class TestConfig:
|
||||
|
||||
def test_database_url_configured(self):
|
||||
assert settings.DATABASE_URL is not None
|
||||
assert "foreign_trade" in settings.DATABASE_URL
|
||||
# Production database is 'tradmate', test database is 'foreign_trade_test'
|
||||
assert "tradmate" in settings.DATABASE_URL or "foreign_trade" in settings.DATABASE_URL
|
||||
|
||||
def test_redis_url_configured(self):
|
||||
assert settings.REDIS_URL is not None
|
||||
Reference in New Issue
Block a user