source: Klonkt/test/cover-fallback.test.js

main
Last change on this file was 2d13bf3, checked in by Robin <roboburr@…>, 5 weeks ago

Leg vast dat een speler-post zijn omslag in image draagt

Een post met gehoste audio of een externe embed laat zijn omslag uit
attachment vallen zodat Mastodon de kaart toont, en de omslag verhuist
naar het AS2-veld image. Daar hangen twee lezers aan: handleInbox tilt
hem eruit voor binnenkomende posts, en sinds vandaag doet Shaer hetzelfde
voor eigen posts van de outbox. Niets bewaakte dat contract.

Vier gevallen: gehoste audio, een externe embed, de gewone post die zijn
omslag juist WEL als bijlage houdt en geen image mag krijgen (anders
tonen de clients hem dubbel), en de post zonder omslag.

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

  • Property mode set to 100644
File size: 3.3 KB
Line 
1// De omslag van een speler-post (Barts melding, 7-8).
2//
3// Een post met gehoste audio of een externe embed laat zijn omslag BEWUST uit
4// `attachment` vallen: Mastodon toont media OF een kaart, nooit allebei, en
5// voor zo'n post willen we de kaart. De omslag verhuist dan naar het AS2-veld
6// `image` van de Note.
7//
8// Dat is een CONTRACT, want er hangen twee lezers aan: handleInbox tilt hem er
9// weer uit voor binnenkomende posts, en sinds vandaag doet Shaer hetzelfde voor
10// je eigen posts van de outbox. Zonder deze test kan `image` stil verdwijnen en
11// wordt een muzieksite in beide clients een muur van kale kaartjes -- precies
12// het beeld waarmee dit begon.
13//
14// In-memory SQLite. Run: npm test
15import { test } from 'node:test';
16import assert from 'node:assert/strict';
17
18process.env.DATABASE_PATH = ':memory:';
19process.env.PUBLIC_BASE_URL = 'https://test.example';
20
21const dbMod = await import('../src/config/database.js');
22const db = dbMod.default;
23dbMod.initializeDatabase();
24const AP = (await import('../src/services/ActivityPubService.js')).default;
25
26const BASE = 'https://test.example';
27db.prepare('INSERT INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)').run('u1', 'u1', 'u1@test', 'x', 'god');
28db.prepare('INSERT INTO sites (id, slug, title, owner_id, is_primary) VALUES (?,?,?,?,?)').run('s1', 'demo', 'Demo', 'u1', 1);
29const site = db.prepare('SELECT * FROM sites WHERE id = ?').get('s1');
30site.primary_slug = 'demo';
31
32db.prepare('INSERT INTO media (id, site_id, filename, mime_type, size, storage_path) VALUES (?,?,?,?,?,?)')
33 .run('m1', 's1', 'song.mp3', 'audio/mpeg', 1000, '/x/song.mp3');
34// fedi_open = 0: de standaard, en juist die post verliest zijn omslag zonder
35// er een speler voor terug te krijgen.
36db.prepare('INSERT INTO audio_tracks (id, site_id, title, media_id, fedi_open) VALUES (?,?,?,?,?)')
37 .run('t1', 's1', 'Gesloten track', 'm1', 0);
38
39const post = (over) => ({ id: 'p', slug: 'p', title: '', content: '<p>x</p>', tags: '[]',
40 cover_image_url: '/media/cover.webp', cover_alt: 'De hoes', created_at: '2026-01-01T00:00:00Z', ...over });
41const images = (n) => (n.attachment || []).filter((a) => /^image\//.test(a.mediaType || ''));
42
43test('een gehoste-audio post ruilt zijn omslag-bijlage in voor image', () => {
44 const n = AP.buildNote(BASE, site, post({ content: '<p>[[track:t1]]</p>' }));
45 assert.equal(images(n).length, 0, 'geen afbeeldingsbijlage');
46 assert.ok(n.image, 'omslag staat in image');
47 assert.equal(n.image.url, `${BASE}/media/cover.webp`);
48 assert.equal(n.image.name, 'De hoes', 'de alt-tekst gaat mee');
49});
50
51test('een externe embed doet hetzelfde', () => {
52 const n = AP.buildNote(BASE, site, post({ content: '<p>Luister: https://open.spotify.com/track/abc</p>' }));
53 assert.equal(images(n).length, 0);
54 assert.equal(n.image && n.image.url, `${BASE}/media/cover.webp`);
55});
56
57test('een gewone post houdt zijn omslag als bijlage en krijgt GEEN image', () => {
58 // Anders zou elke fotopost in de clients een tweede, identieke omslag tonen.
59 const n = AP.buildNote(BASE, site, post());
60 assert.equal(images(n).length, 1);
61 assert.equal(images(n)[0].url, `${BASE}/media/cover.webp`);
62 assert.ok(!n.image, 'image blijft leeg');
63});
64
65test('zonder omslag valt er niets te verhuizen', () => {
66 const n = AP.buildNote(BASE, site, post({ content: '<p>[[track:t1]]</p>', cover_image_url: null }));
67 assert.ok(!n.image);
68});
Note: See TracBrowser for help on using the repository browser.