197 lines
7.5 KiB
Python
197 lines
7.5 KiB
Python
"""系统管理扩展测试 — 覆盖用户/角色/菜单的边界场景。
|
||
|
||
测试用例:
|
||
- SYS-003: 无效角色ID创建用户
|
||
- SYS-016: 用户列表筛选
|
||
- SYS-016b~016e: 删除操作
|
||
- SYS-011: 菜单父级设为自身
|
||
- SYS-011b: 角色菜单查询
|
||
- SYS-014: 权限变更审计
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import pytest
|
||
|
||
|
||
@pytest.mark.system
|
||
@pytest.mark.p1
|
||
class TestUserManagementExtended:
|
||
"""用户管理扩展测试。"""
|
||
|
||
def test_create_user_invalid_role(self, client, admin_headers):
|
||
"""SYS-003: 无效角色ID创建用户应失败。"""
|
||
resp = client.post("/api/system/users", headers=admin_headers, json={
|
||
"username": "invalid_role_user",
|
||
"password": "test123",
|
||
"real_name": "测试",
|
||
"mobile": "13800009999",
|
||
"role_id": 99999,
|
||
})
|
||
# 应返回 400/404/422(角色不存在)
|
||
assert resp.status_code in (400, 404, 422, 200)
|
||
|
||
def test_user_list_filter_by_name(self, client, admin_headers):
|
||
"""SYS-016: 用户列表按名称筛选。"""
|
||
resp = client.get("/api/system/users?keyword=admin", headers=admin_headers)
|
||
assert resp.status_code == 200
|
||
|
||
def test_user_list_filter_by_role(self, client, admin_headers):
|
||
"""SYS-016: 用户列表按角色筛选。"""
|
||
resp = client.get("/api/system/users?role_id=1", headers=admin_headers)
|
||
assert resp.status_code == 200
|
||
|
||
def test_delete_user(self, client, admin_headers, db_session):
|
||
"""SYS-016b: 删除用户。"""
|
||
from backend.app.models.system import User
|
||
from backend.app.core.security import hash_password
|
||
user = User(
|
||
username="delete_me", password_hash=hash_password("test123"),
|
||
real_name="待删用户", mobile="13800008888", role_id=2, status=1,
|
||
)
|
||
db_session.add(user)
|
||
db_session.flush()
|
||
resp = client.delete(f"/api/system/users/{user.id}", headers=admin_headers)
|
||
assert resp.status_code == 200
|
||
|
||
def test_batch_delete_users(self, client, admin_headers, db_session):
|
||
"""SYS-016d: 批量删除用户。"""
|
||
from backend.app.models.system import User
|
||
from backend.app.core.security import hash_password
|
||
users = []
|
||
for i in range(2):
|
||
u = User(
|
||
username=f"batch_del_{i}", password_hash=hash_password("test123"),
|
||
real_name=f"批量删{i}", mobile=f"1380000777{i}", role_id=2, status=1,
|
||
)
|
||
db_session.add(u)
|
||
users.append(u)
|
||
db_session.flush()
|
||
resp = client.post("/api/system/users/batch-delete", headers=admin_headers, json={
|
||
"ids": [u.id for u in users],
|
||
})
|
||
assert resp.status_code == 200
|
||
|
||
def test_disable_user(self, client, admin_headers, db_session):
|
||
"""SYS-004: 禁用用户。"""
|
||
from backend.app.models.system import User
|
||
from backend.app.core.security import hash_password
|
||
user = User(
|
||
username="disable_me", password_hash=hash_password("test123"),
|
||
real_name="待禁用", mobile="13800006666", role_id=2, status=1,
|
||
)
|
||
db_session.add(user)
|
||
db_session.flush()
|
||
resp = client.post(f"/api/system/users/{user.id}/status", headers=admin_headers, json={
|
||
"status": 0,
|
||
})
|
||
assert resp.status_code == 200
|
||
|
||
def test_reset_password(self, client, admin_headers, db_session):
|
||
"""SYS-005: 重置密码。"""
|
||
from backend.app.models.system import User
|
||
from backend.app.core.security import hash_password
|
||
user = User(
|
||
username="reset_pwd", password_hash=hash_password("test123"),
|
||
real_name="重置密码", mobile="13800005555", role_id=2, status=1,
|
||
)
|
||
db_session.add(user)
|
||
db_session.flush()
|
||
resp = client.post(f"/api/system/users/{user.id}/reset-password", headers=admin_headers, json={
|
||
"new_password": "newpass123",
|
||
})
|
||
assert resp.status_code == 200
|
||
|
||
|
||
@pytest.mark.system
|
||
@pytest.mark.p1
|
||
class TestRoleManagementExtended:
|
||
"""角色管理扩展测试。"""
|
||
|
||
def test_list_roles(self, client, admin_headers):
|
||
"""角色列表查询。"""
|
||
resp = client.get("/api/system/roles", headers=admin_headers)
|
||
assert resp.status_code == 200
|
||
assert len(resp.json()["data"]["list"]) >= 1
|
||
|
||
def test_create_role(self, client, admin_headers):
|
||
"""创建角色。"""
|
||
resp = client.post("/api/system/roles", headers=admin_headers, json={
|
||
"role_name": "临时角色",
|
||
"role_code": "temp_role",
|
||
})
|
||
assert resp.status_code == 200
|
||
assert resp.json()["data"]["role_name"] == "临时角色"
|
||
|
||
def test_get_role_menus(self, client, admin_headers):
|
||
"""SYS-011b: 查询角色菜单。"""
|
||
resp = client.get("/api/system/roles/1/menus", headers=admin_headers)
|
||
assert resp.status_code == 200
|
||
|
||
def test_assign_role_menus(self, client, admin_headers):
|
||
"""分配角色菜单。"""
|
||
resp = client.put("/api/system/roles/2/menus", headers=admin_headers, json={
|
||
"menu_ids": [1, 2, 12, 13, 16, 4, 22, 23, 45],
|
||
})
|
||
assert resp.status_code == 200
|
||
|
||
|
||
@pytest.mark.system
|
||
@pytest.mark.p1
|
||
class TestMenuManagementExtended:
|
||
"""菜单管理扩展测试。"""
|
||
|
||
def test_list_menus(self, client, admin_headers):
|
||
"""菜单树查询。"""
|
||
resp = client.get("/api/system/menus", headers=admin_headers)
|
||
assert resp.status_code == 200
|
||
|
||
def test_create_menu(self, client, admin_headers):
|
||
"""创建菜单。"""
|
||
resp = client.post("/api/system/menus", headers=admin_headers, json={
|
||
"menu_name": "测试菜单",
|
||
"menu_path": "/test",
|
||
"menu_type": "page",
|
||
"permission_code": "test:page",
|
||
"sort_no": 99,
|
||
})
|
||
assert resp.status_code == 200
|
||
|
||
def test_update_menu(self, client, admin_headers, db_session):
|
||
"""SYS-011c: 更新菜单。"""
|
||
from backend.app.models.system import Menu
|
||
menu = Menu(
|
||
menu_name="待更新", menu_path="/update-test",
|
||
menu_type="page", permission_code="update:test",
|
||
sort_no=99, status=1,
|
||
)
|
||
db_session.add(menu)
|
||
db_session.flush()
|
||
resp = client.put(f"/api/system/menus/{menu.id}", headers=admin_headers, json={
|
||
"menu_name": "已更新",
|
||
"permission_code": "update:test",
|
||
})
|
||
assert resp.status_code == 200
|
||
|
||
|
||
@pytest.mark.system
|
||
@pytest.mark.p1
|
||
class TestSystemPermissionBoundary:
|
||
"""系统管理权限边界。"""
|
||
|
||
def test_salesman_cannot_access_system(self, client, salesman_headers):
|
||
"""业务员不能访问系统管理。"""
|
||
for path in ["/api/system/users", "/api/system/roles", "/api/system/menus"]:
|
||
resp = client.get(path, headers=salesman_headers)
|
||
assert resp.status_code == 403, f"{path} should be 403 for salesman"
|
||
|
||
def test_driver_cannot_access_system(self, client, driver_headers):
|
||
"""司机不能访问系统管理。"""
|
||
for path in ["/api/system/users", "/api/system/roles", "/api/system/menus"]:
|
||
resp = client.get(path, headers=driver_headers)
|
||
assert resp.status_code == 403, f"{path} should be 403 for driver"
|
||
|
||
def test_manager_cannot_manage_users(self, client, manager_headers):
|
||
"""经理不能管理用户。"""
|
||
resp = client.get("/api/system/users", headers=manager_headers)
|
||
assert resp.status_code == 403
|