# -*- coding: utf-8 -*- """页面级联调验证(playwright + 系统 Chrome headless)""" import io, sys, time, json from playwright.sync_api import sync_playwright sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') BASE = 'http://localhost:8088' token = io.open('tmp/pw_token.txt', encoding='utf-8').read().strip() STORY_ID = 6566 # 研发需求(有冒烟数据:pass 审查状态) USERSTORY_ID = 324 # 用户需求 MEETING_ID = 75 # 会议 checks = [] def check(name, ok, note=''): checks.append((name, ok, note)) print(('PASS ' if ok else 'FAIL ') + name + (' | ' + note if note else '')) with sync_playwright() as p: browser = p.chromium.launch(channel='chrome', headless=True, args=['--disable-gpu']) page = browser.new_page(viewport={'width': 1500, 'height': 950}) page.on('console', lambda m: None) # 真实 UI 登录(store.token 不从 localStorage 初始化,必须走 doLogin) page.goto(BASE, wait_until='domcontentloaded') page.wait_for_timeout(2500) page.locator('input[placeholder="用户名"]').fill('admin') page.locator('input[placeholder="密码"]').fill('123456') page.locator('text="登录"').first.click() page.wait_for_timeout(6000) check('登录跳转', '/login' not in page.url, page.url[-40:]) # 1) 研发需求详情页 page.goto(f'{BASE}/#/product-story-info/{STORY_ID}', wait_until='domcontentloaded') page.wait_for_timeout(6000) text = page.inner_text('body') check('研发详情-需求ID区块', '需求 ID' in text or '需求ID' in text) check('研发详情-AI指标区块', 'AI 指标' in text or 'AI指标' in text or '功能点数' in text) check('研发详情-代码审查报告区块', '代码审查报告' in text) check('研发详情-审查状态pass显示', 'pass' in text or '通过' in text) check('研发详情-提交测试报告区块', '提交测试报告' in text) check('研发详情-工作日志区块', '工作日志' in text) check('研发详情-测试用例区块', '测试用例' in text) page.screenshot(path='tmp/pw_story_detail.png', full_page=False) # 点击审查报告里的在线查看(如存在) try: btn = page.locator('text=在线查看').first if btn.count() > 0: btn.click() page.wait_for_timeout(3000) dlg_txt = page.inner_text('body') check('MD在线渲染(审查报告)', 'AI 代码审查报告' in dlg_txt or '审查事项' in dlg_txt) page.screenshot(path='tmp/pw_mdpreview.png', full_page=False) page.keyboard.press('Escape') except Exception as e: check('MD在线渲染(审查报告)', False, str(e)[:80]) # 2) 用户需求详情-需求讨论会议 tab page.goto(f'{BASE}/#/product-user-story-info/{USERSTORY_ID}', wait_until='domcontentloaded') page.wait_for_timeout(5000) try: tab = page.locator('text=需求讨论会议').first check('用户需求-会议tab存在', tab.count() > 0) if tab.count() > 0: tab.click() page.wait_for_timeout(3000) except Exception as e: check('用户需求-会议tab存在', False, str(e)[:80]) page.screenshot(path='tmp/pw_userstory_tab.png', full_page=False) # 3) 会议纪要详情页 page.goto(f'{BASE}/#/product-meeting-info/{MEETING_ID}', wait_until='domcontentloaded') page.wait_for_timeout(5000) text3 = page.inner_text('body') check('会议详情-附件区块', '附件' in text3) page.screenshot(path='tmp/pw_meeting.png', full_page=False) browser.close() failed = [c for c in checks if not c[1]] print(f'\n== 汇总: {len(checks)-len(failed)}/{len(checks)} 通过 ==') for c in failed: print(' 未过:', c[0], c[2])