95 lines
6.6 KiB
JavaScript
95 lines
6.6 KiB
JavaScript
const assert = require('node:assert/strict')
|
|||
|
|
const fs = require('node:fs')
|
||
|
|
const path = require('node:path')
|
||
|
|
const { chromium } = require('/Users/macclaw/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright')
|
||
|
|
|
||
|
|
async function main() {
|
||
|
|
const directory = '/Volumes/Extreme SSD/yawan-storage/weknora/acceptance'
|
||
|
|
const credentials = JSON.parse(fs.readFileSync(path.join(directory, 'super-admin-login.json'), 'utf8'))
|
||
|
|
const login = await fetch('http://127.0.0.1:18080/api/v1/auth/login', {
|
||
|
|
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify({ email: credentials.email, password: credentials.password }),
|
||
|
|
})
|
||
|
|
assert.equal(login.status, 200)
|
||
|
|
const auth = await login.json()
|
||
|
|
const browser = await chromium.launch({ headless: true, channel: 'chrome' })
|
||
|
|
const checks = [], errors = [], apiFailures = []
|
||
|
|
const check = (name, passed) => { checks.push({ name, passed: !!passed }); assert.ok(passed, name) }
|
||
|
|
let page
|
||
|
|
try {
|
||
|
|
const context = await browser.newContext({ viewport: { width: 1440, height: 1000 } })
|
||
|
|
await context.addInitScript(a => {
|
||
|
|
const values = { weknora_user: JSON.stringify({ ...a.user, tenant_id: String(a.user.tenant_id) }),
|
||
|
|
weknora_tenant: JSON.stringify({ ...a.active_tenant, id: '10059' }), weknora_token: a.token,
|
||
|
|
weknora_refresh_token: a.refresh_token, weknora_memberships: JSON.stringify(a.memberships) }
|
||
|
|
for (const [key, value] of Object.entries(values)) localStorage.setItem(key, value)
|
||
|
|
localStorage.setItem('weknora:new-user-guide-done:v1', '1')
|
||
|
|
}, auth)
|
||
|
|
page = await context.newPage()
|
||
|
|
page.on('pageerror', error => errors.push(error.message))
|
||
|
|
page.on('response', response => {
|
||
|
|
const url = new URL(response.url())
|
||
|
|
if (url.pathname.startsWith('/api/') && response.status() >= 400) apiFailures.push({ path: url.pathname, status: response.status() })
|
||
|
|
})
|
||
|
|
await page.goto('http://127.0.0.1:15173/platform/agents')
|
||
|
|
await page.locator('.user-button').waitFor()
|
||
|
|
const routeRegistered = await page.evaluate(() => {
|
||
|
|
const router = document.querySelector('#app').__vue_app__.config.globalProperties.$router
|
||
|
|
return router.getRoutes().some(route => route.path === '/platform/help')
|
||
|
|
})
|
||
|
|
check('manual_route_registered', routeRegistered)
|
||
|
|
await page.locator('.user-button').click()
|
||
|
|
check('upstream_github_menu_removed', await page.locator('.user-dropdown').getByText('GitHub', { exact: true }).count() === 0)
|
||
|
|
await page.locator('.user-dropdown').getByText('操作手册', { exact: true }).click()
|
||
|
|
await page.locator('.help-page').waitFor()
|
||
|
|
await page.locator('.user-dropdown').waitFor({ state: 'hidden' })
|
||
|
|
check('manual_menu_opens_internal_page', page.url().includes('/platform/help'))
|
||
|
|
check('admin_sections_visible_for_admin', await page.locator('.help-admin-label').count() === 7)
|
||
|
|
check('all_manual_sections_render', await page.locator('.help-section').count() === 22)
|
||
|
|
await page.screenshot({ path: path.join(directory, 'help-desktop.png'), animations: 'disabled' })
|
||
|
|
await page.locator('.help-directory a[href="#agents"]').click()
|
||
|
|
await page.waitForURL('**/platform/help#agents')
|
||
|
|
check('directory_updates_anchor', page.url().endsWith('#agents'))
|
||
|
|
check('agent_creation_steps_present', await page.locator('#agents').getByText('创建 Agent', { exact: true }).isVisible())
|
||
|
|
await page.getByRole('textbox', { name: '搜索操作手册' }).fill('二维码')
|
||
|
|
check('search_filters_sections', await page.locator('.help-section').count() === 1)
|
||
|
|
check('search_finds_wechat', await page.locator('#wechat').count() === 1)
|
||
|
|
await page.getByRole('textbox', { name: '搜索操作手册' }).fill('not-found-example-916')
|
||
|
|
check('empty_search_state', await page.locator('.help-empty').isVisible())
|
||
|
|
await page.getByRole('button', { name: '清除搜索', exact: true }).click()
|
||
|
|
await page.setViewportSize({ width: 390, height: 844 })
|
||
|
|
await page.evaluate(() => document.querySelector('.help-page').scrollIntoView({ block: 'start' }))
|
||
|
|
check('mobile_directory_collapses', await page.locator('.help-directory nav').isHidden())
|
||
|
|
await page.getByRole('button', { name: '手册目录', exact: true }).click()
|
||
|
|
check('mobile_directory_opens', await page.locator('.help-directory nav').isVisible())
|
||
|
|
await page.locator('.help-directory a[href="#content-tasks"]').click()
|
||
|
|
await page.waitForURL('**/platform/help#content-tasks')
|
||
|
|
check('mobile_directory_closes_after_selection', await page.locator('.help-directory nav').isHidden())
|
||
|
|
await page.screenshot({ path: path.join(directory, 'help-mobile.png'), animations: 'disabled' })
|
||
|
|
const mobileLayout = await page.evaluate(() => ({ width: innerWidth, scrollWidth: document.documentElement.scrollWidth, overflow: [...document.querySelectorAll('body *')].map(element => ({ name: element.tagName, class: element.className, rect: element.getBoundingClientRect().toJSON() })).filter(item => item.rect.right > innerWidth + 1 && item.rect.width > 0).slice(0, 12) }))
|
||
|
|
console.log(JSON.stringify({ mobile_layout: mobileLayout }))
|
||
|
|
check('mobile_no_horizontal_overflow', mobileLayout.scrollWidth <= mobileLayout.width + 1)
|
||
|
|
await page.evaluate(async () => {
|
||
|
|
const { useAuthStore } = await import('/src/stores/auth.ts')
|
||
|
|
const store = useAuthStore()
|
||
|
|
store.user = { ...store.user, is_system_admin: false, can_access_all_tenants: false }
|
||
|
|
store.memberships = store.memberships.map(membership => ({ ...membership, role: 'viewer' }))
|
||
|
|
})
|
||
|
|
await page.waitForFunction(() => document.querySelectorAll('.help-admin-label').length === 0)
|
||
|
|
check('admin_sections_hidden_for_viewer_ui', await page.locator('.help-section[id^="admin-"]').count() === 0)
|
||
|
|
await page.getByRole('textbox', { name: '搜索操作手册' }).fill('数据库迁移错误')
|
||
|
|
check('admin_content_excluded_from_viewer_search', await page.locator('.help-empty').isVisible())
|
||
|
|
check('no_page_errors', errors.length === 0)
|
||
|
|
const report = { checks, permission_test: 'UI store role transition only; no backend mutation or authorization claim', errors, api_failures: apiFailures }
|
||
|
|
fs.writeFileSync(path.join(directory, 'help-browser-20260916.json'), JSON.stringify(report, null, 2))
|
||
|
|
console.log(JSON.stringify(report, null, 2))
|
||
|
|
} catch (error) {
|
||
|
|
if (page) await page.screenshot({ path: path.join(directory, 'help-test-failure.png'), animations: 'disabled' }).catch(() => {})
|
||
|
|
console.log(JSON.stringify({ checks, errors, page_url: page?.url() }))
|
||
|
|
throw error
|
||
|
|
} finally {
|
||
|
|
await browser.close()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
main().catch(error => { console.error(error.message); process.exitCode = 1 })
|