source: Klonkt/test/own-card.test.js@ d1075a1

main
Last change on this file since d1075a1 was d1075a1, checked in by Robin <roboburr@…>, 4 weeks ago

Eerst bakken, dan linken zoeken -- en de verloren kolomselectie terug

Twee vondsten van het toestel (shaer-k3f, vervolg op 4838760):

EERST BAKKEN. firstExternalUrl leest <a href>-ankers, en de web-editor
bakt die er bij het opslaan al in -- maar een post uit de APP is platte
tekst waarin de URL nog geen anker is. Het C2S-pad zag dus nooit een
link en een app-post kreeg nooit een kaart, terwijl de preview hem net
wel beloofd had. deliverCreate bakt de inhoud nu voor het zoeken; de
test dekt voortaan het app-geval (platte tekst) in plaats van het
editor-geval.

DE VERLOREN SELECTIE. De kolomtoevoeging aan de outbox-query is bij het
invlechten van parallel werk verloren gegaan: de friend-poot vroeg
row.embed_json aan rijen waar de query hem nooit in had gestopt. Een
diagnoseregel op dev wees het exact aan (rij gevonden, poort open,
embed: false). De query draagt quote_json en embed_json nu echt, en de
route is weer schoon.

Op het toestel bewezen: preview in de composer, posten, en de eigen
feedkaart draagt de kaart. Alle 723 groen.

Co-Authored-By: Claude Opus 5 <noreply@…>

  • Property mode set to 100644
File size: 4.6 KB
Line 
1// De kaart op je EIGEN post (shaer-k3f): een URL in wat je publiceert wordt
2// een quote- of embed-snapshot, langs dezelfde pijplijn als een binnenkomende
3// post -- en de composer-preview loopt door diezelfde pijplijn, zodat de
4// preview nooit iets belooft dat de post niet waarmaakt.
5//
6// In-memory SQLite, gestubde fetch op TEST-NET-3. Run: npm test
7import { test } from 'node:test';
8import assert from 'node:assert/strict';
9
10process.env.DATABASE_PATH = ':memory:';
11process.env.PUBLIC_BASE_URL = 'https://klonkt.test';
12
13const dbMod = await import('../src/config/database.js');
14const db = dbMod.default;
15dbMod.initializeDatabase();
16const AP = await import('../src/services/ActivityPubService.js');
17
18db.prepare('INSERT INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)')
19 .run('u1', 'u1', 'u1@test', 'x', 'god');
20db.prepare('INSERT INTO sites (id, slug, title, owner_id) VALUES (?,?,?,?)').run('s1', 'schrijver', 'Schrijver', 'u1');
21const site = db.prepare('SELECT * FROM sites WHERE id = ?').get('s1');
22
23const EXTERN = 'https://203.0.113.60/artikel';
24const APNOTE = 'https://203.0.113.61/notes/toot-1';
25const APAUTEUR = 'https://203.0.113.61/users/schrijfster';
26
27const OG_PAGINA = `<!doctype html><html><head>
28 <meta property="og:title" content="Een mooi artikel">
29 <meta property="og:image" content="https://203.0.113.60/plaatje.jpg">
30</head><body>tekst</body></html>`;
31
32globalThis.fetch = async (url, opts = {}) => {
33 const u = String(url);
34 const accepts = String((opts.headers && (opts.headers.Accept || opts.headers.accept)) || '');
35 const json = (o) => new Response(JSON.stringify(o), { status: 200, headers: { 'content-type': 'application/activity+json' } });
36 const html = (h) => new Response(h, { status: 200, headers: { 'content-type': 'text/html' } });
37 if (u === EXTERN) return html(OG_PAGINA); // geen AP, wel OpenGraph
38 if (u === APNOTE) {
39 // Een echte fediverse-note: op de AP-vraag AP-json, anders een kale pagina.
40 if (accepts.includes('activity+json')) return json({ id: APNOTE, type: 'Note', attributedTo: APAUTEUR, content: '<p>de toot</p>', published: '2026-08-01T10:00:00Z' });
41 return html('<html><body>toot</body></html>');
42 }
43 if (u === APAUTEUR) return json({ id: APAUTEUR, type: 'Person', preferredUsername: 'schrijfster', name: 'Schrijfster', inbox: `${APAUTEUR}/inbox` });
44 return new Response('not found', { status: 404 });
45};
46
47test('een externe link in een eigen post wordt een embed-snapshot op de post', async () => {
48 // PLATTE tekst, geen anker: zo komt een post uit de app binnen (het
49 // C2S-pad bakt niet voor het opslaan). Op het toestel bleef precies dit
50 // geval een kale link terwijl de web-editor wel een kaart kreeg.
51 db.prepare("INSERT INTO posts (id, site_id, author_id, slug, title, content, status) VALUES ('p1','s1','u1','p1','', ?, 'published')")
52 .run(`<p>Kijk: ${EXTERN}</p>`);
53 const post = db.prepare("SELECT * FROM posts WHERE id = 'p1'").get();
54 await AP.deliverCreate(site, post);
55 const rij = db.prepare("SELECT quote_json, embed_json FROM posts WHERE id = 'p1'").get();
56 assert.ok(rij.embed_json, 'embed-snapshot opgeslagen');
57 const kaart = JSON.parse(rij.embed_json);
58 assert.equal(kaart.title, 'Een mooi artikel');
59 assert.ok(!rij.quote_json, 'geen quote: het is geen fediverse-object');
60});
61
62test('een fediverse-link wordt een quote-snapshot, geen embed', async () => {
63 db.prepare("INSERT INTO posts (id, site_id, author_id, slug, title, content, status) VALUES ('p2','s1','u1','p2','', ?, 'published')")
64 .run(`<p>Dit! <a href="${APNOTE}">${APNOTE}</a></p>`);
65 const post = db.prepare("SELECT * FROM posts WHERE id = 'p2'").get();
66 await AP.deliverCreate(site, post);
67 const rij = db.prepare("SELECT quote_uri, quote_json, embed_json FROM posts WHERE id = 'p2'").get();
68 assert.equal(rij.quote_uri, APNOTE);
69 assert.ok(rij.quote_json, 'quote-snapshot opgeslagen');
70 const kaart = JSON.parse(rij.quote_json);
71 assert.ok(kaart.content.includes('de toot'));
72 assert.equal(kaart.author.name, 'Schrijfster');
73 assert.ok(!rij.embed_json, 'geen embed naast de quote');
74});
75
76test('previewCard geeft voor dezelfde twee links dezelfde twee kaarten', async () => {
77 const extern = await AP.previewCard(EXTERN);
78 assert.ok(extern.embedJson, 'externe link -> embed');
79 assert.equal(JSON.parse(extern.embedJson).title, 'Een mooi artikel');
80 assert.ok(!extern.quoteJson);
81
82 const ap = await AP.previewCard(APNOTE);
83 assert.ok(ap.quoteJson, 'fediverse-link -> quote');
84 assert.equal(JSON.parse(ap.quoteJson).author.handle, '@schrijfster@203.0.113.61');
85 assert.ok(!ap.embedJson);
86
87 // Rommel is geen kaart en geen fout.
88 assert.deepEqual(await AP.previewCard('geen url'), {});
89});
Note: See TracBrowser for help on using the repository browser.