aboutsummaryrefslogtreecommitdiffstats
path: root/tools/feed-live-test.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-07 08:34:45 -0700
committerAdam Soltys <[email protected]>2026-10-07 08:34:45 -0700
commit8dfc629d129c6c1a8a3ed38a935e659eee9f67c7 (patch)
treee85c955e7014e1cf4b22166077d41e3d5c2bc4bd /tools/feed-live-test.js
parent1d6786265f4d86b2260b30060df473a51774fb72 (diff)
downloadcoinosv3-8dfc629d129c6c1a8a3ed38a935e659eee9f67c7.tar.gz
coinosv3-8dfc629d129c6c1a8a3ed38a935e659eee9f67c7.zip
Feed tests: open the Feed from the bottom nav, on Following
The feed left the chat home for a bottom-nav tab, and a wallet with no feed remembered opens on Popular, so these tests click the Feed tab and seed Following as the wallet's last feed. Also brought up to date: - feed-live: the pill lands on the oldest new post; arrivals at the top go in above the first post (held still), not behind the pill; scroll up a screen at a time (one jump lands before the windowed rows are back) - feed-custom: only the feeds' chips are counted (not All/Images/…); the follows box is not the first checkbox any more; the last feed is remembered across a reload; the pack shows in the feed's editor (the chat home no longer lists the feed) - feed-follow: Feed tab + Following chip instead of the messages-home row; the feed opens at ten posts (tall ones, so a page doesn't fill the screen) - moderation: nos.lol is a local stand-in (a relay that won't connect held the mute list back past the checks) Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'tools/feed-live-test.js')
-rw-r--r--tools/feed-live-test.js37
1 files changed, 22 insertions, 15 deletions
diff --git a/tools/feed-live-test.js b/tools/feed-live-test.js
index 9f98fde..8f80d46 100644
--- a/tools/feed-live-test.js
+++ b/tools/feed-live-test.js
@@ -105,12 +105,12 @@ try {
localStorage.setItem(k + ':follows', JSON.stringify({ tags: [['p', pk]], c: '', at: Math.floor(Date.now() / 1000) }));
localStorage.setItem(k + ':feedNotes', JSON.stringify(ns));
localStorage.setItem(k + ':profiles', JSON.stringify({ [pk]: { name: 'Test Author', t: Date.now() } }));
+ localStorage.setItem('btc-wallet-feed:' + k, 'following'); // a new wallet would open on Popular
}, [base, AUTHOR, seeded]);
await page.reload({ waitUntil: 'domcontentloaded' });
await waitText('receive', 20000);
- await page.evaluate(() => { const b = [...document.querySelectorAll('button')].find((e) => /message/i.test(e.getAttribute('aria-label') || '')); if (b) b.click(); });
- await sleep(1000);
- await page.evaluate(() => { const e = [...document.querySelectorAll('.item')].find((n) => /feed/i.test(n.textContent)); if (e) e.click(); });
+ // the Feed is a tab in the bottom nav (it was a row on the chat home)
+ await page.evaluate(() => [...document.querySelectorAll('.app-nav-button')].find((b) => b.getAttribute('aria-label') === 'Feed')?.click());
await sleep(4000);
check('the feed has posts in it', (await page.evaluate(() => document.querySelectorAll('.notes-feed > .row').length)) > 0);
@@ -144,8 +144,12 @@ try {
await page.evaluate(() => document.querySelector('.feed-new-pill').click());
await sleep(600);
- const opened = await page.evaluate(() => ({ y: Math.round(window.scrollY), pill: !!document.querySelector('.feed-new-pill') }));
- check('tapping it takes you up to the post', opened.y < 120, 'scrollY ' + opened.y);
+ // the pill lands on the (oldest) new post, at the top of the screen
+ const opened = await page.evaluate(() => {
+ const r = [...document.querySelectorAll('.notes-feed > .row')].find((n) => /BRAND NEW POST/.test(n.innerText));
+ return { top: r ? Math.round(r.getBoundingClientRect().top) : null, pill: !!document.querySelector('.feed-new-pill') };
+ });
+ check('tapping it takes you up to the post', opened.top !== null && opened.top >= 0 && opened.top < 120, 'post top ' + opened.top);
check('...and the pill is done', !opened.pill);
console.log('\n[scrolling back up on your own]');
@@ -238,6 +242,12 @@ try {
const r = [...document.querySelectorAll('.notes-feed > .row')].find((n) => eval(label)(n) === text);
return r ? { text, top: Math.round(r.getBoundingClientRect().top), y: Math.round(window.scrollY) } : null;
}, label.toString(), text);
+ // up to the top the way a reader goes, a screen at a time (one jump from
+ // far down lands before the rows up there are mounted again)
+ const scrollUp = async () => {
+ while (await page.evaluate(() => { scrollBy(0, -Math.min(scrollY, innerHeight)); return scrollY > 0; })) await sleep(80);
+ await sleep(600);
+ };
const topRow = () => page.evaluate(() => (document.querySelector('.notes-feed > .row') || {}).innerText || '');
console.log('\n[coming back after being away, a few new posts]');
@@ -260,23 +270,20 @@ try {
await page.evaluate(() => window.scrollTo(0, document.documentElement.scrollHeight));
await sleep(600);
check('...older posts that merely missed the cache went in quietly too', /not in the cache/.test(await feedText()));
- await page.evaluate(() => window.scrollTo(0, 0));
- await sleep(600);
+ await scrollUp();
check('...scrolling up reaches the newest post, and clears the pill', /CATCH-UP 1/.test(await topRow()) && !(await page.$('.feed-new-pill')), (await topRow()).slice(0, 40));
console.log('\n[coming back while sitting at the top]');
const wasTop = await anchor();
await away(() => [signed('AT-THE-TOP A', 0), signed('AT-THE-TOP B', 1)]);
const a2 = await rowAt(wasTop.text);
- check('the header and first post stay in place', !!wasTop && !!a2 && a2.text === wasTop.text && Math.abs(a2.top - wasTop.top) <= 2 && a2.y === wasTop.y,
+ // new posts go in above the first post, which is held where it was (the
+ // page grows upward, scrolled by what went in above it)
+ check('the first post stays in place', !!wasTop && !!a2 && a2.text === wasTop.text && Math.abs(a2.top - wasTop.top) <= 2,
JSON.stringify({ was: wasTop, now: a2 }));
- check('...new posts wait while the header is visible', !/AT-THE-TOP A/.test(await topRow()));
- await page.evaluate(() => {
- const first = document.querySelector('.notes-feed > .row');
- scrollBy(0, Math.ceil(first.getBoundingClientRect().top));
- });
- await sleep(600);
- check('...then arrive offscreen above it, with a notice', /AT-THE-TOP A/.test(await topRow()) && /2 new posts/i.test(await page.evaluate(() => document.querySelector('.feed-new-pill')?.textContent || '')));
+ const atTop = await rowAt('AT-THE-TOP A');
+ check('...the new posts went in above it', /AT-THE-TOP A/.test(await topRow()) && !!atTop && !!a2 && atTop.top < a2.top, JSON.stringify(atTop));
+ check('...with a notice', /2 new posts/i.test(await page.evaluate(() => document.querySelector('.feed-new-pill')?.textContent || '')));
console.log('\n[coming back after a long time away]');
await page.evaluate(() => window.scrollTo(0, 900));