80 lines
4.8 KiB
JavaScript
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();
|