- 修复冲突检测API测试参数错误(使用正确的classId/scheduledDate/scheduledTime) - 新增全面API测试脚本 (test_all_apis.sh) - 新增Python Playwright浏览器自动化测试 (test_schedule_page.py) - 新增前端E2E测试用例 (schedule-comprehensive.spec.ts, schedule-real.spec.ts) - 更新测试报告,所有API测试通过 测试覆盖: - 登录认证 ✅ - 课程套餐列表(两层结构)✅ - 排课列表/课表/日历视图 ✅ - 班级/教师列表 ✅ - 冲突检测API ✅ (已修复) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
206 lines
8.3 KiB
Python
206 lines
8.3 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
School Scheduling Page Browser Test
|
||
Tests the scheduling functionality including Tab navigation and create modal
|
||
"""
|
||
|
||
from playwright.sync_api import sync_playwright
|
||
import time
|
||
|
||
def test_schedule_page():
|
||
with sync_playwright() as p:
|
||
# Launch browser in headed mode to see what's happening
|
||
browser = p.chromium.launch(headless=False, slow_mo=1000)
|
||
page = browser.new_page()
|
||
|
||
print("=" * 60)
|
||
print("🧪 学校端排课功能测试")
|
||
print("=" * 60)
|
||
|
||
# Step 1: Navigate to login page
|
||
print("\n1️⃣ 导航到登录页面...")
|
||
page.goto('http://localhost:5174/login')
|
||
page.wait_for_load_state('networkidle')
|
||
print(" ✅ 登录页面加载完成")
|
||
|
||
# Step 2: Click school role button
|
||
print("\n2️⃣ 选择学校角色...")
|
||
try:
|
||
# Try multiple selector strategies
|
||
role_btn = page.locator('.role-btn').filter(has_text='学校').first
|
||
if role_btn.count() == 0:
|
||
role_btn = page.get_by_role('button').filter(has_text='学校').first
|
||
if role_btn.count() == 0:
|
||
# Try text-based selector
|
||
role_btn = page.locator('text=学校').first
|
||
role_btn.click()
|
||
print(" ✅ 已点击学校角色按钮")
|
||
except Exception as e:
|
||
print(f" ⚠️ 点击学校角色失败: {e}")
|
||
# Continue anyway
|
||
|
||
# Step 3: Fill login form
|
||
print("\n3️⃣ 填写登录表单...")
|
||
# Wait for the form to auto-fill based on role selection
|
||
page.wait_for_timeout(500)
|
||
|
||
# The form should auto-fill when role is selected, but let's verify
|
||
account_input = page.locator('input[placeholder*="账号"]').first
|
||
password_input = page.locator('input[placeholder*="密码"]').first
|
||
|
||
account_value = account_input.input_value()
|
||
print(f" 📝 账号输入框当前值: {account_value}")
|
||
|
||
# Fill if needed
|
||
if account_value != 'school1':
|
||
account_input.fill('school1')
|
||
password_input.fill('123456')
|
||
print(" ✅ 已填写账号和密码")
|
||
|
||
# Step 4: Click login button
|
||
print("\n4️⃣ 点击登录按钮...")
|
||
# Use the login-btn class which is more specific
|
||
login_btn = page.locator('.login-btn, button[type="submit"], button:has-text("登录")').first
|
||
login_btn.click()
|
||
|
||
# Wait for navigation
|
||
try:
|
||
page.wait_for_url('**/school/**', timeout=15000)
|
||
print(" ✅ 登录成功,已跳转到学校端")
|
||
except Exception as e:
|
||
print(f" ⚠️ 等待跳转超时: {e}")
|
||
# Check current URL
|
||
current_url = page.url
|
||
print(f" 📍 当前URL: {current_url}")
|
||
|
||
page.wait_for_load_state('networkidle')
|
||
time.sleep(2)
|
||
|
||
# Step 5: Navigate to schedule page
|
||
print("\n5️⃣ 导航到课程排期页面...")
|
||
page.goto('http://localhost:5174/school/schedule')
|
||
page.wait_for_load_state('networkidle')
|
||
time.sleep(2)
|
||
print(" ✅ 已导航到课程排期页面")
|
||
|
||
# Step 6: Take screenshot
|
||
print("\n6️⃣ 截图保存...")
|
||
page.screenshot(path='screenshots/schedule-page-test.png', full_page=True)
|
||
print(" ✅ 截图已保存: screenshots/schedule-page-test.png")
|
||
|
||
# Step 7: Check page title
|
||
print("\n7️⃣ 检查页面标题...")
|
||
try:
|
||
title_element = page.locator('h1, h2, .page-header').first
|
||
title = title_element.text_content()
|
||
print(f" ✅ 页面标题: {title}")
|
||
except:
|
||
print(" ⚠️ 未找到页面标题")
|
||
|
||
# Step 8: Check for Tab navigation
|
||
print("\n8️⃣ 检查Tab导航...")
|
||
tabs = page.locator('[role="tab"], .ant-tabs-tab').all()
|
||
print(f" 📊 找到 {len(tabs)} 个Tab")
|
||
for i, tab in enumerate(tabs):
|
||
try:
|
||
text = tab.text_content()
|
||
print(f" Tab {i+1}: {text}")
|
||
except:
|
||
print(f" Tab {i+1}: (无法获取文本)")
|
||
|
||
# Step 9: Click through each tab
|
||
print("\n9️⃣ 测试Tab切换...")
|
||
tab_labels = ['列表视图', '课表视图', '日历视图']
|
||
for label in tab_labels:
|
||
print(f"\n 🔄 切换到 {label}...")
|
||
try:
|
||
tab = page.locator('[role="tab"], .ant-tabs-tab').filter(has_text=label).first
|
||
if tab.count() > 0:
|
||
tab.click()
|
||
page.wait_for_timeout(1000)
|
||
screenshot_name = f'screenshots/schedule-{label.replace("视图", "")}-test.png'
|
||
page.screenshot(path=screenshot_name)
|
||
print(f" ✅ 已截图: {screenshot_name}")
|
||
|
||
# Check for content
|
||
if '列表' in label:
|
||
table = page.locator('.ant-table')
|
||
has_table = table.count() > 0
|
||
print(f" 📋 列表视图: {'有表格数据' if has_table else '无表格'}")
|
||
elif '课表' in label:
|
||
timetable = page.locator('.timetable-header, .day-header')
|
||
has_timetable = timetable.count() > 0
|
||
print(f" 📅 课表视图: {'有课表' if has_timetable else '无课表'}")
|
||
elif '日历' in label:
|
||
calendar = page.locator('.ant-picker-calendar')
|
||
has_calendar = calendar.count() > 0
|
||
print(f" 📆 日历视图: {'有日历' if has_calendar else '无日历'}")
|
||
else:
|
||
print(f" ⚠️ 未找到 {label} Tab")
|
||
except Exception as e:
|
||
print(f" ❌ 切换失败: {e}")
|
||
|
||
# Step 10: Try clicking "新建排课" button
|
||
print("\n🔟 测试新建排课按钮...")
|
||
try:
|
||
create_btn = page.locator('button:has-text("新建排课")').first
|
||
if create_btn.count() > 0:
|
||
create_btn.click()
|
||
page.wait_for_timeout(1500)
|
||
|
||
# Check if modal opened
|
||
modal = page.locator('.ant-modal').first
|
||
if modal.count() > 0:
|
||
print(" ✅ 新建排课弹窗已打开")
|
||
page.screenshot(path='screenshots/schedule-create-modal-test.png')
|
||
print(" ✅ 弹窗截图已保存")
|
||
|
||
# Check for dropdowns in modal
|
||
dropdowns = modal.locator('.ant-select').all()
|
||
print(f" 📝 弹窗中有 {len(dropdowns)} 个下拉框")
|
||
|
||
# Try clicking the first dropdown to see if it has course collections
|
||
if len(dropdowns) > 0:
|
||
dropdowns[0].click()
|
||
page.wait_for_timeout(500)
|
||
page.screenshot(path='screenshots/schedule-dropdown-test.png')
|
||
print(" ✅ 下拉框截图已保存")
|
||
else:
|
||
print(" ⚠️ 弹窗未打开")
|
||
else:
|
||
print(" ⚠️ 未找到新建排课按钮")
|
||
except Exception as e:
|
||
print(f" ❌ 新建排课测试失败: {e}")
|
||
|
||
# Final screenshot
|
||
print("\n📸 最终截图...")
|
||
page.screenshot(path='screenshots/schedule-final-test.png', full_page=True)
|
||
print(" ✅ 最终截图已保存")
|
||
|
||
# Get page content for debugging
|
||
print("\n📄 获取页面信息...")
|
||
current_url = page.url
|
||
print(f" 当前URL: {current_url}")
|
||
|
||
# Check for any error messages
|
||
error_msg = page.locator('.error-message, .ant-message-error, .ant-alert-error').all()
|
||
if error_msg:
|
||
print(" ⚠️ 发现错误消息:")
|
||
for msg in error_msg:
|
||
try:
|
||
text = msg.text_content()
|
||
print(f" - {text}")
|
||
except:
|
||
pass
|
||
|
||
print("\n" + "=" * 60)
|
||
print("✅ 测试完成!")
|
||
print("=" * 60)
|
||
|
||
# Keep browser open for a moment to see the result
|
||
time.sleep(3)
|
||
browser.close()
|
||
|
||
if __name__ == '__main__':
|
||
test_schedule_page()
|