aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/profile-stream-test.js58
1 files changed, 58 insertions, 0 deletions
diff --git a/tools/profile-stream-test.js b/tools/profile-stream-test.js
new file mode 100644
index 0000000..8d15775
--- /dev/null
+++ b/tools/profile-stream-test.js
@@ -0,0 +1,58 @@
+// A profile visited for the first time, from search: its posts used to land
+// all at once after several seconds of blank (the slowest relay, then every
+// post's media). Now the page shows post-shaped placeholders while it waits,
+// the first posts paint as the quick relays answer, and the top search
+// results are fetched before they're tapped. Reads real relays
+// (relays: 'read'; nothing is published).
+// Run: bun tools/profile-stream-test.js (Q="ben arc" to search someone else)
+import puppeteer from './puppeteer.js';
+import { buildHtml } from '../build.js';
+const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
+let ok = true;
+const check = (n, c, d = '') => { console.log(` ${c ? '✓' : '✗'} ${n}${d ? ' — ' + d : ''}`); if (!c) ok = false; };
+const Q = process.env.Q || 'fiatjaf';
+
+const html = await buildHtml({ minify: true, pwa: false });
+const server = Bun.serve({ port: 0, fetch: () => new Response(html, { headers: { 'content-type': 'text/html' } }) });
+const browser = await puppeteer.launch({ relays: 'read', executablePath: '/usr/bin/google-chrome', headless: 'new', args: ['--no-sandbox'] });
+const page = await browser.newPage();
+const errs = [];
+page.on('pageerror', (e) => errs.push(String(e)));
+try {
+ await page.setViewport({ width: 390, height: 844 });
+ if (process.env.DARK) await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]);
+ await page.goto(server.url.href + 'feed', { waitUntil: 'domcontentloaded' });
+ await sleep(1500);
+ await page.evaluate(() => [...document.querySelectorAll('button')].find((b) => b.getAttribute('aria-label') === 'Search')?.click());
+ await page.waitForSelector('.user-search-main', { timeout: 10000 });
+ await page.type('.user-search-main', Q, { delay: 60 });
+ // the result rows: people (not the "posts that say this" or #topic rows)
+ const rows = () => page.evaluate(() => [...document.querySelectorAll('.list .item')].filter((r) => !/^[\u{1F50D}#]/u.test(r.textContent.trim())).map((r) => r.textContent.trim().slice(0, 40)));
+ let found = [];
+ for (let i = 0; i < 60 && !found.length; i++) { found = await rows(); if (!found.length) await sleep(250); }
+ if (!found.length) console.log(await page.evaluate(() => document.querySelector('.user-search-main')?.closest('.col')?.parentElement?.innerHTML.slice(0, 1500)));
+ check('search finds people', found.length > 0, found.slice(0, 2).join(' | '));
+ const wait = Number(process.env.WAIT || 0); // ms between results and the tap (prefetch's head start)
+ if (wait) await sleep(wait);
+ const t0 = Date.now();
+ await page.evaluate(() => [...document.querySelectorAll('.list .item')].filter((r) => !/^[\u{1F50D}#]/u.test(r.textContent.trim()))[0].click());
+ let ghostAt = 0, firstAt = 0, rowsAt3 = 0;
+ for (let i = 0; i < 200; i++) {
+ const s = await page.evaluate(() => ({
+ ghost: !!document.querySelector('.note-ghosts'),
+ rows: document.querySelectorAll('.notes-feed:not(.note-ghosts) > [data-key]').length,
+ }));
+ const t = Date.now() - t0;
+ if (s.ghost && !ghostAt) { ghostAt = t; if (process.env.SHOT) await page.screenshot({ path: process.env.SHOT }); }
+ if (s.rows && !firstAt) firstAt = t;
+ if (t >= 3000 && !rowsAt3) rowsAt3 = s.rows || -1;
+ if (firstAt && t >= 3000) break;
+ await sleep(50);
+ }
+ console.log(` placeholder ${ghostAt ? ghostAt + ' ms' : 'not seen'}, first post ${firstAt || '—'} ms, rows at 3 s ${rowsAt3}`);
+ check('posts arrive', firstAt > 0);
+ check('...while waiting, the page says posts are loading', !!ghostAt || firstAt < 300, ghostAt ? 'placeholder shown' : 'posts were already in hand');
+ check('no page errors', !errs.length, errs.join(' | '));
+} catch (e) { console.error(e); ok = false; } finally { await browser.close(); server.stop(); }
+console.log(ok ? '\nPASS' : '\nFAIL');
+process.exit(ok ? 0 : 1);