71 lines
4.7 KiB
JavaScript
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(); }
|
|
});
|