fix: автодетект --cli в Bootstrap, отображение локальных сборок в JFX, обработка ошибок установки и друзей
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
import sys, os, json, time, subprocess, signal
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'server'))
|
||||
|
||||
import httpx
|
||||
from pathlib import Path
|
||||
|
||||
BASE = "http://127.0.0.1:1589"
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
def check(name, ok, detail=""):
|
||||
global passed, failed
|
||||
if ok:
|
||||
print(f" PASS {name}")
|
||||
passed += 1
|
||||
else:
|
||||
print(f" FAIL {name} {detail}")
|
||||
failed += 1
|
||||
|
||||
def start_server():
|
||||
env = os.environ.copy()
|
||||
env["PYTHONPATH"] = os.path.join(os.path.dirname(__file__), "server")
|
||||
proc = subprocess.Popen(
|
||||
[sys.executable, "-m", "uvicorn", "main:app", "--host", "127.0.0.1", "--port", "1589"],
|
||||
cwd=os.path.join(os.path.dirname(__file__), "server"),
|
||||
env=env,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
for i in range(30):
|
||||
try:
|
||||
r = httpx.get(f"{BASE}/news", timeout=2)
|
||||
if r.status_code == 200:
|
||||
return proc
|
||||
except:
|
||||
time.sleep(1)
|
||||
return proc
|
||||
|
||||
proc = None
|
||||
try:
|
||||
print("Starting server...")
|
||||
proc = start_server()
|
||||
print("Server started\n")
|
||||
client = httpx.Client(base_url=BASE, timeout=10)
|
||||
|
||||
# ---------- NEWS ----------
|
||||
print("=== NEWS ===")
|
||||
r = client.get("/news")
|
||||
check("GET /news", r.status_code == 200 and "news" in r.json())
|
||||
data = r.json()
|
||||
check("news is array", isinstance(data.get("news"), list))
|
||||
check("news has items", len(data["news"]) > 0,
|
||||
f"got {len(data['news'])} items")
|
||||
if data["news"]:
|
||||
first = data["news"][0]
|
||||
check("news item has title", "title" in first)
|
||||
check("news item has body", "body" in first)
|
||||
check("news item has type", "type" in first)
|
||||
|
||||
# ---------- AUTH ----------
|
||||
print("\n=== AUTH ===")
|
||||
test_user = f"test_{int(time.time())}"
|
||||
test_pass = "test123"
|
||||
r = client.post("/register", json={"username": test_user, "password": test_pass})
|
||||
check("POST /register (new user)", r.status_code == 200)
|
||||
reg_data = r.json()
|
||||
check("register returns token", "access_token" in reg_data)
|
||||
|
||||
r2 = client.post("/register", json={"username": test_user, "password": test_pass})
|
||||
check("POST /register (duplicate)", r2.status_code == 200)
|
||||
|
||||
r3 = client.post("/login", json={"username": test_user, "password": test_pass})
|
||||
check("POST /login (valid)", r3.status_code == 200)
|
||||
login_data = r3.json()
|
||||
check("login returns access_token", "access_token" in login_data)
|
||||
token = login_data.get("access_token", "")
|
||||
|
||||
r4 = client.post("/login", json={"username": test_user, "password": "wrong"})
|
||||
check("POST /login (wrong pass)", r4.status_code == 401)
|
||||
|
||||
r5 = client.post("/login", json={"username": "nonexistent", "password": "x"})
|
||||
check("POST /login (nonexistent)", r5.status_code == 401)
|
||||
|
||||
authed = httpx.Client(base_url=BASE, timeout=10, headers={"Authorization": f"Bearer {token}"})
|
||||
|
||||
# ---------- ACCOUNT ----------
|
||||
print("\n=== ACCOUNT ===")
|
||||
r = authed.get("/account")
|
||||
check("GET /account (authed)", r.status_code == 200)
|
||||
acct = r.json()
|
||||
check("account has username", acct.get("username") == test_user,
|
||||
f"got {acct.get('username')}")
|
||||
check("account has role", "role" in acct)
|
||||
check("account has passActive", "passActive" in acct)
|
||||
|
||||
r2 = client.get("/account")
|
||||
check("GET /account (unauthed)", r2.status_code == 401)
|
||||
|
||||
# ---------- PACKS ----------
|
||||
print("\n=== PACKS ===")
|
||||
r = client.get("/packs")
|
||||
check("GET /packs (unauthed)", r.status_code == 401 or r.status_code == 403,
|
||||
f"got {r.status_code}")
|
||||
|
||||
r2 = authed.get("/packs")
|
||||
check("GET /packs (authed)", r2.status_code in (200, 403),
|
||||
f"got {r2.status_code}")
|
||||
if r2.status_code == 200:
|
||||
packs = r2.json()
|
||||
check("packs has packs key", "packs" in packs)
|
||||
check("packs is list", isinstance(packs.get("packs"), list))
|
||||
|
||||
# ---------- FRIENDS (no auth) ----------
|
||||
print("\n=== FRIENDS ===")
|
||||
r = client.get("/api/friends/list")
|
||||
check("GET /friends/list (unauthed)", r.status_code == 401)
|
||||
|
||||
r2 = authed.get("/api/friends/list")
|
||||
check("GET /friends/list (authed)", r2.status_code == 200)
|
||||
flist = r2.json()
|
||||
check("friends list has friends key", "friends" in flist)
|
||||
|
||||
r3 = authed.get("/api/friends/requests")
|
||||
check("GET /friends/requests (authed)", r3.status_code == 200)
|
||||
freq = r3.json()
|
||||
check("friends requests has requests key", "requests" in freq)
|
||||
|
||||
# ---------- FRIENDS add/search ----------
|
||||
friend_user = f"friend_{int(time.time())}"
|
||||
r = client.post("/register", json={"username": friend_user, "password": "pass123"})
|
||||
check("register friend user", r.status_code == 200)
|
||||
friend_token = r.json().get("access_token", "")
|
||||
friend_authed = httpx.Client(base_url=BASE, timeout=10,
|
||||
headers={"Authorization": f"Bearer {friend_token}"})
|
||||
|
||||
r_add = authed.post("/api/friends/add", json={"username": friend_user})
|
||||
check("POST /friends/add", r_add.status_code == 200,
|
||||
f"got {r_add.status_code}: {r_add.text[:100]}")
|
||||
|
||||
r_dup = authed.post("/api/friends/add", json={"username": friend_user})
|
||||
check("POST /friends/add (duplicate)", r_dup.status_code == 400)
|
||||
|
||||
r_self = authed.post("/api/friends/add", json={"username": test_user})
|
||||
check("POST /friends/add (self)", r_self.status_code == 400)
|
||||
|
||||
r_nonexist = authed.post("/api/friends/add", json={"username": "nonexistent_xyz"})
|
||||
check("POST /friends/add (nonexistent)", r_nonexist.status_code == 404)
|
||||
|
||||
# Friend accepts
|
||||
r_accept = friend_authed.post("/api/friends/accept", json={"user_id": acct.get("id", 0)})
|
||||
check("POST /friends/accept", r_accept.status_code in (200, 404),
|
||||
f"got {r_accept.status_code}: {r_accept.text[:100]}")
|
||||
|
||||
# Check friends list now shows each other
|
||||
r_list = authed.get("/api/friends/list")
|
||||
check("GET /friends/list (after accept)", r_list.status_code == 200)
|
||||
|
||||
# Remove friend
|
||||
friend_acct = r.json()
|
||||
r_remove = authed.post("/api/friends/remove", json={"user_id": 9999})
|
||||
check("POST /friends/remove (nonexistent)", r_remove.status_code == 404)
|
||||
|
||||
# ---------- PLAYTIME ----------
|
||||
print("\n=== PLAYTIME ===")
|
||||
r = authed.post("/api/playtime/sync", json={"pack_name": "test_pack", "minutes": 30})
|
||||
check("POST /playtime/sync", r.status_code == 200, r.text[:100])
|
||||
|
||||
r2 = authed.get("/api/playtime/stats")
|
||||
check("GET /playtime/stats", r2.status_code == 200)
|
||||
stats = r2.json()
|
||||
check("playtime stats has total_minutes", "total_minutes" in stats)
|
||||
check("playtime stats has packs", "packs" in stats)
|
||||
|
||||
r3 = client.get("/api/playtime/stats")
|
||||
check("GET /playtime/stats (unauthed)", r3.status_code == 401)
|
||||
|
||||
# ---------- SUMMARY ----------
|
||||
total = passed + failed
|
||||
print(f"\n{'='*40}")
|
||||
print(f"RESULTS: {passed}/{total} passed, {failed}/{total} failed")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nTEST ERROR: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if proc:
|
||||
proc.terminate()
|
||||
proc.wait(timeout=5)
|
||||
|
||||
sys.exit(1 if failed > 0 else 0)
|
||||
Reference in New Issue
Block a user