// Een C2S-post kon nooit een titel hebben (shaer-uply): c2sCreatePost schreef // '' in posts.title en in posts_fts en las `name` op het binnenkomende object // nooit. Een client die er een zette zag hem geruisloos verdwijnen -- de API // was daarmee de enige publicatieweg die iets niet kon wat het web wel kan. // Gevonden door R9999, dat alleen over C2S publiceert. import { test } from 'node:test'; import assert from 'node:assert/strict'; process.env.DATABASE_PATH = ':memory:'; process.env.PUBLIC_BASE_URL = 'https://test.example'; const dbMod = await import('../src/config/database.js'); const db = dbMod.default; dbMod.initializeDatabase(); const AP = (await import('../src/services/ActivityPubService.js')).default; db.prepare('INSERT INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)') .run('u1', 'robin', 'u1@t', 'x', 'god'); db.prepare('INSERT INTO sites (id, slug, title, owner_id, is_primary) VALUES (?,?,?,?,1)').run('s1', 'kid', 'kid', 'u1'); const site = db.prepare('SELECT * FROM sites WHERE slug = ?').get('kid'); const user = db.prepare('SELECT * FROM users WHERE id = ?').get('u1'); function maak(object) { return AP.ingestOutboxActivity(site, user, { type: 'Create', object: { type: 'Note', to: ['https://test.example/ap/users/kid/followers'], cc: ['https://www.w3.org/ns/activitystreams#Public'], ...object, }, }); } test('de titel van een C2S-post komt in de kolom, de zoekindex en de note', async () => { const r = await maak({ name: 'Mijn eerste getitelde note', content: '
de inhoud
' }); assert.equal(r.status, 201); const post = db.prepare('SELECT * FROM posts WHERE id = ?').get(r.id); assert.equal(post.title, 'Mijn eerste getitelde note', 'de kolom draagt de titel'); // Vindbaar OP de titel, niet alleen op de inhoud -- de tweede schrijfplek // uit shaer-uply. Was alleen de kolom gerepareerd, dan faalde deze. const hit = db.prepare("SELECT post_id FROM posts_fts WHERE posts_fts MATCH 'getitelde'").get(); assert.ok(hit && hit.post_id === r.id, 'de titel staat in de zoekindex'); // En hij federeert zoals een webpost: Mastodon negeert `name` op een Note, // dus buildNote vouwt de titel als vetgedrukte eerste regel in de content. const note = AP.buildNote('https://test.example', site, post); assert.match(note.content, /^Mijn eerste getitelde note<\/strong><\/p>/, 'vetgedrukte eerste regel');
});
test('geen echte titel blijft een lege titel: zonder name, en met alleen witruimte', async () => {
// Een regel met twee kanten (samengevoegd 25-8): wat er niet is, wordt niet
// verzonnen -- of het veld nu ontbreekt of alleen witruimte draagt.
const zonder = await maak({ content: ' gewoon een note '), 'geen verzonnen kopregel');
const wit = await maak({ name: ' ', content: ' z '), 'en er komt geen lege kopregel');
});
test('de titel is platte tekst: HTML erin wordt tekst, en de grens is 200', async () => {
// `name` is per AS2 platte tekst, maar een client kan sturen wat hij wil.
// De kolom en de views verwachten tekst; opmaak wordt dus tekst, en een
// scriptpoging houdt niets uitvoerbaars over.
const r = await maak({ name: 'Dag wereld', content: ' x