diff options
Diffstat (limited to 'tools/thread-instant-test.js')
| -rw-r--r-- | tools/thread-instant-test.js | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/tools/thread-instant-test.js b/tools/thread-instant-test.js index 095b6cf..bd80408 100644 --- a/tools/thread-instant-test.js +++ b/tools/thread-instant-test.js @@ -24,9 +24,11 @@ const S2 = post('alice on bob, slow relay', 300, SKA, [['e', B1.id, '', 'root'], const C1 = post('carol posts last, fetched ahead', 200, SKC); const U1 = post('bob on carol, held back', 100, SKB, [['e', C1.id, '', 'root'], ['p', CAROL]]); const html = await buildHtml({ minify: true, pwa: false }); +const FACE = Bun.spawnSync(['ffmpeg', '-loglevel', 'error', '-f', 'lavfi', '-i', 'testsrc=size=96x96', '-frames:v', '1', '-f', 'image2', '-c:v', 'png', 'pipe:1']).stdout; const server = Bun.serve({ port: 0, fetch: (req) => { const path = new URL(req.url).pathname; if (path.startsWith('/punks')) return new Response(Bun.file('dist' + path)); + if (path === '/bob.png') return new Response(FACE, { headers: { 'content-type': 'image/png' } }); return new Response(html, { headers: { 'content-type': 'text/html' } }); } }); @@ -82,6 +84,7 @@ const thread = () => page.evaluate(() => ({ rows: [...document.querySelectorAll('.thread-page [data-zap-post]')].map((r) => r.getAttribute('data-zap-post')), spinner: !!document.querySelector('.thread-card .spinner'), text: document.querySelector('.thread-card')?.innerText || '', + face: [...document.querySelectorAll('.thread-page [data-zap-post]')].slice(-1)[0]?.querySelector('.note-avatar')?.style.backgroundImage || '', })); const openRow = (id) => page.evaluate((id) => document.querySelector('.notes-feed .note-post[data-zap-post="' + id + '"] > .note-content > .note-text').click(), id); @@ -100,7 +103,7 @@ try { await page.evaluate(([k, alice, bob, carol, notes]) => { localStorage.setItem(k + ':follows', JSON.stringify({ tags: [['p', alice], ['p', bob]], c: '', at: Math.floor(Date.now() / 1000) })); localStorage.setItem(k + ':feedNotes', JSON.stringify(notes)); - localStorage.setItem(k + ':profiles', JSON.stringify({ [alice]: { name: 'Alice Asker', t: Date.now() }, [bob]: { name: 'Bob Quiet', t: Date.now() }, [carol]: { name: 'Carol Quick', t: Date.now() } })); + localStorage.setItem(k + ':profiles', JSON.stringify({ [alice]: { name: 'Alice Asker', t: Date.now() }, [bob]: { name: 'Bob Quiet', picture: location.origin + '/bob.png', t: Date.now() }, [carol]: { name: 'Carol Quick', t: Date.now() } })); localStorage.setItem('btc-wallet-feed:' + k, 'following'); }, [base, ALICE, BOB, CAROL, [C1, B1, A1]]); await page.reload({ waitUntil: 'domcontentloaded' }); @@ -109,15 +112,16 @@ try { check('the feed paints the posts', await waitFor(() => document.querySelectorAll('.notes-feed .note-post[data-zap-post]').length >= 3, null, 20000)); console.log('\n[fetched ahead before the count answered]'); check('reading carol\'s post for a moment fetches its thread ahead', await waitFor((id) => window.__reqs.some((r) => r.fs.some((f) => (f['#e'] || []).includes(id) && f.limit)), C1.id, 15000)); + await page.evaluate(() => { window.__conn.saveData = true; }); // no more fetching ahead: the later parts want their threads untouched await sleep(300); await page.evaluate(() => window.__releaseC()); // now the count answer lands, after the thread entry was made check('…and the count answer brings its reply', await waitFor((id) => /\b1\b/.test(document.querySelector('.notes-feed .note-post[data-zap-post="' + id + '"]')?.innerText || ''), C1.id, 8000)); - await page.evaluate(() => { window.__conn.saveData = true; }); // no more fetching ahead: the next parts want threads untouched const t2 = Date.now(); await openRow(C1.id); let ahead = null; for (let i = 0; i < 40; i++) { const th = await thread(); if (th.rows.includes(U1.id)) { ahead = { ...th, ms: Date.now() - t2 }; break; } await sleep(25); } check('the thread opens with the reply from the count, not after its own 6 s ask', !!ahead && ahead.ms < 1500 && !ahead.spinner, ahead ? ahead.ms + ' ms' : 'never'); + check('…painted in its final shape: bob\'s face was fetched ahead, on the row at its first paint', !!ahead && /blob:|data:image/.test(ahead.face || ''), ahead ? String(ahead.face).slice(0, 60) : ''); await page.goBack(); await sleep(800); await waitFor(() => !!document.querySelector('.feed-chips'), null, 6000); @@ -140,11 +144,13 @@ try { console.log('\n[a post with nothing in hand]'); const t1 = Date.now(); await openRow(B1.id); - check('a spinner while nothing is there to read', await waitFor(() => !!document.querySelector('.thread-card .spinner'), null, 1500, 20)); - let streamed = null; - for (let i = 0; i < 80; i++) { const th = await thread(); if (th.rows.includes(S1.id)) { streamed = { ...th, ms: Date.now() - t1 }; break; } await sleep(25); } - check('the first reply shows as it arrives, the slow one still on its way', !!streamed && streamed.ms < 2000 && !streamed.rows.includes(S2.id), streamed ? streamed.ms + ' ms' : 'never'); - check('…the spinner gone once there is something to read', !!streamed && !streamed.spinner); + let opened = null; + for (let i = 0; i < 40; i++) { const th = await thread(); if (th.rows[0] === B1.id) { opened = { ...th, ms: Date.now() - t1 }; break; } await sleep(20); } + check('the post reads at once: no spinner, no "no replies" while they are on their way', !!opened && !opened.spinner && !/no replies/i.test(opened.text), opened ? opened.ms + ' ms' : 'never'); + let streamed = null, spun = false; + for (let i = 0; i < 80; i++) { const th = await thread(); spun ||= th.spinner; if (th.rows.includes(S1.id)) { streamed = { ...th, ms: Date.now() - t1 }; break; } await sleep(25); } + check('the first reply pops in as it arrives, the slow one still on its way', !!streamed && streamed.ms < 2500 && !streamed.rows.includes(S2.id), streamed ? streamed.ms + ' ms' : 'never'); + check('…never a spinner', !spun && !!streamed && !streamed.spinner); check('the slow one lands in its place', await waitFor((id) => { const rows = [...document.querySelectorAll('.thread-page [data-zap-post]')].map((r) => r.getAttribute('data-zap-post')); return rows.length === 3 && rows[2] === id && !document.querySelector('.thread-card .spinner'); }, S2.id, 6000)); check('no page errors', errs.length === 0, errs.slice(0, 2).join(' | ')); } catch (e) { console.error(e); ok = false; } finally { await browser.close(); server.stop(true); } |
