import fs from 'node:fs'; import path from 'node:path'; import assert from 'node:assert/strict'; import { chromium } from '@playwright/test'; const report = path.resolve('reports/instructors-v2-20260914'); const origin = 'http://127.0.0.1:8003'; const values = new Map(fs.readFileSync('../账号.MD', 'utf8').split(/\r?\n/).flatMap(line => { const match = line.match(/^\s*([^::]+)\s*[::]\s*(.*?)\s*$/); return match ? [[match[1].trim(), match[2].trim()]] : []; })); const browser = await chromium.launch({ channel: 'msedge', headless: true, args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] }); try { const context = await browser.newContext({ viewport: { width: 1920, height: 1080 } }); const page = await context.newPage(); const errors = []; page.on('pageerror', error => errors.push(error.message)); await page.goto(origin + '/login'); await page.locator('[data-role-code="admin"]').click(); await page.locator('input[name="username"]').fill(values.get('账号') || values.get('用户名')); await page.locator('input[name="password"]').fill(values.get('密码')); await page.getByRole('button', { name: /^(?:登录|登录系统|正在验证身份)$/ }).click(); await page.waitForURL(url => !url.pathname.startsWith('/login'), { timeout: 30000 }); await page.goto(origin + '/assets/avatars'); await page.locator('.avatar-card').first().waitFor(); assert.equal(await page.locator('.avatar-card').count(), 3); await page.waitForFunction(() => [...document.querySelectorAll('.avatar-cover img')].every(image => image.complete && image.naturalWidth > 0)); await page.screenshot({ path: report + '/catalog-v2.png', fullPage: true }); const cards = await page.locator('.avatar-card').allTextContents(); assert.ok(cards.find(text => text.includes('教员2'))?.includes('默认数字人')); const previews = []; for (const number of [1, 2, 3]) { const card = page.locator('.avatar-card').filter({ has: page.getByRole('heading', { name: `教员${number}`, exact: true }) }); await card.getByRole('button', { name: '预览', exact: true }).click(); const dialog = page.locator('.el-dialog:visible'); await dialog.waitFor(); const iframe = dialog.locator('iframe'); await iframe.waitFor(); const source = await iframe.getAttribute('src'); assert.ok(source.includes(`a100000000000000000000000000000${number + 4}`)); const frame = await (await iframe.elementHandle()).contentFrame(); await frame.waitForFunction(() => window.DH_RUNTIME_READY, {}, { timeout: 120000 }); await page.screenshot({ path: `${report}/catalog-preview-${number}.png`, fullPage: true }); previews.push({ number, viewer: source, ready: true }); await dialog.locator('.el-dialog__headerbtn').click(); await dialog.waitFor({ state: 'hidden' }); } assert.deepEqual(errors, []); const result = { count: 3, defaultInstructor: 2, previews, errors }; fs.writeFileSync(`${report}/catalog-validation.json`, JSON.stringify(result, null, 2)); console.log(JSON.stringify(result)); } finally { await browser.close(); }