Files
pear-admin-flask/scripts/probe_nav_category.py
T
bwstudio 0ffc103e46 feat(plugins): 4 个业务插件代码 + 前台公开页面改造
plugins/navManager:导航 CRUD + 导航分类 CRUD(独立 blueprint)
plugins/friendManager:友情链接 CRUD
plugins/aboutManager:关于本站 CRUD
plugins/siteStats:访问统计主页 + JSON 接口 + /site/* GET 埋点 + nav 卡片点击埋点

applications/view/public/nav.py:导航聚合页 / 分类详情 / JSON 接口,支持 visit_count 注入
applications/view/public/about.py:关于本站公开页
applications/view/public/friend.py:友情链接公开页

templates/public/base.html:响应式首页(搜索框 / 分类抽屉 / 5 主题切换 / footer 隐私小字)
templates/public/index.html / category.html:卡片右下角访问次数
templates/public/about.html / friend.html:关于 + 友链前台页

docs/plugins-development.md:插件开发完整指南(生命周期 + 4 个示例 + FAQ + framework 迁移)

scripts/:探针与端到端验证脚本(probe_*/verify_*/test_*)
2026-09-06 18:18:06 +08:00

142 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
导航分类功能端到端探针
======================
不依赖浏览器 + ddddocr + 调试 header,直接用 Flask test_client 走完整流程:
1. 登录 admin
2. GET /system/nav-category/ (主页面 HTML)
3. GET /system/nav-category/data (table_api JSON)
4. POST /system/nav-category/save (新增)
5. PUT /system/nav-category/update (更新)
6. PUT /system/nav-category/enable (启用/禁用)
7. DELETE /system/nav-category/remove/<id> (删除)
8. 验证每个 API 的 {code, message, data} 协议
退出码:全部通过 → 0;任一失败 → 1
"""
import json
import sys
import traceback
sys.path.insert(0, r'D:\bwstudio\pear-admin-flask')
from applications import create_app
app = create_app()
client = app.test_client()
def _login():
"""admin/123456 登录拿 cookie session。"""
# 拿一张 captcha —— 通过 test_client 共享 session_transaction
r = client.get('/system/passport/getCaptcha')
assert r.status_code == 200, r.status_code
with client.session_transaction() as sess:
code = sess.get('code') or ''
code = code.lower()
assert code, 'captcha code missing'
r = client.post('/system/passport/login', data={
'username': 'admin',
'password': '123456',
'captcha': code,
}, follow_redirects=False)
assert r.status_code in (200, 302), r.status_code
def _show(label, resp):
body = resp.get_data(as_text=True)
print(f' [{resp.status_code}] {label} -> {body[:200]}{"..." if len(body) > 200 else ""}')
def main():
_login()
print('=== 已登录,开始 E2E 探针 ===\n')
# 1. 分类主页面 HTML
r = client.get('/system/nav-category/')
print(f'[HTML main] {r.status_code} content-type={r.content_type}')
assert r.status_code == 200
assert b'nav-category/data' in r.data or b'\u5bfc\u822a\u5206\u7c7b' in r.data, 'main 页面未包含预期内容'
print(' [OK] 分类主页面返回 200,含预期关键字\n')
# 2. data 接口(table_api 协议:{code, data, count, msg, limit}
r = client.get('/system/nav-category/data')
assert r.status_code == 200
payload = r.get_json()
assert payload['code'] == 0, payload
before_ids = {row['id'] for row in payload['data']}
print(f' [OK] data 接口 code=0count={payload["count"]},已有分类 {len(before_ids)} 条:{sorted(before_ids)}\n')
# 3. 新增(success_api 协议:{success, msg}
unique_name = f'E2E临时分类{int(__import__("time").time())}'
r = client.post('/system/nav-category/save',
json={'name': unique_name, 'icon': 'layui-icon-test',
'description': 'e2e created', 'sort': 1, 'enable': 1})
payload = r.get_json()
assert payload.get('success') is True, payload
print(f' [OK] 新增成功:{unique_name}\n')
# 4. 拿到 id
r = client.get('/system/nav-category/data')
payload = r.get_json()
new_id = next((row['id'] for row in payload['data'] if row['name'] == unique_name), None)
assert new_id is not None, '新增的分类查不到'
print(f' [OK] 查回新增分类 id={new_id}\n')
# 5. 更新
r = client.put('/system/nav-category/update',
json={'catId': new_id, 'name': unique_name + '_改',
'icon': 'layui-icon-edit', 'description': 'e2e updated',
'sort': 99, 'enable': 1})
payload = r.get_json()
assert payload.get('success') is True, payload
print(f' [OK] 更新成功\n')
# 6. 禁用 → 启用
r = client.put('/system/nav-category/disable', json={'catId': new_id})
assert r.get_json().get('success') is True
r = client.put('/system/nav-category/enable', json={'catId': new_id})
assert r.get_json().get('success') is True
print(f' [OK] 禁用→启用通过\n')
# 7. 删除
r = client.delete(f'/system/nav-category/remove/{new_id}')
assert r.get_json().get('success') is True, r.get_json()
print(f' [OK] 删除成功\n')
# 8. 查回 count 必须等于开始前
r = client.get('/system/nav-category/data')
payload = r.get_json()
after_ids = {row['id'] for row in payload['data']}
assert before_ids == after_ids, f'分类集合变化:before={before_ids}, after={after_ids}'
print(f' [OK] 删除后 count 还原,新增的 id 已不在集合中\n')
# 9. 重名检测
existing_name = None
if payload['data']:
existing_name = payload['data'][0]['name']
if existing_name:
r = client.post('/system/nav-category/save',
json={'name': existing_name, 'icon': 'x', 'description': '', 'sort': 0, 'enable': 1})
body = r.get_json()
assert body.get('success') is False, body
print(f' [OK] 重名拦截正常:{body["msg"]}\n')
print('=== ALL PASS ===')
if __name__ == '__main__':
try:
main()
sys.exit(0)
except AssertionError as e:
print(f'\n!!! ASSERT FAIL: {e}')
traceback.print_exc()
sys.exit(1)
except Exception as e:
print(f'\n!!! UNEXPECTED: {e}')
traceback.print_exc()
sys.exit(1)