frontend admin refakctorálás

This commit is contained in:
Roo
2026-07-08 08:03:57 +00:00
parent 07b59032ce
commit 2e0abc62a7
455 changed files with 14428 additions and 21651 deletions

View File

@@ -0,0 +1,199 @@
# /opt/docker/dev/service_finder/backend/app/tests/test_validation_engine.py
"""
Test script for ValidationEngine.
Tests:
1. get_rules() — fetches dynamic rules from DB
2. process_staging_score() with admin override
3. process_staging_score() with user weight
4. process_staging_score() with robot base score
5. Auto-promotion when threshold reached
Usage:
docker exec -i sf_api python -m app.tests.test_validation_engine
"""
import asyncio
import logging
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
from app.database import AsyncSessionLocal
from app.models import (
ServiceStaging,
ValidationRule,
UserStats,
)
from app.models.identity.social import ProviderValidation
from app.services.validation_engine import ValidationEngine
from sqlalchemy import select, delete
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s')
logger = logging.getLogger("TestValidationEngine")
PASS = 0
FAIL = 0
def assert_eq(actual, expected, label: str):
global PASS, FAIL
if actual == expected:
PASS += 1
logger.info(f"{label}: {actual} == {expected}")
else:
FAIL += 1
logger.error(f"{label}: {actual} != {expected}")
async def test_get_rules():
"""Test that get_rules() fetches all 4 base rules from the DB."""
logger.info("\n📋 Test: get_rules()")
engine = ValidationEngine()
async with AsyncSessionLocal() as db:
rules = await engine.get_rules(db)
assert_eq(rules.get("BOT_BASE_SCORE"), 20, "BOT_BASE_SCORE")
assert_eq(rules.get("FIRST_ENTRY_SCORE"), 40, "FIRST_ENTRY_SCORE")
assert_eq(rules.get("USER_CONFIRM_BASE"), 20, "USER_CONFIRM_BASE")
assert_eq(rules.get("AUTO_APPROVE_THRESHOLD"), 80, "AUTO_APPROVE_THRESHOLD")
assert_eq(len(rules), 4, "rule count")
async def test_admin_override():
"""Test that admin override sets score=100."""
logger.info("\n📋 Test: admin override (score=100)")
engine = ValidationEngine()
async with AsyncSessionLocal() as db:
staging = ServiceStaging(
name="Test Admin Garage",
city="Budapest",
fingerprint="test_admin_fp_001",
status="pending",
validation_level=0,
)
db.add(staging)
await db.flush()
new_level = await engine.process_staging_score(
db, staging, is_admin=True
)
assert_eq(new_level, 100, "admin validation_level")
assert_eq(staging.validation_level, 100, "staging.validation_level")
# Cleanup
await db.rollback()
async def test_user_weight():
"""Test that user weight is calculated from UserStats.current_level."""
logger.info("\n📋 Test: user weight calculation")
engine = ValidationEngine()
async with AsyncSessionLocal() as db:
# Create a staging entry
staging = ServiceStaging(
name="Test User Garage",
city="Debrecen",
fingerprint="test_user_fp_001",
status="pending",
validation_level=0,
)
db.add(staging)
await db.flush()
# Test with user_id that doesn't exist (should use base weight)
new_level = await engine.process_staging_score(
db, staging, user_id=999999
)
# USER_CONFIRM_BASE=20, no UserStats -> base=20
assert_eq(new_level, 20, "user weight without stats (base=20)")
staging.validation_level = 0 # reset
# Create UserStats for user 1 (if exists)
stmt = select(UserStats).where(UserStats.user_id == 1)
result = await db.execute(stmt)
stats = result.scalar_one_or_none()
if stats:
level = stats.current_level or 1
expected = 20 + (level * 5)
new_level = await engine.process_staging_score(
db, staging, user_id=1
)
assert_eq(new_level, expected, f"user weight with level={level}")
await db.rollback()
async def test_robot_base_score():
"""Test that robot (no user_id) uses BOT_BASE_SCORE=20."""
logger.info("\n📋 Test: robot base score (BOT_BASE_SCORE=20)")
engine = ValidationEngine()
async with AsyncSessionLocal() as db:
staging = ServiceStaging(
name="Test Robot Garage",
city="Szeged",
fingerprint="test_robot_fp_001",
status="pending",
validation_level=0,
)
db.add(staging)
await db.flush()
new_level = await engine.process_staging_score(db, staging)
assert_eq(new_level, 20, "robot base score")
assert_eq(staging.validation_level, 20, "staging.validation_level")
await db.rollback()
async def test_auto_promote():
"""Test that staging is auto-promoted when validation_level >= 80."""
logger.info("\n📋 Test: auto-promotion at threshold >= 80")
engine = ValidationEngine()
async with AsyncSessionLocal() as db:
staging = ServiceStaging(
name="Test Promote Garage",
city="Miskolc",
postal_code="3500",
full_address="3500 Miskolc, Test Street 1",
fingerprint="test_promote_fp_001",
status="pending",
validation_level=40,
trust_score=20,
)
db.add(staging)
await db.flush()
# First pass: admin adds 40 -> 80 (threshold reached)
new_level = await engine.process_staging_score(
db, staging, is_admin=True
)
# Admin gives 100, but capped at 100
assert_eq(new_level, 100, "auto-promote validation_level")
# Status should be 'approved' now
assert_eq(staging.status, "approved", "staging.status after promotion")
await db.rollback()
async def main():
logger.info("=" * 60)
logger.info("🔍 ValidationEngine Test Suite")
logger.info("=" * 60)
await test_get_rules()
await test_admin_override()
await test_user_weight()
await test_robot_base_score()
await test_auto_promote()
logger.info("\n" + "=" * 60)
logger.info(f"📊 Results: {PASS} passed, {FAIL} failed")
logger.info("=" * 60)
if FAIL > 0:
sys.exit(1)
if __name__ == "__main__":
asyncio.run(main())