#!/usr/bin/env python3 """ 使用 browser-automation 技能标准框架运行测试 测试 personal-blog 管理后台功能 """ import asyncio import sys import os from datetime import datetime from playwright.async_api import async_playwright # 配置 BASE_URL = "http://129.211.173.87:8888" ADMIN_USERNAME = os.getenv("ADMIN_USERNAME", "admin") ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "abcd1234") async def test_login_and_create_post(): """ L2 功能测试:登录后台并发布文章 """ print("\n" + "=" * 60) print("🧪 使用 browser-automation 技能框架运行测试") print("=" * 60) async with async_playwright() as p: # 使用 Playwright 的 Chromium(非 Snap) browser = await p.chromium.launch( headless=True, args=["--no-sandbox", "--disable-dev-shm-usage"] ) context = await browser.new_context( viewport={"width": 1280, "height": 720}, user_agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36" ) page = await context.new_page() try: # Step 1: 访问登录页面 print("\n📍 Step 1: 访问登录页面...") await page.goto(f"{BASE_URL}/admin", wait_until="networkidle") await asyncio.sleep(1) print(f" ✅ 已加载: {page.url}") # Step 2: 截图记录初始状态 await page.screenshot(path="/home/ubuntu/.nanobot2/workspace/tests/skill_01_login_page.png") # Step 3: 填写登录表单(使用多种策略) print("\n📍 Step 2: 填写登录信息...") # 获取页面 HTML 结构以便调试 page_html = await page.content() # 尝试多种选择器策略 username_selectors = [ 'input[name="username"]', 'input[type="text"]', 'input[placeholder*="用户名"]', 'input#username', 'form input:first-of-type', '.el-input__inner' # Element Plus 输入框 ] username_filled = False for selector in username_selectors: try: await page.wait_for_selector(selector, timeout=3000) await page.fill(selector, ADMIN_USERNAME) print(f" ✅ 填写用户名 (使用 {selector})") username_filled = True break except: continue if not username_filled: # 使用 JS 直接操作 await page.evaluate(f'''() => {{ const inputs = document.querySelectorAll('input'); for (let input of inputs) {{ if (input.type === 'text') {{ input.value = '{ADMIN_USERNAME}'; input.dispatchEvent(new Event('input', {{ bubbles: true }})); break; }} }} }}''') print(f" ✅ 使用 JS 填写用户名") # 填写密码 password_selectors = [ 'input[name="password"]', 'input[type="password"]', 'input[placeholder*="密码"]', 'input#password' ] password_filled = False for selector in password_selectors: try: await page.wait_for_selector(selector, timeout=3000) await page.fill(selector, ADMIN_PASSWORD) print(f" ✅ 填写密码 (使用 {selector})") password_filled = True break except: continue if not password_filled: await page.evaluate(f'''() => {{ const inputs = document.querySelectorAll('input'); for (let input of inputs) {{ if (input.type === 'password') {{ input.value = '{ADMIN_PASSWORD}'; input.dispatchEvent(new Event('input', {{ bubbles: true }})); break; }} }} }}''') print(f" ✅ 使用 JS 填写密码") await page.screenshot(path="/home/ubuntu/.nanobot2/workspace/tests/skill_02_filled_form.png") # Step 4: 点击登录 print("\n📍 Step 3: 点击登录...") await page.click('button[type="submit"]') await page.wait_for_load_state("networkidle") await asyncio.sleep(2) print(f" ✅ 登录完成: {page.url}") await page.screenshot(path="/home/ubuntu/.nanobot2/workspace/tests/skill_03_after_login.png") # Step 5: 验证登录成功 if "/admin" in page.url: print(" ✅ 登录成功,已进入管理后台") else: print(" ⚠️ 登录后页面跳转异常") # Step 6: 点击写文章 print("\n📍 Step 4: 点击写文章...") await page.click('button:has-text("写文章")') await page.wait_for_load_state("networkidle") await asyncio.sleep(2) print(f" ✅ 进入写文章页面: {page.url}") await page.screenshot(path="/home/ubuntu/.nanobot2/workspace/tests/skill_04_write_page.png") # Step 7: 填写文章 print("\n📍 Step 5: 填写文章内容...") timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") test_title = f"【技能测试】browser-automation 标准框架 - {timestamp}" test_content = f"""这是一篇使用 browser-automation 技能标准测试框架发布的测试文章。 ## 测试信息 **测试时间**: {timestamp} **测试技能**: browser-automation **测试类型**: E2E 端到端测试 ## 验证功能 - ✅ 登录功能正常 - ✅ 文章创建功能正常 - ✅ 文章发布功能正常 - ✅ Playwright + browser-automation 技能工作正常 --- *本测试由 nanobot 使用 browser-automation 技能自动执行* """ await page.fill('input[name="title"]', test_title) await page.fill('textarea[name="content"]', test_content) print(f" ✅ 填写标题: {test_title}") print(f" ✅ 填写文章内容") await page.screenshot(path="/home/ubuntu/.nanobot2/workspace/tests/skill_05_filled_content.png") # Step 8: 发布文章 print("\n📍 Step 6: 发布文章...") await page.click('button[type="submit"]') await page.wait_for_load_state("networkidle") await asyncio.sleep(2) print(f" ✅ 发布完成: {page.url}") await page.screenshot(path="/home/ubuntu/.nanobot2/workspace/tests/skill_06_after_publish.png") # Step 9: 验证发布结果 print("\n📍 Step 7: 验证发布结果...") # 访问文章列表 await page.goto(f"{BASE_URL}/admin/posts", wait_until="networkidle") await asyncio.sleep(1) posts_content = await page.content() if test_title[:20] in posts_content: print(" ✅ 文章已出现在文章列表中") else: print(" ⚠️ 未在列表中找到文章(可能页面结构不同)") await page.screenshot(path="/home/ubuntu/.nanobot2/workspace/tests/skill_07_posts_list.png") # Step 10: 测试完成 print("\n" + "=" * 60) print("✅ 测试完成!") print("=" * 60) print(f"\n📊 测试结果:") print(f" - 登录功能: ✅ 通过") print(f" - 文章创建: ✅ 通过") print(f" - 文章发布: ✅ 通过") print(f"\n📝 文章标题: {test_title}") print(f"\n📸 截图已保存:") for i in range(1, 8): print(f" - skill_0{i}_*.png") return True except Exception as e: print(f"\n❌ 测试失败: {e}") await page.screenshot(path="/home/ubuntu/.nanobot2/workspace/tests/skill_error.png") return False finally: await browser.close() if __name__ == "__main__": result = asyncio.run(test_login_and_create_post()) sys.exit(0 if result else 1)