__tests__/postwatch-threads.test.js
Rama main · réplica de lectura del repositorio original.
/**
* Threads the owner STARTED on someone else's post get the post-watcher treatment: only branches the
* owner is in count, a reply to the owner waits on them, other people's root comments are not the
* owner's business there, and the items say whose post it is. Pure: in-memory feed, no browser.
*/
import { describe, it, expect } from 'vitest';
import { ingest, cleanName } from '../src/postWatch.js';
function fakeFeed() {
const items = {};
return {
items,
upsert(wid, item) { const k = item.url; if (!items[k]) items[k] = { key: k, handled: false, fields: {}, ...item }; return { item: items[k], isNew: true }; },
mark(wid, key, patch) { Object.assign(items[key], patch); return true; },
list() { return Object.values(items); },
};
}
const N = (i, author, text, o = {}) => { const r = o.root !== undefined; return { i, id: String(o.id !== undefined ? o.id : i), cid: r ? String(o.root) : String(i), rid: r ? String(i) : null, isReply: r, author, replyTo: o.to || '', reactedByMe: !!o.reacted, text, when: '1 u', parentId: r ? String(o.root) : null }; };
const theirPost = (nodes) => ({ postId: 'Q', group: 'g', postText: 'Ilya: my auth stack is entra + supabase', postAuthor: 'Ilya Elbert', me: '', nodes });
const cfg = { meName: 'Wesley Stoep' };
const item = (feed, author, text) => Object.values(feed.items).find((it) => it.fields.author === author && it.fields.said === text);
describe("threads the owner started on other people's posts", () => {
it('a reply to the owner\'s comment waits on the owner; the post author\'s and a stranger\'s alike', () => {
const feed = fakeFeed();
const out = ingest('w', theirPost([
N(0, 'Wesley Stoep', 'super clean stack'),
N(1, 'Ilya Elbert', 'i was so angry at entra lol', { root: 0, to: 'Wesley Stoep' }),
N(2, 'Dennis', 'same here, 7 keys per app', { root: 0, to: 'Wesley Stoep' }),
]), cfg, feed);
expect(item(feed, 'Ilya Elbert', 'i was so angry at entra lol').fields.status).toBe('waiting on you');
expect(item(feed, 'Dennis', 'same here, 7 keys per app').fields.status).toBe('waiting on you');
expect(out.filter((e) => e.needsReply).map((e) => e.node.author)).toEqual(['Ilya Elbert', 'Dennis']);
const it_ = item(feed, 'Ilya Elbert', 'i was so angry at entra lol');
expect(it_.title).toBe("Ilya Elbert replied to you on Ilya Elbert's post");
expect(it_.fields.theirs).toBe(true); expect(it_.fields.postAuthor).toBe('Ilya Elbert'); expect(it_.fields.postTitle).toMatch(/^Ilya Elbert: /);
});
it('root comments by other people on their post are not the owner\'s; branches without the owner are left out entirely', () => {
const feed = fakeFeed();
ingest('w', theirPost([
N(0, 'Wesley Stoep', 'super clean stack'),
N(1, 'Peter', 'nice post Ilya'),
N(2, 'Ilya Elbert', 'thanks Peter', { root: 1, to: 'Peter' }),
N(3, 'Ilya Elbert', 'glad you like it Wesley', { root: 0, to: 'Wesley Stoep' }),
]), cfg, feed);
expect(item(feed, 'Peter', 'nice post Ilya')).toBeUndefined();
expect(item(feed, 'Ilya Elbert', 'thanks Peter')).toBeUndefined();
expect(item(feed, 'Ilya Elbert', 'glad you like it Wesley').fields.status).toBe('waiting on you');
});
it('answered once the owner replies back to that person; the owner\'s own comment is never waiting', () => {
const feed = fakeFeed();
ingest('w', theirPost([
N(0, 'Wesley Stoep', 'super clean stack'),
N(1, 'Ilya Elbert', 'i was so angry at entra lol', { root: 0, to: 'Wesley Stoep' }),
N(2, 'Wesley Stoep', 'haha the policy maze is unreal', { root: 0, to: 'Ilya Elbert' }),
]), cfg, feed);
expect(item(feed, 'Ilya Elbert', 'i was so angry at entra lol').fields.status).toBe('answered');
expect(item(feed, 'Wesley Stoep', 'super clean stack').fields.status).toBe('you');
expect(item(feed, 'Wesley Stoep', 'super clean stack').handled).toBe(true);
});
it('when the page gives no post author, the discovery\'s list of "their" posts still marks the thread as theirs', () => {
const feed = fakeFeed();
ingest('w', { postId: 'R', group: 'g', postText: 'Day 9 of vibe coding a game', postAuthor: '', me: '', nodes: [
N(0, 'Wesley Stoep', 'Looks good, is there a reason for 2d'),
N(1, 'Henry Chien', 'save cost lol', { root: 0, to: 'Wesley Stoep' }),
N(2, 'Someone', 'nice game'),
] }, { meName: 'Wesley Stoep', theirsIds: ['R'] }, feed);
const it_ = item(feed, 'Henry Chien', 'save cost lol');
expect(it_.fields.status).toBe('waiting on you'); expect(it_.fields.theirs).toBe(true); expect(it_.title).toBe('Henry Chien replied to you on their post');
expect(it_.fields.postTitle).toBe('Day 9 of vibe coding a game');
expect(item(feed, 'Someone', 'nice game')).toBeUndefined(); // not the owner's business on their post
});
it('a "your post" row wins over a "your comment" row: the owner\'s own post is never theirs', () => {
const feed = fakeFeed();
ingest('w', { postId: 'P', group: 'g', postText: 'my post', postAuthor: '', me: '', nodes: [N(0, 'Adam', 'nice'), N(1, 'Wesley Stoep', 'thanks', { root: 0, to: 'Adam' })] }, { meName: 'Wesley Stoep', theirsIds: ['P'], mineIds: ['P'] }, feed);
expect(item(feed, 'Adam', 'nice').fields.status).toBe('answered'); expect(item(feed, 'Adam', 'nice').fields.theirs).toBe(false);
});
it('with no author and no discovery, an owner who wrote a ROOT comment there is a guest; names lose their time suffix', () => {
expect(cleanName('Wesley Stoep 2 weken geleden')).toBe('Wesley Stoep'); expect(cleanName('Eric Sijbesma about an hour ago')).toBe('Eric Sijbesma'); expect(cleanName('Jarne Staal')).toBe('Jarne Staal'); expect(cleanName('Ilya Elbert 3 h')).toBe('Ilya Elbert');
const feed = fakeFeed();
// a stale item from a pass that took the post for the owner's: a stranger's root comment, waiting
feed.upsert('w', { url: 'https://fb/old', title: 'Sander commented on your post', fields: { postId: 'D', author: 'Sander Rombout', said: 'ik snap het', status: 'waiting on you' } });
ingest('w', { postId: 'D', group: 'g', postText: 'Trap niet in de verkoop praatjes', postAuthor: '', me: '', nodes: [
N(0, 'Wesley Stoep 2 weken geleden', 'goed punt'),
N(1, 'Eric Sijbesma 2 weken geleden', 'eens!', { root: 0, to: 'Wesley Stoep 2 weken geleden' }),
N(2, 'Sander Rombout', 'ik snap het'),
] }, { meName: 'Wesley Stoep' }, feed);
expect(item(feed, 'Eric Sijbesma', 'eens!').fields.status).toBe('waiting on you'); expect(item(feed, 'Eric Sijbesma', 'eens!').fields.theirs).toBe(true);
expect(item(feed, 'Wesley Stoep', 'goed punt').fields.status).toBe('you');
// Sander's root comment is not produced again — only the stale item remains, and it is folded away
expect(Object.values(feed.items).filter((it) => it.fields.author === 'Sander Rombout').map((it) => it.key)).toEqual(['https://fb/old']);
const stale = feed.items['https://fb/old']; expect(stale.handled).toBe(true); expect(stale.fields.status).toBe('side conversation');
});
it('the owner\'s own post still works as before (root comments wait)', () => {
const feed = fakeFeed();
ingest('w', { postId: 'P', group: 'g', postText: 'my post', postAuthor: 'Wesley Stoep', me: '', nodes: [N(0, 'Adam', 'nice')] }, cfg, feed);
expect(item(feed, 'Adam', 'nice').fields.status).toBe('waiting on you'); expect(item(feed, 'Adam', 'nice').fields.theirs).toBe(false);
});
});