source: Klonkt/test/music-type.test.js@ 47f1183

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

En een test die bewaakt dat de gedeelde regel puur blijft

De editor draait dezelfde module in de browser, met een Map in plaats van een
query. Gaat er ooit een db-import in, dan valt hij nu hier om en niet pas in de
browser -- waar niemand het ziet.

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

  • Property mode set to 100644
File size: 6.6 KB
Line 
1// Welk soort uitgave is een BESTAANDE post? (shaer-cyg)
2//
3// Nieuwe posts krijgen hun type uit de keuze -- album of playlist wordt gekozen
4// als de playlist wordt gemaakt. Deze afleiding is er voor wat er al staat: de
5// type=audio posts van voor die keuze. De regel gaat over IDENTITEIT en niet
6// over tellen: een post neemt het type van zijn muziek over als hij precies EEN
7// muzikale eenheid bevat. Zijn het er meer, dan is de post een post die naar
8// muziek verwijst en houden de collecties hun eigen identiteit -- en vervalt de
9// reden om de posttitel en -cover te lenen.
10import { test } from 'node:test';
11import assert from 'node:assert/strict';
12
13process.env.DATABASE_PATH = ':memory:';
14process.env.PUBLIC_BASE_URL = 'https://test.example';
15
16const dbMod = await import('../src/config/database.js');
17dbMod.initializeDatabase();
18const db = dbMod.default;
19const { postMusicType } = await import('../src/services/music/index.js');
20
21const SITE = 'site-muziek';
22const ANDERE = 'site-anders';
23db.prepare('INSERT INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)')
24 .run('u1', 'robin', 'r@test', 'x', 'god');
25db.prepare('INSERT INTO sites (id, slug, title, owner_id) VALUES (?,?,?,?)').run(SITE, 'muziek', 'Muziek', 'u1');
26db.prepare('INSERT INTO sites (id, slug, title, owner_id) VALUES (?,?,?,?)').run(ANDERE, 'anders', 'Anders', 'u1');
27
28const maakPlaylist = (id, kind, siteId = SITE) =>
29 db.prepare('INSERT INTO playlists (id, site_id, title, kind) VALUES (?, ?, ?, ?)')
30 .run(id, siteId, id, kind);
31
32maakPlaylist('nachtlicht', 'playlist');
33maakPlaylist('de-plaat', 'album');
34maakPlaylist('tweede', 'playlist');
35maakPlaylist('elders', 'playlist', ANDERE);
36
37const type = (c) => postMusicType(c, SITE);
38
39test('geen muziek: geen type', () => {
40 assert.equal(type('<p>gewoon een bericht</p>'), null);
41 assert.equal(type(''), null);
42 assert.equal(type(null), null);
43});
44
45test('losse tracks worden een playlist, en lenen de metadata van de post', () => {
46 const r = type('Twee nieuwe: [[track:a]] en [[track:b]]');
47 assert.equal(r.type, 'playlist');
48 assert.deepEqual(r.tracks, ['a', 'b']);
49 assert.equal(r.leentMetadata, true);
50});
51
52test('ook EEN losse track wordt een playlist', () => {
53 // Naar buiten toe is er dan altijd een collectie om naar te wijzen. Dat
54 // "Playlist" boven een enkel nummer gek leest is een weergavekwestie.
55 assert.equal(type('[[track:a]]').type, 'playlist');
56});
57
58test('de post neemt de GEKOZEN soort van de playlist over', () => {
59 // De kern van Robins besluit: album of playlist is bij het maken van de
60 // playlist al gekozen. Hier wordt hij opgezocht, niet afgeleid.
61 assert.equal(type('Nieuw: [[playlist:nachtlicht]]').type, 'playlist');
62 assert.equal(type('Nieuw: [[playlist:de-plaat]]').type, 'album',
63 'een post om een album is een album, ook al heet de shortcode playlist');
64});
65
66test('de collectie draagt haar eigen soort mee', () => {
67 const r = type('Nieuw: [[playlist:nachtlicht]]');
68 assert.deepEqual(r.collectie, { soort: 'playlist', id: 'nachtlicht' });
69 assert.equal(r.leentMetadata, true);
70});
71
72test('een album-insluiting is ook een collectie, en telt als album', () => {
73 // [[album:naam]] groepeert tracks op hun albumveld -- geen playlist-rij, dus
74 // geen gekozen soort. Hem als losse tracks tellen zou een albumpost tot
75 // playlist maken.
76 const r = type('Luister [[album:De Plaat]]');
77 assert.equal(r.type, 'album');
78 assert.deepEqual(r.collectie, { soort: 'album', naam: 'De Plaat' });
79});
80
81test('een collectie MET losse tracks is een album, en die losse zijn bonus', () => {
82 const r = type('[[playlist:nachtlicht]] plus [[track:x]] en [[track:y]]');
83 assert.equal(r.type, 'album', 'ook al is de playlist zelf een playlist');
84 assert.equal(r.collectie.id, 'nachtlicht');
85 assert.deepEqual(r.bonus, ['x', 'y'], 'geen rommelrestje maar bonus-tracks');
86 assert.deepEqual(r.tracks, [], 'de losse zitten in bonus, niet twee keer');
87 assert.equal(r.leentMetadata, true);
88});
89
90test('TWEE collecties: de post blijft een post en leent niets', () => {
91 const r = type('[[playlist:nachtlicht]] en ook [[playlist:tweede]]');
92 assert.equal(r.type, 'post');
93 assert.equal(r.collecties.length, 2);
94 assert.equal(r.leentMetadata, false,
95 'bij twee is de post niet meer de drager van EEN identiteit');
96});
97
98test('twee collecties van verschillende soort tellen ook als twee', () => {
99 const r = type('[[playlist:nachtlicht]] naast [[album:De Plaat]]');
100 assert.equal(r.type, 'post');
101 assert.equal(r.collecties.length, 2);
102});
103
104test('dezelfde insluiting twee keer is EEN collectie', () => {
105 // Anders maakt een herhaalde shortcode van een albumpost stilletjes een
106 // gewone post.
107 const r = type('[[playlist:nachtlicht]] ... en nog eens [[playlist:nachtlicht]]');
108 assert.equal(r.type, 'playlist');
109 assert.equal(r.collectie.id, 'nachtlicht');
110});
111
112test('dezelfde track twee keer telt ook maar een keer', () => {
113 assert.deepEqual(type('[[track:a]] [[track:a]] [[track:b]]').tracks, ['a', 'b']);
114});
115
116test('onbekende playlist: gewone post, niets verzonnen', () => {
117 // Robins laatste optie voor een onbekende situatie. De insluiting blijft
118 // staan en houdt de post als context; alleen het label wordt niet geraden.
119 const r = type('[[playlist:bestaat-niet]]');
120 assert.equal(r.type, 'post');
121 assert.deepEqual(r.onbekend, ['bestaat-niet']);
122 assert.equal(r.leentMetadata, false);
123});
124
125test('een playlist van een ANDERE site telt niet als de onze', () => {
126 const r = type('[[playlist:elders]]');
127 assert.equal(r.type, 'post');
128 assert.deepEqual(r.onbekend, ['elders']);
129});
130
131test('zonder site is er niets op te zoeken, dus geen type verzinnen', () => {
132 assert.equal(postMusicType('[[playlist:nachtlicht]]').type, 'post');
133});
134
135test('de regel werkt ook zonder database -- de editor gebruikt hem zo', async () => {
136 // De editor draait dezelfde module in de browser, met een Map in plaats van
137 // een query. Deze test bewaakt dat de gedeelde module PUUR blijft: gaat er
138 // ooit een db-import in, dan valt hij hier om en niet pas in de browser.
139 const { afleidenUitInsluitingen } = await import('../src/assets/js/shared/post-music-type.js');
140 const soorten = new Map([['een', 'album'], ['twee', 'playlist']]);
141 const kindVan = (id) => soorten.get(id) || null;
142
143 assert.equal(afleidenUitInsluitingen('[[playlist:een]]', kindVan).type, 'album');
144 assert.equal(afleidenUitInsluitingen('[[playlist:twee]]', kindVan).type, 'playlist');
145 assert.equal(afleidenUitInsluitingen('[[track:x]]', kindVan).type, 'playlist');
146 assert.equal(afleidenUitInsluitingen('gewoon tekst', kindVan), null);
147 assert.equal(afleidenUitInsluitingen('[[playlist:weg]]', kindVan).type, 'post');
148});
Note: See TracBrowser for help on using the repository browser.