diff options
| author | Adam Soltys <[email protected]> | 2026-10-20 12:24:35 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-20 12:24:35 -0700 |
| commit | d0752d70b54e9d58bba5e11aea06c9ba1678e89b (patch) | |
| tree | af890d6fd9da9cb78b94a4013607ffee7cefe58f /tools | |
| parent | 1e0d551daae8d09f86dbf54ab67bf52610c0c9ac (diff) | |
| download | coinosv3-d0752d70b54e9d58bba5e11aea06c9ba1678e89b.tar.gz coinosv3-d0752d70b54e9d58bba5e11aea06c9ba1678e89b.zip | |
A reply under "Couldn't find that note on the relays" told nobody anything (Adam, 2026-10-20), so once every lookup comes back without its post it isn't shown in a feed's Conversations view (its thread, notifications and the replier's own Replies tab keep it; a lookup that later finds the post brings it back).
The lookups miss less:
- A NIP-22 comment (kind 1111) names its parent's author at e-tag [3], not NIP-10's [4], so every comment's parent lost its author and the author's outbox went unasked. fiatjaf's comment on Kieran's routstr post lives on relay.snort.social (its hint), Kieran's pyramid.fiatjaf.com and ditto: none of ours.
- A reply that names no author asks the outboxes of the people it's addressed to (its p tags, up to three).
- The relay the reference itself names is asked even when this device has marked it sick.
- A post read in Following (or the feed in use) is found in that feed's disk cache too, so a Conversations view opened right after a reload doesn't take its replies for orphans.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013ZDf1cyCQLkfjftYhymZAg
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/feed-conversations-test.js | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/tools/feed-conversations-test.js b/tools/feed-conversations-test.js index e762d1a..f16fc35 100644 --- a/tools/feed-conversations-test.js +++ b/tools/feed-conversations-test.js @@ -67,7 +67,7 @@ try { const following = await rowIds(); check('…only posts: no replies in Following', following.includes(A1.id) && following.includes(B1.id) && !following.includes(R1.id) && !following.includes(R2.id), following.map((x) => x.slice(0, 6)).join(',')); const modes = () => page.$$eval('.media-mode', (l) => l.map((e) => e.getAttribute('data-mode') + '=' + e.textContent.trim() + (e.classList.contains('on') ? '*' : '')).join(' ')); - check('Notes and Conversations lead the view chips', await modes() === 'all=Notes* replies=Conversations images=Images videos=Videos articles=Articles', await modes()); + check('Notes and Conversations lead the view chips', await modes() === 'all=Notes* replies=Conversations images=Images videos=Videos live=Live articles=Articles', await modes()); check('no Conversations feed chip of its own', !(await page.$$eval('.feed-chips > .feed-chip', (l) => l.some((e) => /Conversations/.test(e.textContent))))); console.log('\n[Conversations]'); @@ -79,7 +79,8 @@ try { const c1 = await contextOf(R1.id); check('a reply sits under the post it answers (in hand from Following, no relay asked)', !!c1 && c1.of === B1.id && c1.card && /Replying to/.test(c1.text) && /Bob Asker/.test(c1.text) && /bob root here/.test(c1.text), JSON.stringify(c1)); check('…and the header no longer repeats "reply"', !(await page.$eval('.notes-feed .note-post[data-zap-post="' + R1.id + '"] .note-header', (e) => /\breply\b/i.test(e.innerText)))); - check('a parent nobody has: the card says so', await waitFor((id) => { const c = document.querySelector('.note-post[data-zap-post="' + id + '"] .note-context'); return !!c && /find that note/i.test(c.innerText); }, R2.id, 8000), (await contextOf(R2.id) || {}).text); + // (a "Couldn't find that note" card over it told nobody anything: Adam, 2026-10-20) + check('a parent nobody has: the reply leaves the feed once every lookup comes back without it', await waitFor((ids) => !document.querySelector('.note-post[data-zap-post="' + ids[0] + '"]') && !!document.querySelector('.note-post[data-zap-post="' + ids[1] + '"]'), [R2.id, R1.id], 12000), (await rowIds()).map((x) => x.slice(0, 6)).join(',')); // the reply's own tap (its text, not the card above it): its thread, at the reply await page.evaluate((id) => document.querySelector('.note-post[data-zap-post="' + id + '"] > .note-content > .note-text').click(), R1.id); check('tapping the reply opens the thread at the reply', await waitFor((id) => !!document.querySelector('[data-focus-note="1"][data-zap-post="' + id + '"]'), R1.id, 8000)); @@ -114,7 +115,7 @@ try { }); await click('save'); await sleep(600); check('saved as a chip', await waitFor(() => [...document.querySelectorAll('.feed-chip')].some((e) => e.textContent.trim() === 'Alice talks' && e.classList.contains('on')), null, 6000)); - check('…opened in the Conversations view, the replies borrowed from the feeds in hand', /replies=Conversations\*/.test(await modes()) && await waitFor((ids) => { const got = [...document.querySelectorAll('.notes-feed .note-post[data-zap-post]')].map((r) => r.getAttribute('data-zap-post')); return got.length === 2 && got.includes(ids[0]) && got.includes(ids[1]); }, [R1.id, R2.id], 8000), (await rowIds()).map((x) => x.slice(0, 6)).join(',')); + check('…opened in the Conversations view, the replies borrowed from the feeds in hand', /replies=Conversations\*/.test(await modes()) && await waitFor((ids) => { const got = [...document.querySelectorAll('.notes-feed .note-post[data-zap-post]')].map((r) => r.getAttribute('data-zap-post')); return got.length === 1 && got.includes(ids[0]) && !got.includes(ids[1]); }, [R1.id, R2.id], 8000), (await rowIds()).map((x) => x.slice(0, 6)).join(',')); check('…each with its context', (await contextOf(R1.id) || {}).of === B1.id); await page.evaluate(() => document.querySelector('.media-mode[data-mode="all"]').click()); check('Notes: the same feed\'s posts', await waitFor((ids) => { const got = [...document.querySelectorAll('.notes-feed .note-post[data-zap-post]')].map((r) => r.getAttribute('data-zap-post')); return got.length === 2 && got.includes(ids[0]) && got.includes(ids[1]); }, [A1.id, B1.id], 8000), (await rowIds()).map((x) => x.slice(0, 6)).join(',')); @@ -122,7 +123,7 @@ try { await page.evaluate(() => document.querySelector('.feed-chip[data-key="chip:following"]').click()); check('Following in Notes is posts only', await waitFor((ids) => { const got = [...document.querySelectorAll('.notes-feed .note-post[data-zap-post]')].map((r) => r.getAttribute('data-zap-post')); return got.includes(ids[0]) && !got.includes(ids[1]); }, [A1.id, R1.id], 8000)); await page.evaluate(() => document.querySelector('.media-mode[data-mode="replies"]').click()); - check('…and its Conversations view is back at once', await waitFor((ids) => { const got = [...document.querySelectorAll('.notes-feed .note-post[data-zap-post]')].map((r) => r.getAttribute('data-zap-post')); return got.length === 2 && got[0] === ids[0]; }, [R2.id], 8000)); + check('…and its Conversations view is back at once', await waitFor((ids) => { const got = [...document.querySelectorAll('.notes-feed .note-post[data-zap-post]')].map((r) => r.getAttribute('data-zap-post')); return got.length === 1 && got[0] === ids[0]; }, [R1.id], 8000)); await page.reload({ waitUntil: 'domcontentloaded' }); await waitText('receive', 20000); await page.evaluate(() => document.querySelector('.app-nav-button[aria-label="Feed"]').click()); |
