aboutsummaryrefslogtreecommitdiffstats
path: root/tools/feed-streaming-test.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-07 08:12:38 -0700
committerAdam Soltys <[email protected]>2026-10-07 08:12:38 -0700
commitfaad243486666eb4cbefcd7ff813329e707106dd (patch)
treece25612f6ed8fdd9355b08d7e07efb5c6b429c7f /tools/feed-streaming-test.js
parent78cf670939133fc4f656f0f42b21a59431a53842 (diff)
downloadcoinosv3-faad243486666eb4cbefcd7ff813329e707106dd.tar.gz
coinosv3-faad243486666eb4cbefcd7ff813329e707106dd.zip
Feed tests: catch up with Articles, Popular as the default feed, timed feed defs and the tint that fades on sight
- feed-media-views: the mode switch has an Articles button now - feed-media-cache: the live watch's since-only subscription isn't part of the crawl - feed-switch-seed: seeded feeds carry their edit time (the feeds sync merge drops one without) - feed-editor-relays: nos.lol is a local stand-in relay, so the test doesn't depend on reaching it - feed-streaming: the stub wallet opens on Following (no remembered feed = Popular); the held picture answers repeat fetches once released; the new-post tint is recorded as it paints (it fades on sight) Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'tools/feed-streaming-test.js')
-rw-r--r--tools/feed-streaming-test.js24
1 files changed, 19 insertions, 5 deletions
diff --git a/tools/feed-streaming-test.js b/tools/feed-streaming-test.js
index e662b42..3070771 100644
--- a/tools/feed-streaming-test.js
+++ b/tools/feed-streaming-test.js
@@ -51,6 +51,7 @@ const server = Bun.serve({ port: 0, fetch(req) {
if (path.startsWith('/punks')) return new Response(png, { headers: { 'Content-Type': 'image/png' } });
return new Response(html, { headers: { 'Content-Type': 'text/html' } });
} });
+const heldPng = { status: 200, contentType: 'image/png', body: png };
const browser = await puppeteer.launch({ executablePath: '/usr/bin/google-chrome', headless: true, args: ['--no-sandbox'] });
const errors = [];
try {
@@ -61,10 +62,23 @@ try {
await page.emulateMediaFeatures([{ name: 'prefers-reduced-motion', value: 'reduce' }]);
await page.setRequestInterception(true);
page.on('request', (r) => {
- if (r.url() === 'https://media.example/held.png') { page.heldImage = r; return; }
+ if (r.url() === 'https://media.example/held.png') {
+ // held until the test lets it go; once it has, asking again (the
+ // picture is read more than once on its way in) is answered at once
+ if (page.released) r.respond(heldPng); else page.heldImage = r;
+ return;
+ }
if (r.url().startsWith(server.url.origin) || r.url().startsWith('data:')) r.continue(); else r.abort();
});
await page.evaluateOnNewDocument(() => {
+ // the stub wallet's feed is Following (a wallet with none remembered opens on Popular)
+ try { localStorage.setItem('btc-wallet-feed:', 'following'); } catch {}
+ // rows that went on screen wearing the new-post tint (it fades the
+ // moment a row is seen, so the class alone can't be read afterwards)
+ window.freshSeen = new Set();
+ new MutationObserver((ms) => { for (const m of ms) for (const n of m.type === 'attributes' ? [m.target] : m.addedNodes)
+ if (n.classList?.contains('note-fresh')) window.freshSeen.add(n.getAttribute('data-key')); })
+ .observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] });
const sockets = [];
window.feedClosed = 0;
class FakeSocket extends EventTarget {
@@ -125,7 +139,7 @@ try {
assert.equal(await count(page), 2, 'out-of-order posts count and duplicates do not');
assert(Math.abs(await page.$eval(row(reading), (r) => r.getBoundingClientRect().top) - held) <= 1, 'streaming preserves reading position');
assert(page.heldImage, 'slow media is being prepared');
- await page.heldImage.respond({ status: 200, contentType: 'image/png', body: png });
+ page.released = true; await page.heldImage.respond(heldPng);
await page.waitForSelector(row(slow.id), { timeout: 2000 });
assert.equal(await count(page), 3);
assert(await page.$eval(row(slow.id), (r) => { const img = r.querySelector('.note-img'); return img?.complete && img.naturalWidth > 0; }), 'photo is decoded when admitted');
@@ -173,9 +187,9 @@ try {
assert(await page.evaluate(() => !window.bootDone), 'new-post notice does not wait for cached media');
await page.click('.feed-new-pill');
await page.waitForSelector(row(fast.id));
- assert(await page.$eval(row(fast.id), (r) => r.classList.contains('note-fresh')), 'prepared new rows keep their stable presentation during cache warm-up');
+ assert(await page.evaluate((id) => window.freshSeen.has(id), fast.id), 'prepared new rows keep their stable presentation during cache warm-up');
assert(page.heldImage);
- await page.heldImage.respond({ status: 200, contentType: 'image/png', body: png });
+ page.released = true; await page.heldImage.respond(heldPng);
await page.waitForFunction(() => window.bootDone);
await page.evaluate(() => window.endQueries());
await page.waitForFunction(() => window.refreshDone);
@@ -192,7 +206,7 @@ try {
await page.click('.feed-new-pill');
await page.waitForSelector(row(fast.id));
assert(page.heldImage);
- await page.heldImage.respond({ status: 200, contentType: 'image/png', body: png });
+ page.released = true; await page.heldImage.respond(heldPng);
await page.waitForFunction(() => window.batchDone);
await page.evaluate(() => window.endQueries());
await page.waitForFunction(() => window.refreshDone);