{ "test_date": "2026-06-22 19:36:55", "module": "班级管理 (Class Management)", "version": "v1", "base_url": "http://localhost:3000", "covered_submodules": [ "admin-classes", "management-classes", "teacher-classes", "teacher-my-classes" ], "summary": { "total": 21, "passed": 18, "failed": 0, "warnings": 3 }, "roles": { "admin": { "role": "admin", "login_success": true, "access_tests": [ { "route_key": "admin_classes", "url": "http://localhost:3000/admin/school/classes", "expected_access": true, "http_status": 200, "final_url": "http://localhost:3000/admin/school/classes", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "页面正常加载", "passed": true } ] }, { "route_key": "management_classes", "url": "http://localhost:3000/management/grade/classes", "expected_access": true, "http_status": 200, "final_url": "http://localhost:3000/management/grade/classes", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "页面正常加载", "passed": true } ] }, { "route_key": "teacher_classes", "url": "http://localhost:3000/teacher/classes", "expected_access": true, "http_status": 200, "final_url": "http://localhost:3000/teacher/classes/my", "status": "warning", "errors": [], "warnings": [ "重定向到 http://localhost:3000/teacher/classes/my(预期 /teacher/classes)" ], "checks": [] }, { "route_key": "teacher_my_classes", "url": "http://localhost:3000/teacher/classes/my", "expected_access": true, "http_status": 200, "final_url": "http://localhost:3000/teacher/classes/my", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "页面正常加载", "passed": true } ] } ], "crud_tests": [ { "feature": "admin 班级 CRUD", "role": "admin", "operations": [ { "name": "列表加载", "passed": true, "detail": "列表/空状态正常显示" }, { "name": "打开创建对话框", "passed": true, "detail": "创建对话框已打开" }, { "name": "编辑入口存在", "passed": true, "detail": "无数据行,跳过" }, { "name": "删除入口存在", "passed": true, "detail": "无数据行,跳过" } ], "status": "passed", "errors": [] }, { "feature": "年级班级 CRUD (grade_head)", "role": "admin", "operations": [ { "name": "列表加载", "passed": false, "detail": "未找到表格或空状态" }, { "name": "打开创建对话框", "passed": false, "detail": "异常: Locator.click: Timeout 30000ms exceeded.\nCall log:\n - waiting for locator(\"button:has-text(\\\"New\\\"), button:has-text(\\\"新建\\\"), button:has-text(\\\"Create\\\"), button:has-text(\\\"新增\\\")\").first\n - locator resolved to \n - attempting click action\n 2 × waiting for element to be visible, enabled and stable\n - element is not enabled\n - retrying click action\n - waiting 20ms\n 2 × waiting for element to be visible, enabled and stable\n - element is not enabled\n - retrying click action\n - waiting 100ms\n 57 × waiting for element to be visible, enabled and stable\n - element is not enabled\n - retrying click action\n - waiting 500ms\n" }, { "name": "编辑入口存在", "passed": true, "detail": "无数据行,跳过" }, { "name": "删除入口存在", "passed": true, "detail": "无数据行,跳过" } ], "status": "warning", "errors": [] } ], "view_tests": [ { "feature": "教师班级查看", "role": "admin", "operations": [ { "name": "页面加载", "passed": true, "detail": "页面内容长度 401163" }, { "name": "班级卡片/列表存在", "passed": true, "detail": "找到卡片/表格/空状态(cards: 1, tables: 0, empty: 0)" } ], "status": "passed", "errors": [] } ], "errors": [], "warnings": [ "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran", "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran", "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran", "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran" ] }, "teacher": { "role": "teacher", "login_success": true, "access_tests": [ { "route_key": "admin_classes", "url": "http://localhost:3000/admin/school/classes", "expected_access": false, "http_status": 200, "final_url": "http://localhost:3000/teacher/dashboard?from=%2Fadmin%2Fschool%2Fclasses&reason=forbidden", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "权限拒绝重定向", "passed": true, "detail": "正确重定向到 http://localhost:3000/teacher/dashboard?from=%2Fadmin%2Fschool%2Fclasses&reason=forbidden" } ] }, { "route_key": "management_classes", "url": "http://localhost:3000/management/grade/classes", "expected_access": true, "http_status": 200, "final_url": "http://localhost:3000/management/grade/classes", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "页面正常加载", "passed": true } ] }, { "route_key": "teacher_classes", "url": "http://localhost:3000/teacher/classes", "expected_access": true, "http_status": 200, "final_url": "http://localhost:3000/teacher/classes/my", "status": "warning", "errors": [], "warnings": [ "重定向到 http://localhost:3000/teacher/classes/my(预期 /teacher/classes)" ], "checks": [] }, { "route_key": "teacher_my_classes", "url": "http://localhost:3000/teacher/classes/my", "expected_access": true, "http_status": 200, "final_url": "http://localhost:3000/teacher/classes/my", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "页面正常加载", "passed": true } ] } ], "crud_tests": [ { "feature": "admin 班级 CRUD", "role": "teacher", "operations": [], "status": "skipped", "errors": [ "teacher 无 SCHOOL_MANAGE 权限,跳过 admin 班级 CRUD 测试" ] }, { "feature": "年级班级 CRUD (grade_head)", "role": "teacher", "operations": [ { "name": "列表加载", "passed": true, "detail": "列表/空状态正常显示" }, { "name": "打开创建对话框", "passed": true, "detail": "创建对话框已打开" }, { "name": "编辑入口存在", "passed": true, "detail": "无数据行,跳过" }, { "name": "删除入口存在", "passed": true, "detail": "无数据行,跳过" } ], "status": "passed", "errors": [] } ], "view_tests": [ { "feature": "教师班级查看", "role": "teacher", "operations": [ { "name": "页面加载", "passed": true, "detail": "页面内容长度 401708" }, { "name": "班级卡片/列表存在", "passed": true, "detail": "找到卡片/表格/空状态(cards: 5, tables: 0, empty: 0)" } ], "status": "passed", "errors": [] } ], "errors": [], "warnings": [ "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran", "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran" ] }, "student": { "role": "student", "login_success": true, "access_tests": [ { "route_key": "admin_classes", "url": "http://localhost:3000/admin/school/classes", "expected_access": false, "http_status": 200, "final_url": "http://localhost:3000/student/dashboard?from=%2Fadmin%2Fschool%2Fclasses&reason=forbidden", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "权限拒绝重定向", "passed": true, "detail": "正确重定向到 http://localhost:3000/student/dashboard?from=%2Fadmin%2Fschool%2Fclasses&reason=forbidden" } ] }, { "route_key": "management_classes", "url": "http://localhost:3000/management/grade/classes", "expected_access": false, "http_status": 200, "final_url": "http://localhost:3000/student/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "权限拒绝重定向", "passed": true, "detail": "正确重定向到 http://localhost:3000/student/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden" } ] }, { "route_key": "teacher_classes", "url": "http://localhost:3000/teacher/classes", "expected_access": false, "http_status": 200, "final_url": "http://localhost:3000/student/dashboard?from=%2Fteacher%2Fclasses&reason=forbidden", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "权限拒绝重定向", "passed": true, "detail": "正确重定向到 http://localhost:3000/student/dashboard?from=%2Fteacher%2Fclasses&reason=forbidden" } ] }, { "route_key": "teacher_my_classes", "url": "http://localhost:3000/teacher/classes/my", "expected_access": false, "http_status": 200, "final_url": "http://localhost:3000/student/dashboard?from=%2Fteacher%2Fclasses%2Fmy&reason=forbidden", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "权限拒绝重定向", "passed": true, "detail": "正确重定向到 http://localhost:3000/student/dashboard?from=%2Fteacher%2Fclasses%2Fmy&reason=forbidden" } ] } ], "crud_tests": [ { "feature": "admin 班级 CRUD", "role": "student", "operations": [], "status": "skipped", "errors": [ "student 无 SCHOOL_MANAGE 权限,跳过 admin 班级 CRUD 测试" ] }, { "feature": "年级班级 CRUD (grade_head)", "role": "student", "operations": [], "status": "skipped", "errors": [ "student 无 GRADE_MANAGE 权限,跳过 management 班级 CRUD 测试" ] } ], "view_tests": [ { "feature": "教师班级查看", "role": "student", "operations": [], "status": "skipped", "errors": [ "student 无 CLASS_READ 权限,跳过教师班级查看测试" ] } ], "errors": [], "warnings": [] }, "parent": { "role": "parent", "login_success": true, "access_tests": [ { "route_key": "admin_classes", "url": "http://localhost:3000/admin/school/classes", "expected_access": false, "http_status": 200, "final_url": "http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fschool%2Fclasses&reason=forbidden", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "权限拒绝重定向", "passed": true, "detail": "正确重定向到 http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fschool%2Fclasses&reason=forbidden" } ] }, { "route_key": "management_classes", "url": "http://localhost:3000/management/grade/classes", "expected_access": false, "http_status": 200, "final_url": "http://localhost:3000/parent/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "权限拒绝重定向", "passed": true, "detail": "正确重定向到 http://localhost:3000/parent/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden" } ] }, { "route_key": "teacher_classes", "url": "http://localhost:3000/teacher/classes", "expected_access": false, "http_status": 200, "final_url": "http://localhost:3000/parent/dashboard?from=%2Fteacher%2Fclasses&reason=forbidden", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "权限拒绝重定向", "passed": true, "detail": "正确重定向到 http://localhost:3000/parent/dashboard?from=%2Fteacher%2Fclasses&reason=forbidden" } ] }, { "route_key": "teacher_my_classes", "url": "http://localhost:3000/teacher/classes/my", "expected_access": false, "http_status": 200, "final_url": "http://localhost:3000/parent/dashboard?from=%2Fteacher%2Fclasses%2Fmy&reason=forbidden", "status": "passed", "errors": [], "warnings": [], "checks": [ { "name": "权限拒绝重定向", "passed": true, "detail": "正确重定向到 http://localhost:3000/parent/dashboard?from=%2Fteacher%2Fclasses%2Fmy&reason=forbidden" } ] } ], "crud_tests": [ { "feature": "admin 班级 CRUD", "role": "parent", "operations": [], "status": "skipped", "errors": [ "parent 无 SCHOOL_MANAGE 权限,跳过 admin 班级 CRUD 测试" ] }, { "feature": "年级班级 CRUD (grade_head)", "role": "parent", "operations": [], "status": "skipped", "errors": [ "parent 无 GRADE_MANAGE 权限,跳过 management 班级 CRUD 测试" ] } ], "view_tests": [ { "feature": "教师班级查看", "role": "parent", "operations": [], "status": "skipped", "errors": [ "parent 无 CLASS_READ 权限,跳过教师班级查看测试" ] } ], "errors": [], "warnings": [ "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran" ] } }, "console_errors_global": [ { "role": "admin", "error": "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client branch `if (typeof window !== 'undefined')`.\n- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\n- Date formatting in a user's locale which doesn't match the server.\n- External changing data without sending a snapshot of it along with the HTML.\n- Invalid HTML tag nesting.\n\nIt can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n%s%s https://react.dev/link/hydration-mismatch \n\n ...\n
\n \n ...\n \n \n \n \n \n \n \n \n \n \n \n