const test = require('node:test'); const assert = require('node:assert/strict'); const { collectContentReferences, replaceContentReferences } = require('../src/data/content-references'); test('content reference extraction indexes typed sources, media paths, and fonts by owner region', () => { const references = collectContentReferences('template', 42, { brand: { type: 'html', value: 'Brand', font_family: 'Acme Display' }, agenda: { type: 'timetable', timetable_group_id: 7 }, feed: { type: 'rss', feed_id: '8' }, forecast: { type: 'weather', weather_location_id: 9, weather_icon_set_id: 'night' }, api: { type: 'api', source_id: 10 } }); const values = references.map(reference => [reference.owner_key, reference.reference_type, reference.reference_value]); assert.deepEqual(values, [ ['brand', 'media', '/media/uploads/brand.png'], ['brand', 'font-family', 'acme display'], ['agenda', 'timetable-group', '7'], ['feed', 'rss-feed', '8'], ['forecast', 'weather-location', '9'], ['forecast', 'weather-icon-set', 'night'], ['api', 'api-request', '10'] ]); assert.ok(references.every(reference => reference.owner_type === 'template' && reference.owner_id === 42 && Buffer.isBuffer(reference.reference_hash))); }); test('content reference extraction deduplicates repeated references within a region', () => { const references = collectContentReferences('slide', 12, { hero: { value: '/media/uploads/a.png', secondary: '/media/uploads/a.png', source_id: 4, copy: { source_id: 4 } } }); assert.deepEqual(references.map(reference => [reference.reference_type, reference.reference_value]), [ ['media', '/media/uploads/a.png'], ['api-request', '4'] ]); }); test('content reference replacement preserves unchanged rows and only deletes or inserts the delta', async () => { const calls = []; const connection = { async query(sql, params) { calls.push([sql, params]); if (sql.startsWith('SELECT id, owner_key')) { return [[ { id: 101, owner_key: 'hero', reference_type: 'media', reference_value: '/media/uploads/keep.png' }, { id: 102, owner_key: 'api', reference_type: 'api-request', reference_value: '4' }, { id: 103, owner_key: 'old', reference_type: 'font-family', reference_value: 'arial' } ]]; } return [{}]; } }; await replaceContentReferences(connection, 'slide', 22, { hero: { value: '/media/uploads/keep.png' }, api: { source_id: 5 }, feed: { feed_id: 8 } }); const deletion = calls.find(([sql]) => sql.startsWith('DELETE FROM c_content_references')); assert.deepEqual(deletion[1], ['slide', 22, [102, 103]]); const insertion = calls.find(([sql]) => sql.startsWith('INSERT IGNORE INTO c_content_references')); assert.equal(insertion[1][0].length, 2); assert.deepEqual(insertion[1][0].map(row => [row[3], row[4]]), [['api-request', '5'], ['rss-feed', '8']]); assert.ok(!calls.some(([sql]) => sql === 'DELETE FROM c_content_references WHERE owner_type = ? AND owner_id = ?')); });