frontend/test/skeleton-tier-fill.test.ts
Rama master · réplica de lectura del repositorio original.
/* 横向骨架铺到右缘:铺满,而且整批只让浏览器布局几次。
*
* 改过 DOM 之后再读一次宽度,浏览器就得当场把整页布局一遍。冷启动时资料页那几排骨架逐枚
* 追加、逐枚量,实测一排一百多毫秒。这里用桩出来的几何数「改了又读」发生了几次。 */
import { afterEach, describe, expect, it } from 'vitest';
import { fillSkeletonTier, fitSkeleton } from '../src/ui-kit';
const ROW = 1000;
const SLOT = 100;
let layouts = 0;
let dirty = false;
const rect = (left: number, right: number) => ({ left, right, top: 0, bottom: 20, width: right - left, height: 20 });
const original = HTMLElement.prototype.getBoundingClientRect;
function row(kind: string): HTMLElement {
const node = document.createElement('div');
node.dataset.skeletonTier = kind;
const read = () => { if (dirty) { layouts++; dirty = false; } };
Object.defineProperty(node, 'clientWidth', { get: () => { read(); return ROW; } });
Object.defineProperty(node, 'scrollWidth', { get: () => { read(); return Math.max(ROW, node.children.length * SLOT); } });
const insert = node.insertAdjacentHTML.bind(node);
node.insertAdjacentHTML = (where: InsertPosition, html: string) => { dirty = true; insert(where, html); };
return node;
}
HTMLElement.prototype.getBoundingClientRect = function getBoundingClientRect(this: HTMLElement) {
const parent = this.parentElement;
if (this.dataset.skeletonTier) { if (dirty) { layouts++; dirty = false; } return rect(0, ROW) as DOMRect; }
if (parent?.dataset.skeletonTier) {
if (dirty) { layouts++; dirty = false; }
const index = [...parent.children].indexOf(this);
return rect(index * SLOT, (index + 1) * SLOT) as DOMRect;
}
return original.call(this);
};
afterEach(() => { layouts = 0; dirty = false; document.body.replaceChildren(); });
describe('横向骨架补满', () => {
it('几排一起补:每排都越过右缘,整批只布局两次', () => {
const root = document.createElement('div');
const rows = [row('av'), row('brandpill'), row('pill')];
root.append(...rows);
document.body.append(root);
fitSkeleton(root);
for (const node of rows) expect(node.children.length * SLOT).toBeGreaterThan(ROW);
expect(layouts).toBe(2);
});
it('已经铺满的那排再补一次不追加', () => {
const root = document.createElement('div');
const node = row('pill');
root.append(node);
document.body.append(root);
fitSkeleton(root);
const filled = node.children.length;
fitSkeleton(root);
expect(node.children.length).toBe(filled);
});
it('单独补一排也越过右缘,多出来的不超过一轮宽度序列', () => {
const node = row('av');
document.body.append(node);
fillSkeletonTier(node, 'av');
expect(node.children.length * SLOT).toBeGreaterThan(ROW);
expect(node.children.length).toBeLessThanOrEqual(ROW / SLOT + 2);
});
});