# -*- coding: utf-8 -*- from playwright.sync_api import sync_playwright import sys, io import re sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') def run(): with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page(viewport={'width': 1440, 'height': 900}) errors = [] page.on('pageerror', lambda err: errors.append(f'PAGE_ERR: {str(err)[:200]}')) page.goto('http://localhost:5173', wait_until='networkidle', timeout=30000) page.wait_for_timeout(1000) # Login page.locator('input[type="text"]').first.fill('admin') page.locator('input[type="password"]').first.fill('admin123') page.locator('button').first.click() page.wait_for_timeout(3000) # ===================================================== # TEST: Model Config modal - check select visibility # ===================================================== print('=' * 60) print('TEST: Model Config 弹窗控件可见性') print('=' * 60) page.evaluate('window.location.hash = "/settings/model-config"') page.wait_for_timeout(2000) page.screenshot(path='/tmp/report_model_before.png', full_page=True) # Click new config button add_btn = page.locator('button:has-text("新建配置")') if add_btn.count() > 0: add_btn.first.click() page.wait_for_timeout(1500) page.screenshot(path='/tmp/report_model_modal.png', full_page=True) # Get all selects in dialog all_selects = page.locator('.t-dialog .t-select__wrap').all() print(f'弹窗中所有 t-select__wrap: {len(all_selects)}') for i, s in enumerate(all_selects): visible = s.is_visible() bb = s.bounding_box() print(f' 下拉{i}: visible={visible}, box={bb}') # Check provider select specially provider_select = page.locator('.t-dialog .t-select__wrap').nth(1) # second select print(f'\nProvider select visible: {provider_select.is_visible()}') print(f'Provider select box: {provider_select.bounding_box()}') # Check model input model_input = page.locator('.t-dialog input[placeholder*="模型名称"]') print(f'Model input count: {model_input.count()}') # Count ALL inputs in dialog all_inputs = page.locator('.t-dialog input:not([type="hidden"])') print(f'\nAll dialog inputs: {all_inputs.count()}') for i, inp in enumerate(all_inputs.all()[:15]): tp = inp.get_attribute('type') or 'text' ph = inp.get_attribute('placeholder') or '' vis = inp.is_visible() print(f' input{i}: type={tp}, placeholder="{ph[:40]}", visible={vis}') page.keyboard.press('Escape') page.wait_for_timeout(500) # ===================================================== # TEST: Check the appType filter select in toolbar # ===================================================== print('\n' + '=' * 60) print('TEST: 页面工具栏下拉控件') print('=' * 60) # Back to model config page toolbar_selects = page.locator('.t-select__wrap, .t-select').all() visible_selects = [s for s in toolbar_selects if s.is_visible()] print(f'可见下拉总数: {len(visible_selects)}') # ===================================================== # TEST: Doc upload modal # ===================================================== print('\n' + '=' * 60) print('TEST: 文档管理 - 上传弹窗') print('=' * 60) page.evaluate('window.location.hash = "/knowledge/document"') page.wait_for_timeout(2000) # 检查页面上的上传按钮 - 在旧代码中是 .upload-area 或按钮 upload_triggers = page.locator('button').all() upload_found = False for btn in upload_triggers: text = btn.inner_text() if btn.is_visible() else '' if '上传' in text: print(f'找到上传相关按钮: "{text}"') btn.click() page.wait_for_timeout(1000) upload_found = True page.screenshot(path='/tmp/report_upload_modal.png', full_page=True) page.keyboard.press('Escape') page.wait_for_timeout(500) break if not upload_found: print('WARNING: 未找到上传按钮') # ===================================================== # TEST: FAQ modal - check selects # ===================================================== print('\n' + '=' * 60) print('TEST: FAQ 弹窗 - 下拉控件详情') print('=' * 60) page.evaluate('window.location.hash = "/knowledge/faq"') page.wait_for_timeout(2000) add_faq = page.locator('button:has-text("添加 FAQ")') if add_faq.count() > 0: add_faq.first.click() page.wait_for_timeout(1000) page.screenshot(path='/tmp/report_faq_modal.png', full_page=True) faq_selects = page.locator('.t-dialog .t-select__wrap').all() for i, ds in enumerate(faq_selects): visible = ds.is_visible() bb = ds.bounding_box() print(f' FAQ弹窗下拉{i}: visible={visible}, box={bb}') page.keyboard.press('Escape') page.wait_for_timeout(500) # ===================================================== # TEST: Sensitive word modal - check selects # ===================================================== print('\n' + '=' * 60) print('TEST: 敏感词弹窗 - 下拉控件详情') print('=' * 60) page.evaluate('window.location.hash = "/settings/sensitive"') page.wait_for_timeout(2000) add_sw = page.locator('button:has-text("添加敏感词")') if add_sw.count() > 0: add_sw.first.click() page.wait_for_timeout(1000) page.screenshot(path='/tmp/report_sensitive_modal.png', full_page=True) sw_selects = page.locator('.t-dialog .t-select__wrap').all() for i, ds in enumerate(sw_selects): visible = ds.is_visible() bb = ds.bounding_box() print(f' 敏感词弹窗下拉{i}: visible={visible}, box={bb}') if visible: try: ds.click() page.wait_for_timeout(400) opts = page.locator('.t-select-option').all() print(f' 展开选项数: {len(opts)}') for o in opts: print(f' - {o.inner_text()[:50]}') page.keyboard.press('Escape') page.wait_for_timeout(200) except Exception as e: print(f' 展开异常: {e}') page.keyboard.press('Escape') page.wait_for_timeout(500) # ===================================================== # FINAL SUMMARY # ===================================================== print('\n' + '=' * 60) print('FINAL SUMMARY') print('=' * 60) if errors: unique_errs = list(set(errors)) print(f'PAGE ERRORS ({len(unique_errs)}):') for e in unique_errs: print(f' {e}') else: print('NO PAGE ERRORS') browser.close() if __name__ == '__main__': run()