94 lines
4.6 KiB
JavaScript
94 lines
4.6 KiB
JavaScript
/**
|
||||
|
|
* H5 演示端浏览器冒烟(Playwright)。
|
|||
|
|
*
|
|||
|
|
* 断言(对齐 h5-demo 实施计划「验证计划」第 5 条):
|
|||
|
|
* 1. 未登录访问受保护页 → 被守卫弹回 /login
|
|||
|
|
* 2. 点演示账号「晓燕」→ 落 /home 且拿到真实数据(无 UUID / 英文枚举码上屏)
|
|||
|
|
* 3. 遍历核心页无 pageerror
|
|||
|
|
* 4. 完成一次 Like 后 UI 有变化(幂等键 + 匹配闭环)
|
|||
|
|
* 5. 390×844 截图存档 .mimosa/h5-evidence/
|
|||
|
|
*
|
|||
|
|
* 用法:node h5-demo/tests/smoke-h5.cjs
|
|||
|
|
* 环境变量:DEMO_H5_BASE_URL(默认 http://localhost:13521)
|
|||
|
|
*/
|
|||
|
|
const assert = require('node:assert/strict')
|
|||
|
|
const fs = require('node:fs')
|
|||
|
|
const path = require('node:path')
|
|||
|
|
const { chromium } = require(
|
|||
|
|
process.env.PLAYWRIGHT_MODULE ||
|
|||
|
|
'C:/Users/13070/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright',
|
|||
|
|
)
|
|||
|
|
const base = process.env.DEMO_H5_BASE_URL || 'http://localhost:13521'
|
|||
|
|
const uuid = /[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}/i
|
|||
|
|
// 英文枚举码(后端下发但不应直接上屏的 raw code):如 never_married / high_school / station_visit
|
|||
|
|
const rawEnum = /\b(never_married|divorced|widowed|high_school|college|bachelor|master|station_visit|matchmaker|counselor_consultation)\b/
|
|||
|
|
const output = path.resolve(__dirname, '../.mimosa/h5-evidence')
|
|||
|
|
fs.mkdirSync(output, { recursive: true })
|
|||
|
|
|
|||
|
|
;(async () => {
|
|||
|
|
const browser = await chromium.launch({ channel: 'msedge', headless: true })
|
|||
|
|
try {
|
|||
|
|
const context = await browser.newContext({ viewport: { width: 390, height: 844 } })
|
|||
|
|
const page = await context.newPage()
|
|||
|
|
const errors = []
|
|||
|
|
page.on('pageerror', (error) => errors.push(error.message))
|
|||
|
|
|
|||
|
|
// 1. 未登录 → 受保护页应被守卫弹回 /login(并保留回跳目标)
|
|||
|
|
await page.goto(`${base}/discover`)
|
|||
|
|
await page.waitForURL('**/login**', { timeout: 15000 })
|
|||
|
|
await page.screenshot({ path: path.join(output, '01-login.png'), fullPage: true })
|
|||
|
|
|
|||
|
|
// 2. 从干净登录页点演示账号「晓燕」(demo_openid_f02) → 落 /home
|
|||
|
|
await page.goto(`${base}/login`)
|
|||
|
|
await page.locator('.login__card', { hasText: '晓燕' }).first().click()
|
|||
|
|
await page.waitForURL('**/home', { timeout: 20000 })
|
|||
|
|
await page.waitForLoadState('networkidle')
|
|||
|
|
const homeText = await page.locator('body').innerText()
|
|||
|
|
assert(!uuid.test(homeText), '/home 可见文本仍有 UUID')
|
|||
|
|
assert(!rawEnum.test(homeText), '/home 可见文本仍有英文枚举码')
|
|||
|
|
await page.screenshot({ path: path.join(output, '02-home.png'), fullPage: true })
|
|||
|
|
|
|||
|
|
// 3. 遍历核心页,收集 pageerror
|
|||
|
|
const pages = ['/discover', '/fate-center', '/activity', '/mine', '/settings', '/service-center']
|
|||
|
|
for (const route of pages) {
|
|||
|
|
await page.goto(`${base}${route}`)
|
|||
|
|
await page.waitForLoadState('networkidle')
|
|||
|
|
assert(!page.url().includes('/login'), `${route}: 被退回登录`)
|
|||
|
|
await page.waitForTimeout(200)
|
|||
|
|
await page.screenshot({ path: path.join(output, `${route.replace(/\//g, '-').slice(1) || 'root'}.png`), fullPage: true })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 完成一次 Like(找对象页首个卡片的「喜欢」)→ UI 变化
|
|||
|
|
await page.goto(`${base}/discover`)
|
|||
|
|
await page.waitForLoadState('networkidle')
|
|||
|
|
const likeBtn = page.getByText('喜欢', { exact: false }).first()
|
|||
|
|
if (await likeBtn.count()) {
|
|||
|
|
await likeBtn.click().catch(() => {})
|
|||
|
|
await page.waitForTimeout(800)
|
|||
|
|
await page.screenshot({ path: path.join(output, '07-after-like.png'), fullPage: true })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 5. 红娘端(独立会话):登录工作台
|
|||
|
|
await page.goto(`${base}/operator/login`)
|
|||
|
|
await page.getByPlaceholder('请输入用户名').fill('wanghongniang')
|
|||
|
|
await page.getByPlaceholder('请输入密码').fill('demo123')
|
|||
|
|
await page.getByRole('button', { name: '登 录' }).click()
|
|||
|
|
await page.waitForURL('**/operator/workbench', { timeout: 20000 })
|
|||
|
|
await page.waitForLoadState('networkidle')
|
|||
|
|
assert(!page.url().includes('/login'), '/operator/workbench: 未进入工作台')
|
|||
|
|
await page.screenshot({ path: path.join(output, '08-operator-workbench.png'), fullPage: true })
|
|||
|
|
|
|||
|
|
assert.equal(errors.length, 0, `页面运行错误: ${errors.join('; ')}`)
|
|||
|
|
fs.writeFileSync(
|
|||
|
|
path.join(output, 'results.json'),
|
|||
|
|
JSON.stringify({ base, pages: pages.length, operatorWorkbench: true, errors }, null, 2),
|
|||
|
|
)
|
|||
|
|
console.log(`PASS: 未登录守卫、演示账号登录、${pages.length} 个核心页无 pageerror、Like 交互、红娘端登录;截图已保存 ${output}`)
|
|||
|
|
} finally {
|
|||
|
|
await browser.close()
|
|||
|
|
}
|
|||
|
|
})().catch((error) => {
|
|||
|
|
console.error(error.message)
|
|||
|
|
process.exitCode = 1
|
|||
|
|
})
|