Files
juzi/h5/test/ui-20261009.mjs
T

80 lines
4.8 KiB
JavaScript

import { execSync } from 'node:child_process';
import { pathToFileURL } from 'node:url';
const { chromium } = await import(pathToFileURL(execSync('npm root -g', { encoding: 'utf8' }).trim() + '/playwright/index.mjs').href);
import fs from 'node:fs';
import assert from 'node:assert/strict';
const root = process.env.H5_ARTIFACT_DIR
? pathToFileURL(process.env.H5_ARTIFACT_DIR.replace(/\/$/, '') + '/')
: new URL('../../design/ui-20261009/verification/', import.meta.url);
fs.mkdirSync(root, { recursive: true });
const browser = await chromium.launch({ headless: true, args: ['--no-sandbox'] });
const page = await browser.newPage({ viewport: { width: 375, height: 726 } });
const errors = [];
page.on('pageerror', e => errors.push(e.message));
const base = process.env.H5_BASE_URL || 'http://127.0.0.1:8080/';
await page.goto(base);
await page.waitForFunction(() => !document.querySelector('#login-message').textContent.includes('检查'));
await page.evaluate(() => document.fonts.ready);
await page.waitForTimeout(400);
await page.screenshot({ path: new URL('01-login.png', root).pathname });
await page.click('[data-action="login-wechat"]');
assert(await page.locator('#s-login').evaluate(e => e.classList.contains('active')));
await page.check('#login-consent');
await page.click('[data-action="login-wechat"]');
await page.waitForFunction(() => document.querySelector('#login-message').textContent.includes('免登录'));
await page.click('[data-action="guest-experience"]');
await page.waitForSelector('#s-splash.active');
assert.equal(await page.locator('#p-login-success.show').count(), 0);
await page.waitForTimeout(400);
await page.waitForFunction(() => !document.querySelector('#toast').classList.contains('show'));
await page.waitForTimeout(400);
await page.screenshot({ path: new URL('02-home.png', root).pathname });
await page.click('[data-action="history"]');
await page.waitForFunction(() => document.querySelector('#history-count').textContent.includes('不保存'));
await page.waitForTimeout(400);
await page.screenshot({ path: new URL('03-history-empty.png', root).pathname });
await page.goBack();
await page.waitForSelector('#s-splash.active');
await page.reload();
await page.waitForSelector('#s-login.active');
await page.waitForFunction(() => !document.querySelector('#login-message').textContent.includes('检查'));
await page.click('[data-action="guest-experience"]');
await page.waitForSelector('#s-splash.active');
await page.click('[data-action="open-privacy"]');
await page.waitForTimeout(400);
await page.screenshot({ path: new URL('04-privacy.png', root).pathname });
await page.click('#privacy-check');
await page.click('[data-action="agree-continue"]');
await page.waitForTimeout(400);
assert.equal(await page.locator('#s-profile').evaluate(e => e.getBoundingClientRect().top), 0);
await page.screenshot({ path: new URL('05-profile.png', root).pathname });
// Static mask layout audit only; real capture flow is covered by e2e-browser.mjs.
await page.evaluate(() => document.querySelectorAll('.screen').forEach(s => s.classList.toggle('active', s.id === 's-cam')));
await page.waitForTimeout(400);
for (const [step, name, label] of [['0', 'front', '1/3<br>请正脸出镜'], ['2', 'right', '2/3<br>请右脸出镜'], ['1', 'left', '3/3<br>请左脸出镜']]) {
await page.evaluate(({ step, label }) => { document.querySelector('#cam-mask').dataset.step = step; document.querySelector('#cam-step').innerHTML = label; }, { step, label });
await page.screenshot({ path: new URL('08-camera-' + name + '-layout.png', root).pathname });
}
await page.goto(base + '?mock=1&screen=report');
await page.waitForFunction(() => document.querySelector('#stat-score b').textContent !== '--');
await page.waitForTimeout(1200);
assert.equal(await page.locator('.card-detail').count(), 3);
assert.equal(await page.locator('.dtab').count(), 7);
assert.equal(await page.locator('.card-product img#product-image').count(), 1);
await page.screenshot({ path: new URL('06-report-top.png', root).pathname });
await page.locator('#s-report').evaluate(e => { e.style.position = 'relative'; e.style.height = 'auto'; e.style.overflow = 'visible'; document.body.style.overflow = 'visible'; });
await page.screenshot({ path: new URL('07-report-full.png', root).pathname, fullPage: true });
for (const card of await page.locator('.card-detail').all()) {
for (const tab of await card.locator('.dtab').all()) {
await tab.click();
assert.equal(await card.locator('.dpanel.active').count(), 1);
}
}
for (const width of [320, 390, 480]) {
await page.setViewportSize({ width, height: 844 });
assert(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), 'horizontal overflow ' + width);
}
assert.deepEqual(errors, []);
console.log('PASS: login/consent/fallback/refresh/history/profile/report/7 tabs/3 viewport widths, no JS errors');
await browser.close();