Files
juzi/taobao/test/page-header.test.cjs
T
xsl 774376fa16 feat: 完善淘宝小程序拍照、报告与登录流程
接入本地实时识别和自动三连拍,调整报告裁切、商品跳转、分享标题及居中页眉;完善游客会话、后台渠道隔离、部署脚本与回归测试。
2026-11-04 15:07:51 +08:00

71 lines
4.7 KiB
JavaScript

const test = require('node:test'), assert = require('node:assert/strict');
const header = require('../utils/page-header');
test('header reserves status/notch and native controls, preserves page lifecycle and refreshes on resize', () => {
let info = { statusBarHeight: 59, titleBarHeight: 44 }, loaded = 0, resized = 0;
const p = header.page({ data: { original: true }, onLoad(query) { assert.equal(this.data.brandHeader.height, 103); loaded++; return query.id; },
onResize() { resized++; } }, { getSystemInfoSync: () => info });
p.setData = patch => Object.assign(p.data, patch);
assert.equal(p.onLoad({ id: 7 }), 7); assert.equal(loaded, 1); assert.equal(p.data.original, true);
assert.equal(p.data.brandHeader.title, "1'me肌肤状态检测");
info = { safeArea: { top: 24 }, titleBarHeight: 48 }; p.onResize();
assert.equal(p.data.brandHeader.height, 72); assert.equal(resized, 1);
assert.equal(header.layout({ getSystemInfoSync() { throw Error('unsupported'); } }).height, 64);
});
test('native title is cleared on load, ready and return without interfering with login or late callbacks', () => {
const calls = []; let shown = 0, ready = 0, hidden = 0;
const p = header.page({ data: {}, onShow() { shown++; return 'login-flow'; }, onReady() { ready++; }, onHide() { hidden++; } },
{ setNavigationBar(options) { calls.push(options); } }, { nativeTitleFallback: true });
p.setData = patch => Object.assign(p.data, patch);
p.onLoad(); p.onReady(); assert.equal(p.onShow(), 'login-flow');
assert.equal(calls.length, 3); assert.equal(shown, 1); assert.equal(ready, 1);
assert(calls.every(call => call.title === '\u200b' && !('backgroundColor' in call)));
calls[0].fail({}); assert.equal(p.data.brandHeader.showTitle, true, 'stale native failure cannot hide the current title');
calls[2].fail({}); assert.equal(p.data.brandHeader.showTitle, false, 'entry page falls back to one platform title if clearing is rejected');
p.onShow(); calls[3].success({}); assert.equal(p.data.brandHeader.showTitle, true);
p.onShow(); p.onHide(); calls[4].fail({}); assert.equal(hidden, 1); assert.equal(p.data.brandHeader.showTitle, true);
});
test('native errors cannot block page loading and rejected promises are observed', async () => {
let loaded = 0;
for (const mode of ['throw', 'reject']) {
const p = header.page({ data: {}, onLoad() { loaded++; } }, { setNavigationBar() {
if (mode === 'throw') throw Error('unsupported'); return Promise.reject(Error('unsupported'));
} }, { nativeTitleFallback: true });
p.setData = patch => Object.assign(p.data, patch); p.onLoad();
await new Promise(resolve => setImmediate(resolve));
assert.equal(p.data.brandHeader.showTitle, false);
}
assert.equal(loaded, 2);
});
test('actual header template centers on the full screen and keeps clear of status and native buttons', async () => {
const fs = require('node:fs'), path = require('node:path'), { chromium } = require('playwright');
const root = path.resolve(__dirname, '..');
const axml = fs.readFileSync(path.join(root, 'components/brand-header.axml'), 'utf8');
const css = fs.readFileSync(path.join(root, 'app.acss'), 'utf8');
const browser = await chromium.launch({ headless: true });
try {
const tab = await browser.newPage();
for (const width of [320, 375, 414]) for (const top of [20, 59]) {
const geometry = header.layout({ getSystemInfoSync: () => ({ statusBarHeight: top, titleBarHeight: 44 }) });
const html = axml.replace(/<\/?template[^>]*>/g, '').replace(/view/g, 'div').replace(/<\/?text/g, tag => tag.replace('text', 'span'))
.replace(/\{\{brandHeader\.(\w+)\}\}/g, (_, key) => geometry[key]);
await tab.setViewportSize({ width, height: 812 });
await tab.setContent('<style>body{margin:0}' + css + '</style>' + html);
const bounds = await tab.evaluate(() => {
const row = document.querySelector('.brand-header-line').getBoundingClientRect();
const title = document.querySelector('.brand-header-title').getBoundingClientRect();
return { rowTop: row.top, titleCenter: title.left + title.width / 2, left: title.left, right: title.right };
});
assert.equal(bounds.rowTop, top); assert(Math.abs(bounds.titleCenter - width / 2) < .01);
assert(bounds.left >= 76 && bounds.right <= width - 76);
}
for (const route of JSON.parse(fs.readFileSync(path.join(root, 'app.json'), 'utf8')).pages) {
const config = JSON.parse(fs.readFileSync(path.join(root, route + '.json'), 'utf8'));
assert.equal(config.transparentTitle, 'always'); assert.equal(config.defaultTitle, '\u200b');
assert.match(fs.readFileSync(path.join(root, route + '.axml'), 'utf8'), /template is="brand-header"/);
}
} finally { await browser.close(); }
});