release: freeze demo v1.1.0 2026-10-19
CI/CD Pipeline / Backend Build & Test (push) Waiting to run
CI/CD Pipeline / Admin Web Build (push) Waiting to run
CI/CD Pipeline / Mini Program Compile Check (push) Waiting to run
CI/CD Pipeline / Migration Validation (push) Blocked by required conditions
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Waiting to run
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Waiting to run
CI/CD Pipeline / E2E (live stack) (push) Blocked by required conditions
CI/CD Pipeline / Backend Build & Test (push) Waiting to run
CI/CD Pipeline / Admin Web Build (push) Waiting to run
CI/CD Pipeline / Mini Program Compile Check (push) Waiting to run
CI/CD Pipeline / Migration Validation (push) Blocked by required conditions
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Waiting to run
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Waiting to run
CI/CD Pipeline / E2E (live stack) (push) Blocked by required conditions
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* 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
|
||||
})
|
||||
Reference in New Issue
Block a user