Changeset 812fea9 in Klonkt for test/archive-import.test.js


Ignore:
Timestamp:
08/06/2026 02:20:19 PM (5 weeks ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
7aa3140
Parents:
58cfe5f
git-author:
Robin <roboburr@…> (08/06/2026 02:20:09 PM)
git-committer:
roboburr <roboburr@…> (08/06/2026 02:20:19 PM)
Message:

Elke bijlage zegt waar hij voor was (shaer-pmr, vervolg)

Gevonden bij een oefenherstel: ik vergeleek dertien kolommen, noemde het een
schone rondgang, en vergeleek daarna ALLE kolommen. Toen bleken er drie dingen
weg te vallen.

COVER de bytes zaten in het archief, maar nergens stond dat ze de

cover waren. cover_image_url kwam als null terug, dus de post
stond zonder cover.

C2S-BIJLAGE idem: het audiobestand en zijn poster zaten erin, maar

c2s_attachments werd niet hersteld, dus de speler verdween.

SUB-SECONDE de import zette tijdstempels om naar SQL-notatie en verloor de

milliseconden. Twee posts in dezelfde seconde staan dan in
willekeurige volgorde.

Elke bijlage draagt nu een shaer:role -- cover, coverVideo, inline, c2s, poster,
track -- en een poster wijst met shaer:posterFor naar de bijlage waar hij bij
hoort. De importer bouwt cover_image_url, cover_video_url en c2s_attachments
daaruit terug. Een rol is geen versiering: zonder rol heeft het archief wel de
bytes maar niet het feit dat ze de cover WAREN, en dat zie je pas als je alle
kolommen vergelijkt.

Tijdstempels gaan nu ongewijzigd de database in. Klonkt schrijft zelf in twee
spellingen; het archief normaliseert naar ISO. Het MOMENT overleeft de rondgang,
de spelling niet -- nu ook zo gedocumenteerd in plaats van stilzwijgend.

Rondgang op echte beta-data: geen verschil meer over 29 kolommen, met de tijden
op moment vergeleken in plaats van op tekst. 21 tests. Suite 514/514.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • test/archive-import.test.js

    r58cfe5f r812fea9  
    292292});
    293293
     294test('de cover en de speler komen terug, niet alleen hun bestanden', () => {
     295  // Gevonden bij het oefenherstel, door ALLE kolommen te vergelijken in plaats
     296  // van een handjevol: de bytes zaten in het archief, maar nergens stond dat ze
     297  // de cover waren. De post kwam zonder cover en zonder speler terug.
     298  leeg();
     299  fs.mkdirSync(path.join(MEDIA, 'c'), { recursive: true });
     300  for (const [n, b] of [['cov.jpg', 'cover'], ['op.m4a', 'audio'], ['op.png', 'poster']]) {
     301    fs.writeFileSync(path.join(MEDIA, 'c', n), Buffer.from(b));
     302  }
     303  db.prepare(`INSERT INTO posts (id, site_id, slug, author_id, title, content, status, published_at, cover_image_url, cover_alt, c2s_attachments)
     304              VALUES ('rijk','s1','rijke-post','u1','Rijk','<p>x</p>','published','2026-08-05 10:00:00',
     305              '/media/c/cov.jpg','de cover', ?)`)
     306    .run(JSON.stringify([{ url: '/media/c/op.m4a', mediaType: 'audio/mp4', name: 'opname.m4a', poster: '/media/c/op.png' }]));
     307
     308  const arch = AX.buildArchive('me', { exportedAt: 'X' });
     309  const rollen = JSON.parse(arch.files.get('posts/rijk.json').toString()).attachment.map((a) => a['shaer:role']);
     310  assert.deepEqual(rollen.sort(), ['c2s', 'cover', 'poster'], 'elke bijlage zegt waar hij voor was');
     311
     312  db.prepare('DELETE FROM posts').run();
     313  fs.rmSync(path.join(MEDIA, 'c'), { recursive: true, force: true });
     314  AI.importArchive(arch.files, { slug: 'me' });
     315
     316  const p = db.prepare("SELECT * FROM posts WHERE id = 'rijk'").get();
     317  assert.equal(p.cover_image_url, '/media/c/cov.jpg', 'zonder dit staat de post zonder cover terug');
     318  assert.equal(p.cover_alt, 'de cover');
     319  const c2s = JSON.parse(p.c2s_attachments);
     320  assert.equal(c2s[0].url, '/media/c/op.m4a');
     321  assert.equal(c2s[0].poster, '/media/c/op.png', 'de poster hoort weer bij zijn opname');
     322  assert.ok(fs.existsSync(path.join(MEDIA, 'c', 'cov.jpg')));
     323});
     324
     325test('het MOMENT van een tijdstempel overleeft, ook uit SQL-notatie', () => {
     326  // Klonkt schrijft in twee spellingen. Het archief normaliseert naar ISO; het
     327  // moment blijft, de spelling niet. Dat is gedocumenteerd gedrag, geen verlies.
     328  leeg();
     329  db.prepare(`INSERT INTO posts (id, site_id, slug, author_id, title, content, status, published_at)
     330              VALUES ('tijd','s1','tijd','u1','T','<p>x</p>','published','2026-07-01 12:56:10')`).run();
     331  const arch = AX.buildArchive('me', { exportedAt: 'X' });
     332  db.prepare('DELETE FROM posts').run();
     333  AI.importArchive(arch.files, { slug: 'me' });
     334  const p = db.prepare("SELECT published_at FROM posts WHERE id = 'tijd'").get();
     335  assert.equal(Date.parse(p.published_at), Date.parse('2026-07-01T12:56:10Z'));
     336});
     337
    294338test('zonder manifest is het geen archief', () => {
    295339  const files = new Map(ARCHIEF.files);
Note: See TracChangeset for help on using the changeset viewer.