source: Klonkt/test/admin-seo-save.test.js

main
Last change on this file was bb9e54c, checked in by Robin <roboburr@…>, 3 weeks ago

SEO-paneel kon niets opslaan: twee regels stonden in de SQL-string

In f50a84b belandden de twee const-regels van de MusicBrainz-koppeling BINNEN
de template-literal van de UPDATE. Daarmee waren ze geen code maar tekst in de
SQL, en faalde elke opslag op /admin/seo met near "/": syntax error.

Niet alleen de koppeling: het hele paneel. Titelsjabloon, canonical,
omschrijving, og:image, alle verificatiecodes, publisher -- alles ging door
dezelfde UPDATE.

Waarom niemand het zag. Het is geldig JavaScript, dus node --check, de lader en
de suite bleven groen; de fout leeft pas bij prepare(). En het zoekscherm loopt
langs een aparte GET, dus 'Ben jij dit?' toonde de artiest netjes -- alleen
bewaren deed niets. Het actor-document liet daarom terecht geen schema:sameAs
zien: er stond niets in de kolom. Gemeten op soundfabrics: mb_artist_id is
null, op alle instanties.

Vier routetests erbij, door de echte route heen, plus de tweede helft: dat de
koppeling ook echt als schema:sameAs op de actor komt. Controleproef gedraaid --
met de oude opstelling vallen alle vier om terwijl node --check groen blijft.

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

  • Property mode set to 100644
File size: 4.6 KB
Line 
1// Het SEO & social-paneel opslaan, door de ECHTE route heen.
2//
3// Waarom deze test bestaat: in f50a84b stonden twee const-regels BINNEN de
4// template-literal van de UPDATE. Geldig JavaScript -- het werd tekst in de SQL
5// -- dus geen enkele lader, linter of syntaxcontrole zag er iets van. Pas bij
6// het opslaan viel het om, met `near "/": syntax error`, en dan niet alleen op
7// de MusicBrainz-koppeling maar op het HELE paneel: titelsjabloon, omschrijving,
8// og:image, elke verificatiecode.
9//
10// Het gevolg was stil op de plek waar je zou kijken. Het zoekscherm werkt langs
11// een aparte GET, dus de artiest verscheen netjes; alleen bewaren deed niets, en
12// het actor-document liet daarom terecht geen schema:sameAs zien. Zie
13// test/feed-alt-view.test.js voor dezelfde vorm: een formulierroute breekt in de
14// SQL, en alleen een test die er echt doorheen gaat merkt het.
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';
20const dbMod = await import('../src/config/database.js');
21const db = dbMod.default;
22dbMod.initializeDatabase();
23
24db.prepare('INSERT INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)')
25 .run('u1', 'baas', 'b@t.nl', 'x', 'god');
26db.prepare('INSERT INTO sites (id, slug, title, owner_id) VALUES (?,?,?,?)')
27 .run('s1', 'robo', 'Soundfabrics', 'u1');
28
29const express = (await import('express')).default;
30const router = (await import('../src/routes/admin-seo.js')).default;
31const app = express();
32app.use(express.urlencoded({ extended: true }));
33app.use((req, _res, next) => { req.session = { user: { id: 'u1', role: 'god' } }; next(); });
34app.use('/admin/seo', router);
35
36const server = app.listen(0);
37server.unref();
38const poort = server.address().port;
39
40// Met tijdslimiet: express vangt een worp in de handler niet af, dus zonder
41// limiet blijft de suite hangen op precies de fout die ze moet vangen.
42const post = async (velden) => {
43 try {
44 return await fetch(`http://127.0.0.1:${poort}/admin/seo`, {
45 method: 'POST', redirect: 'manual',
46 headers: { 'content-type': 'application/x-www-form-urlencoded' },
47 body: new URLSearchParams(velden).toString(),
48 signal: AbortSignal.timeout(5000),
49 });
50 } catch (e) {
51 assert.fail(`de route antwoordde niet (${e.name}) -- vrijwel altijd een worp in `
52 + 'de handler, en bij dit formulier meestal de SQL zelf');
53 }
54};
55const site = () => db.prepare('SELECT * FROM sites WHERE slug = ?').get('robo');
56
57const MBID = 'b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d';
58
59test('opslaan bewaart de MusicBrainz-koppeling', async () => {
60 const r = await post({ mb_artist_id: MBID, mb_artist_name: 'Soundfabrics', schema_type: 'Person' });
61 assert.ok(r.status === 302 || r.status === 200, 'opslaan mag niet stranden, kreeg ' + r.status);
62 assert.equal(site().mb_artist_id, MBID);
63 assert.equal(site().mb_artist_name, 'Soundfabrics');
64});
65
66test('en de rest van het paneel ook — de breuk raakte alle velden', async () => {
67 await post({
68 mb_artist_id: MBID,
69 title_template: '{title} · {site}',
70 default_description: 'Beats en alchemie',
71 google_verification: 'goog-123',
72 publisher_name: 'Soundfabrics',
73 schema_type: 'Organization',
74 });
75 const s = site();
76 assert.equal(s.title_template, '{title} · {site}');
77 assert.equal(s.default_description, 'Beats en alchemie');
78 assert.equal(s.google_verification, 'goog-123');
79 assert.equal(s.publisher_name, 'Soundfabrics');
80 assert.equal(s.schema_type, 'Organization');
81});
82
83test('geen MBID is ontkoppelen, en rommel komt de kolom niet in', async () => {
84 await post({ mb_artist_id: MBID, mb_artist_name: 'Soundfabrics' });
85 assert.equal(site().mb_artist_id, MBID, 'eerst gekoppeld');
86
87 await post({ mb_artist_id: '', mb_artist_name: '' });
88 assert.equal(site().mb_artist_id, null, 'leeg laten is ontkoppelen');
89
90 // Een URL of een handle in plaats van een id: de zeef hoort dat te weigeren,
91 // want dit veld gaat naar twee uitgangen naar buiten.
92 await post({ mb_artist_id: 'https://musicbrainz.org/artist/' + MBID });
93 assert.equal(site().mb_artist_id, null, 'een URL is geen MBID');
94});
95
96test('de koppeling belandt op het actor-document als schema:sameAs', async () => {
97 await post({ mb_artist_id: MBID, mb_artist_name: 'Soundfabrics' });
98 const AP = await import('../src/services/ActivityPubService.js');
99 const actor = AP.buildActor('https://test.example', site());
100 // De hele reden dat de kolom bestaat: hij hoort de draad op te gaan. Een test
101 // die alleen de kolom controleert zou de tweede helft missen.
102 assert.equal(actor.sameAs, `https://musicbrainz.org/artist/${MBID}`);
103});
Note: See TracBrowser for help on using the repository browser.