|
- 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()
- }
|