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()
|