1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
import assert from 'node:assert/strict';
import { createThreadPrefetch } from '../src/thread-prefetch.js';
let time = 0, task, calls = [], rows = [], resolve;
const cached = new Set();
const doc = { hidden: false, documentElement: { clientHeight: 800 }, querySelectorAll: () => rows };
const nav = { onLine: true, connection: {} };
const p = createThreadPrefetch({ doc, nav, now: () => time,
schedule: (fn) => { task = fn; return 1; }, cancel: () => { task = null; },
key: (e) => e.id, cached: (e) => cached.has(e.id),
load: (e) => { calls.push(e.id); cached.add(e.id); return new Promise((r) => { resolve = r; }); },
});
const row = (id, top = 0, height = 300) => ({ id, top, height,
getAttribute() { return this.id; },
getBoundingClientRect() { return { top: this.top, bottom: this.top + this.height, height: this.height }; },
});
const tick = async (ms = 250) => { time += ms; const fn = task; task = null; fn?.(); await Promise.resolve(); await Promise.resolve(); await Promise.resolve(); };
const watch = (...rs) => { rows = rs; for (const r of rs) p.watch({ id: r.id }); };
const dwell = async () => { for (let i = 0; i < 7; i++) await tick(); };
watch(row('passing')); await tick(); rows = []; await dwell(); assert.deepEqual(calls, []);
watch(row('moving')); for (let i = 0; i < 8; i++) { rows[0].top += 30; await tick(); } assert.deepEqual(calls, []);
watch(row('hidden')); doc.hidden = true; await dwell(); assert.deepEqual(calls, []); doc.hidden = false;
nav.connection.saveData = true; await dwell(); assert.deepEqual(calls, []); nav.connection.saveData = false;
watch(row('tall', -200, 1800), row('second', 100)); await dwell(); assert.deepEqual(calls, ['tall']);
await dwell(); assert.deepEqual(calls, ['tall'], 'only one in-flight fetch');
resolve(); await tick(); await tick(); assert.deepEqual(calls, ['tall', 'second']);
resolve(); await tick(); await dwell(); assert.equal(calls.length, 2, 'cached posts are reused');
for (let i = 0; i < 5; i++) { watch(row('rate' + i)); await dwell(); resolve(); await tick(); }
assert.equal(calls.length, 6, 'six starts per minute');
await tick(60000); assert.equal(calls.length, 7); resolve(); await tick();
watch(row('cancelled')); p.stop(); await dwell(); assert.equal(calls.length, 7);
console.log('✓ dwell, fast scrolling, unmount, hidden tab, data saver, tall posts, concurrency, cache, rate limit and stop');
|