- 新增 Pagination 通用组件:首页/上一页/页码/下一页/末页导航 - PickModal 和 SwapModal 集成分页功能,每页20项 - 搜索/筛选切换自动回到第1页 - 现代化CSS样式:hover浮起动效、主色高亮、移动端适配 - 新增 dashboard、admin 管理模板 - 菜系(cuisine)模型和迁移 - 构建脚本 build.py 支持 PyInstaller 打包 - 前端资源重新构建
121 lines
4.4 KiB
Python
121 lines
4.4 KiB
Python
import urllib.request, urllib.error, json, http.cookiejar
|
|
|
|
cj = http.cookiejar.CookieJar()
|
|
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
|
|
|
|
print("=" * 60)
|
|
print(" School Meal Admin Test Report")
|
|
print("=" * 60)
|
|
|
|
# Test 1: Admin Login Page
|
|
print("\n1. Admin Login Page")
|
|
try:
|
|
r = opener.open("http://127.0.0.1:8000/admin/login/", timeout=5)
|
|
body = r.read().decode("utf-8", errors="replace")
|
|
print(" Status: %d OK" % r.status)
|
|
print(" Size: %d bytes" % len(body))
|
|
print(" Has login form: %s" % ("id_username" in body))
|
|
print(" Has password field: %s" % ("id_password" in body))
|
|
print(" Has CSRF: %s" % ("csrfmiddlewaretoken" in body))
|
|
title_start = body.find("<title>") + 7
|
|
title_end = body.find("</title>")
|
|
print(" Title: %s" % body[title_start:title_end])
|
|
except Exception as e:
|
|
print(" FAIL: %s" % e)
|
|
|
|
# Test 2: Admin Login
|
|
print("\n2. Admin Login")
|
|
try:
|
|
r = opener.open("http://127.0.0.1:8000/admin/login/", timeout=5)
|
|
body = r.read().decode("utf-8", errors="replace")
|
|
csrf = body.split('csrfmiddlewaretoken" value="')[1].split('"')[0]
|
|
import urllib.parse
|
|
data = urllib.parse.urlencode({"csrfmiddlewaretoken": csrf, "username": "admin", "password": "admin123", "next": "/admin/"}).encode()
|
|
req = urllib.request.Request("http://127.0.0.1:8000/admin/login/", data=data)
|
|
req.add_header("Referer", "http://127.0.0.1:8000/admin/login/")
|
|
r2 = opener.open(req, timeout=5)
|
|
print(" Login OK: %d" % r2.status)
|
|
except urllib.error.HTTPError as e:
|
|
if e.code == 302:
|
|
print(" Login OK: 302 redirect to %s" % e.headers.get("Location", "unknown"))
|
|
else:
|
|
print(" FAIL: %d" % e.code)
|
|
except Exception as e:
|
|
print(" FAIL: %s" % e)
|
|
|
|
# Test 3: Admin Dashboard
|
|
print("\n3. Admin Dashboard")
|
|
try:
|
|
r = opener.open("http://127.0.0.1:8000/admin/", timeout=5)
|
|
body = r.read().decode("utf-8", errors="replace")
|
|
print(" Status: %d OK" % r.status)
|
|
print(" Size: %d bytes" % len(body))
|
|
print(" Has Dish model: %s" % ("Dish" in body or "meals" in body))
|
|
print(" Has User model: %s" % ("User" in body or "auth" in body))
|
|
print(" Has sidebar: %s" % ("sidebar" in body))
|
|
except Exception as e:
|
|
print(" FAIL: %s" % e)
|
|
|
|
# Test 4: Admin Dishes List
|
|
print("\n4. Admin Dishes List")
|
|
try:
|
|
r = opener.open("http://127.0.0.1:8000/admin/meals/dish/", timeout=5)
|
|
body = r.read().decode("utf-8", errors="replace")
|
|
print(" Status: %d OK" % r.status)
|
|
print(" Size: %d bytes" % len(body))
|
|
print(" Has result table: %s" % ("result_list" in body))
|
|
except Exception as e:
|
|
print(" FAIL: %s" % e)
|
|
|
|
# Test 5: API Dishes
|
|
print("\n5. API Dishes")
|
|
try:
|
|
r = opener.open("http://127.0.0.1:8000/api/dishes/", timeout=5)
|
|
data = json.loads(r.read())
|
|
print(" Status: %d OK" % r.status)
|
|
print(" Dish count: %d" % len(data))
|
|
if data:
|
|
print(" First dish: %s (%s)" % (data[0]["name"], data[0]["dish_type"]))
|
|
except Exception as e:
|
|
print(" FAIL: %s" % e)
|
|
|
|
# Test 6: Menu Generation
|
|
print("\n6. Menu Generation")
|
|
try:
|
|
req = urllib.request.Request("http://127.0.0.1:8000/api/menu/generate/",
|
|
data=json.dumps({"selections": [], "auto_all": True}).encode(),
|
|
headers={"Content-Type": "application/json"})
|
|
r = opener.open(req, timeout=10)
|
|
menu = json.loads(r.read())
|
|
print(" Status: %d OK" % r.status)
|
|
print(" Menu A days: %d" % len(menu["a"]["week"]))
|
|
print(" Menu B days: %d" % len(menu["b"]["week"]))
|
|
day_a = menu["a"]["week"][0]
|
|
print(" A Mon: %d meats %d vegs soup" % (len(day_a["meats"]), len(day_a["vegs"])))
|
|
except Exception as e:
|
|
print(" FAIL: %s" % e)
|
|
|
|
# Test 7: Frontend
|
|
print("\n7. Frontend")
|
|
try:
|
|
r = opener.open("http://127.0.0.1:8000/", timeout=5)
|
|
body = r.read().decode("utf-8", errors="replace")
|
|
print(" Status: %d OK" % r.status)
|
|
print(" Size: %d bytes" % len(body))
|
|
print(" Has React root: %s" % ("root" in body))
|
|
except Exception as e:
|
|
print(" FAIL: %s" % e)
|
|
|
|
# Test 8: Static Files
|
|
print("\n8. Static Files")
|
|
for path in ["/static/admin/css/base.css", "/static/jazzmin/css/main.css"]:
|
|
try:
|
|
r = opener.open("http://127.0.0.1:8000%s" % path, timeout=5)
|
|
print(" %s: %d OK (%d bytes)" % (path, r.status, len(r.read())))
|
|
except Exception as e:
|
|
print(" %s: FAIL (%s)" % (path, e))
|
|
|
|
print("\n" + "=" * 60)
|
|
print(" All tests completed")
|
|
print("=" * 60)
|