#!/usr/bin/env node /** * 成果归属实测(2026-11-10) * * 验证点:用户自己上传的文件**只出现在「文件」页签**,不出现在「成果」。 * * 做法: * 1. 打开开发态登录的桌面端 * 2. 进入 lj-test 会话(`$approot_mwagplwv…`,里面有用户上传的 image.png) * 3. 切到右栏「文件」→ 截图 + 计数 * 4. 切到右栏「成果」→ 截图 + 计数 * * 用法:node scripts/verify-deliverable-separation.mjs */ import { chromium } from 'playwright'; import { mkdir } from 'node:fs/promises'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; const here = dirname(fileURLToPath(import.meta.url)); const root = resolve(here, '..'); const outDir = resolve(root, 'test-results/deliverable-separation'); const BASE = process.env.BASE_URL || 'http://127.0.0.1:4300'; /** 实测有用户上传图片的会话标题 */ const SESSION_TITLE = '使用HTML根据我这个图片做一个页面出来'; await mkdir(outDir, { recursive: true }); const browser = await chromium.launch({ /* 本机已装 Chrome,不必下载 Playwright 自带的 chromium */ channel: 'chrome', }); const page = await browser.newPage({ viewport: { width: 1440, height: 900 } }); const errors = []; page.on('pageerror', (e) => errors.push(String(e))); /* 🔴 不能用 networkidle:Matrix `/sync` 是长轮询,页面永远「不空闲」 */ await page.goto(`${BASE}/desktop/chat`, { waitUntil: 'domcontentloaded' }); await page.waitForTimeout(8000); // ① 找到目标会话并打开 const item = page.locator('text=' + SESSION_TITLE.slice(0, 12)).first(); if (await item.count()) { await item.click(); await page.waitForTimeout(4000); } else { console.log('⚠ 左栏没找到目标会话,截当前画面'); } // ② 右栏「文件」页签 const filesTab = page.getByRole('tab', { name: /文件/ }).first(); const resultsTab = page.getByRole('tab', { name: /成果/ }).first(); async function tabReport(tab, name) { if (!(await tab.count())) return { name, error: '找不到页签' }; await tab.click(); await page.waitForTimeout(1500); await page.screenshot({ path: `${outDir}/${name}.png` }); const pane = page.locator('aside, [class*="rail"]').last(); const text = (await pane.innerText().catch(() => '')) || ''; const hasImage = /image\.png/.test(text); const isEmpty = /暂无/.test(text); return { name, hasImage, isEmpty, textLen: text.length, snippet: text.slice(0, 200) }; } const files = await tabReport(filesTab, 'rail-files'); const results = await tabReport(resultsTab, 'rail-results'); console.log('\n=== 右栏「文件」==='); console.log(JSON.stringify(files, null, 2)); console.log('\n=== 右栏「成果」==='); console.log(JSON.stringify(results, null, 2)); const pass = files.hasImage && !results.hasImage; console.log(`\n${pass ? '✓ PASS' : '✗ FAIL'}:用户上传的 image.png ` + (files.hasImage ? '在「文件」中' : '**不在**「文件」中') + ',' + (results.hasImage ? '**仍在**「成果」中' : '不在「成果」中')); if (errors.length) console.log('页面错误:', errors.slice(0, 3)); await browser.close(); process.exit(pass ? 0 : 1);