|
|
|
@@ -0,0 +1,114 @@ |
|
|
|
import fs from 'node:fs' |
|
|
|
import path from 'node:path' |
|
|
|
import { createRequire } from 'node:module' |
|
|
|
import { fileURLToPath } from 'node:url' |
|
|
|
import assert from 'node:assert/strict' |
|
|
|
import { login } from './role-permissions-live.mjs' |
|
|
|
const { chromium, expect } = createRequire(new URL('../package.json', import.meta.url))('@playwright/test') |
|
|
|
const report = fileURLToPath(new URL('../reports/guide-style-20260909/', import.meta.url)) |
|
|
|
fs.mkdirSync(report, { recursive:true }) |
|
|
|
const browser = await chromium.launch({ channel:'msedge', headless:true, args:['--enable-unsafe-swiftshader'] }) |
|
|
|
const checks = [], errors = [] |
|
|
|
const session = await login('root') |
|
|
|
const context = await browser.newContext({ viewport:{ width:1920, height:911 } }) |
|
|
|
await context.addInitScript(({ accessToken, refreshToken }) => { |
|
|
|
sessionStorage.setItem('unreal-tran:web:access-token:v1', accessToken) |
|
|
|
sessionStorage.setItem('unreal-tran:web:refresh-token:v1', refreshToken) |
|
|
|
}, session) |
|
|
|
const page = await context.newPage() |
|
|
|
page.on('pageerror', error => errors.push(error.message)) |
|
|
|
async function shot(name) { |
|
|
|
const overflow = await page.locator('.legacy-guide-page').evaluate(el => el.scrollWidth > el.clientWidth + 2) |
|
|
|
assert.equal(overflow, false, `${name}: page has no horizontal overflow`) |
|
|
|
await page.screenshot({ path:path.join(report, `${name}.png`), animations:'disabled' }) |
|
|
|
checks.push({ name, result:'PASS', screenshot:`${name}.png` }) |
|
|
|
} |
|
|
|
async function theme(mode) { |
|
|
|
await page.evaluate(async mode => (await import('/src/stores/preferences.ts')).usePreferencesStore().setThemeMode(mode), mode) |
|
|
|
} |
|
|
|
try { |
|
|
|
await page.goto('http://127.0.0.1:6180/content/ofd') |
|
|
|
await expect(page.locator('.guide-project-list')).toBeVisible({ timeout:60000 }) |
|
|
|
await theme('military') |
|
|
|
// Fixtures exist only in this disposable browser's local guide repository. |
|
|
|
await page.evaluate(async () => { |
|
|
|
const { legacyGuideContentStore } = await import('/src/features/guide-legacy/runtime.ts') |
|
|
|
for (let i=1;i<=12;i++) legacyGuideContentStore.createOFDProject({ id:`STYLE-${i}`, code:`STYLE-${String(i).padStart(3,'0')}`, title:`液压系统检查作业指导书 · 样式验证 ${i}`, author:'样式验证' }) |
|
|
|
}) |
|
|
|
await expect(page.locator('.guide-project-title')).toHaveCount(10) |
|
|
|
console.log('List loaded', await page.locator('.guide-project-title').count()) |
|
|
|
await shot('01-list') |
|
|
|
const count = await page.locator('.guide-project-title').count() |
|
|
|
await page.getByRole('textbox', { name:'搜索指导书', exact:true }).fill('NO-MATCH-GUIDE-STYLE') |
|
|
|
assert.equal(await page.locator('.guide-project-title').count(), count, 'Search waits for explicit submission') |
|
|
|
await page.locator('.guide-project-list').getByRole('button', { name:'搜索', exact:true }).click() |
|
|
|
await expect(page.locator('.guide-project-title')).toHaveCount(0) |
|
|
|
await page.getByRole('button', { name:'重置', exact:true }).click() |
|
|
|
await expect(page.locator('.guide-project-title')).toHaveCount(count) |
|
|
|
await page.locator('.system-pagination .btn-next').click() |
|
|
|
await expect(page.locator('.guide-project-title')).toHaveCount(2) |
|
|
|
await page.locator('.system-pagination .btn-prev').click() |
|
|
|
await expect(page.locator('.guide-project-title')).toHaveCount(10) |
|
|
|
if (count) { |
|
|
|
await page.locator('.guide-project-actions').first().getByRole('button', { name:'更多' }).click() |
|
|
|
await expect(page.getByRole('menuitem', { name:'项目详情', exact:true })).toBeVisible() |
|
|
|
await shot('02-list-actions') |
|
|
|
await page.getByRole('menuitem', { name:'项目详情', exact:true }).click() |
|
|
|
await expect(page.getByRole('button', { name:'关闭项目详情' })).toBeVisible() |
|
|
|
await page.getByRole('button', { name:'关闭项目详情' }).click() |
|
|
|
await page.locator('.guide-project-actions').first().getByRole('button', { name:'进入编制', exact:true }).click() |
|
|
|
await expect(page.locator('.ofd-view-editor')).toBeVisible({ timeout:60000 }) |
|
|
|
await shot('03-editor') |
|
|
|
await theme('dark') |
|
|
|
await shot('03-editor-dark') |
|
|
|
await theme('military') |
|
|
|
await page.locator('.ofd-top-actions [data-action="open-preview"]').click() |
|
|
|
await expect(page.locator('.ofd-workspace-dialog.preview')).toBeVisible() |
|
|
|
await shot('03-guide-preview') |
|
|
|
console.log('Editor loaded', page.url()) |
|
|
|
} |
|
|
|
await page.goto('http://127.0.0.1:6180/content/ofd/templates') |
|
|
|
await expect(page.locator('.guide-tpl-card')).toHaveCount(4, { timeout:30000 }) |
|
|
|
await page.locator('[data-guide-tpl-action="select"]').nth(1).click() |
|
|
|
await expect(page.locator('.guide-tpl-card').nth(1)).toHaveClass(/is-active/) |
|
|
|
await shot('04-templates') |
|
|
|
await page.locator('.guide-tpl-card').nth(1).getByRole('button', { name:'预览', exact:true }).click() |
|
|
|
await expect(page.locator('.guide-tpl-modal')).toBeVisible() |
|
|
|
await shot('05-template-preview') |
|
|
|
await page.goto('http://127.0.0.1:6180/content/ofd/api') |
|
|
|
await expect(page.locator('.ofd-api-layout')).toBeVisible({ timeout:30000 }) |
|
|
|
await shot('06-api') |
|
|
|
await page.getByRole('button', { name:'执行调用', exact:true }).click() |
|
|
|
await expect(page.locator('.ofd-api-result')).toBeVisible() |
|
|
|
await expect(page.locator('.ofd-api-result header b')).toHaveText('200') |
|
|
|
await shot('07-api-result') |
|
|
|
for (const mode of ['technology','graphite','dark']) { |
|
|
|
await theme(mode) |
|
|
|
await shot(`08-api-${mode}`) |
|
|
|
} |
|
|
|
await page.setViewportSize({ width:1366, height:768 }) |
|
|
|
await theme('military') |
|
|
|
await shot('09-api-laptop') |
|
|
|
await page.goto('http://127.0.0.1:6180/content/ofd/templates') |
|
|
|
await expect(page.locator('.guide-tpl-card')).toHaveCount(4) |
|
|
|
await shot('10-templates-laptop') |
|
|
|
await theme('dark') |
|
|
|
await shot('11-templates-dark') |
|
|
|
await page.goto('http://127.0.0.1:6180/content/ofd') |
|
|
|
await expect(page.locator('.guide-project-list')).toBeVisible() |
|
|
|
await shot('12-list-dark') |
|
|
|
await theme('military') |
|
|
|
await page.getByRole('button', { name:'新建指导书', exact:true }).click() |
|
|
|
await expect(page.locator('.ofd-app')).toBeVisible() |
|
|
|
await shot('13-create-wizard') |
|
|
|
assert.equal((await context.request.get('http://192.168.31.168:6180/')).status(),200) |
|
|
|
assert.deepEqual(errors, [], 'No unhandled browser exceptions') |
|
|
|
checks.push({ name:'搜索/重置、详情、编制入口、模板选择/预览、GET 接口自检、主题切换、局域网入口', result:'PASS' }) |
|
|
|
} catch(error) { |
|
|
|
await page.screenshot({ path:path.join(report,'failure.png') }).catch(()=>{}) |
|
|
|
console.error('Browser errors:',errors) |
|
|
|
throw error |
|
|
|
} finally { |
|
|
|
fs.writeFileSync(path.join(report,'results.json'), JSON.stringify({ checks, errors },null,2)) |
|
|
|
await browser.close() |
|
|
|
} |