test/framework/business/file_manager_page.py

119 lines
4.6 KiB
Python

import time
import os
from framework.core.base_page import BasePage
from framework.core.logger import get_logger
logger = get_logger("FileManagerPage")
class FileManagerPage(BasePage):
"""文件管理页面 POM - 纯原子操作层"""
MENU_TEXT = "数据管理"
def __init__(self, page):
self.page = page
def navigate_to(self):
"""进入页面"""
logger.info("正在切换到数据管理页面...")
self.smart_click(self.MENU_TEXT)
# 等待页面核心元素出现,确保切换完成
try:
self.page.wait_for_selector(".p-datatable, button:has-text('新建文件夹')", timeout=5000)
except:
pass
time.sleep(2)
def create_folder(self, name):
"""原子:创建文件夹"""
logger.info(f"📁 新建文件夹: {name}")
self.smart_click("新建文件夹")
self.page.fill("#folderName", name)
self.smart_click("确定", role="button")
time.sleep(1)
def enter_folder(self, name):
"""原子:双击进入文件夹"""
logger.info(f"📂 进入文件夹: {name}")
self.page.click(f"text='{name}'")
time.sleep(1)
def upload_files(self, file_paths):
"""原子:触发上传并选择文件"""
if isinstance(file_paths, str): file_paths = [file_paths]
logger.info(f"📤 准备上传文件: {file_paths}")
self.smart_click("上传")
time.sleep(0.5)
self.page.set_input_files("input[type='file']", file_paths)
def cancel_upload(self, slow_mode=True):
"""原子:在上传中途取消"""
logger.info("⏹️ 尝试取消上传任务")
if slow_mode: time.sleep(1)
try:
# 缩短超时时间,取消操作不应阻塞太久
self.smart_click("取消上传", timeout=1500)
except:
# 兜底:尝试点关闭图标或按 ESC
try:
self.page.evaluate("document.querySelector('button.p-dialog-header-close')?.click()")
self.page.keyboard.press("Escape")
except:
pass
time.sleep(1)
def wait_for_success(self, count=1):
"""原子:等待上传进度条跑完"""
logger.info(f"⏳ 等待进度达成 ({count})...")
start = time.time()
while time.time() - start < 300:
content = self.page.evaluate("() => document.querySelector('.p-dialog')?.innerText || ''")
if ("成功" in content and str(count) in content) or f"{count}/{count}" in content:
break
time.sleep(2)
time.sleep(2)
self.page.evaluate("document.querySelector('button.p-dialog-header-close')?.click()")
time.sleep(1)
def rename_item(self, old_name, new_name):
"""原子:执行行内重命名"""
logger.info(f"✏️ 重命名: {old_name} -> {new_name}")
self.page.evaluate(f"""() => {{
const row = Array.from(document.querySelectorAll('tr')).find(r => r.innerText.includes('{old_name}'));
row?.querySelector('button[aria-label="重命名"], .p-button-text')?.click();
}}""")
time.sleep(0.5)
self.page.fill("input[placeholder*='名称']", new_name)
# 强力点击确定 (支持文本、类名、角色)
self.smart_click("确定", role="button")
time.sleep(1)
def delete_item(self, name):
"""原子:执行行内删除"""
logger.info(f"🗑️ 删除: {name}")
self.page.evaluate(f"""() => {{
const row = Array.from(document.querySelectorAll('tr')).find(r => r.innerText.includes('{name}'));
if (!row) return;
const delBtn = row.querySelector('button[aria-label="删除"]') ||
Array.from(row.querySelectorAll('button')).find(b => b.innerText.includes('删除'));
delBtn?.click();
}}""")
time.sleep(1) # 等待弹窗动画完成
# 针对确认框的多种可能属性进行强力点击
try:
self.smart_click("确定", role="button", timeout=3000)
except:
# 兜底:直接寻找 PrimeVue 或 通用确认框的“接受”按钮类
self.page.evaluate("""() => {
const ok = document.querySelector('.p-confirm-dialog-accept, .p-dialog-footer button:last-child, .btn-primary');
if (ok) ok.click();
}""")
time.sleep(1)
def back_to_root(self):
"""原子:通过面包屑返回"""
logger.info("🔙 返回根目录")
self.smart_click("数据管理", timeout=2000)
time.sleep(1)