const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('fs'); const os = require('os'); const path = require('path'); const { normalizeMediaPath, registerMediaAssets, syncMediaAssetsFromDirectory, countMediaAssetReferences } = require('../src/web/lib/media/library'); test('media library normalizes only media URLs', () => { assert.equal(normalizeMediaPath('/media/uploads/photo.png'), '/media/uploads/photo.png'); assert.equal(normalizeMediaPath(' /media/video.mp4 '), '/media/video.mp4'); assert.equal(normalizeMediaPath('/assets/photo.png'), null); }); test('media library registers uploaded files with their metadata', async () => { const queries = []; const pool = { async query(sql, params) { queries.push({ sql, params }); return [{ affectedRows: 1 }]; } }; const registered = await registerMediaAssets(pool, [{ filename: 'upload.png', originalname: 'Photo.png', mimetype: 'image/png', size: 42 }], file => '/media/uploads/' + file.filename, () => 'image', 7); assert.deepEqual(registered, ['/media/uploads/upload.png']); assert.match(queries[0].sql, /INSERT INTO c_media_assets/); assert.deepEqual(queries[0].params, [ '/media/uploads/upload.png', 'Photo.png', 'image', 'image/png', 42, 1, 7, 7 ]); }); test('media library backfills existing image and video uploads', async () => { const uploadDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'pulse-media-library-')); await fs.promises.writeFile(path.join(uploadDir, 'legacy.png'), Buffer.from('image')); await fs.promises.writeFile(path.join(uploadDir, 'legacy.mp4'), Buffer.from('video')); await fs.promises.writeFile(path.join(uploadDir, 'ignore.txt'), Buffer.from('other')); const queries = []; const pool = { async query(sql, params) { queries.push({ sql, params }); return [{ affectedRows: 1 }]; } }; try { assert.equal(await syncMediaAssetsFromDirectory(pool, uploadDir), 2); assert.deepEqual(queries.map(query => query.params[0]).sort(), [ '/media/uploads/legacy.mp4', '/media/uploads/legacy.png' ]); assert.match(queries[0].sql, /original_name = original_name/); assert.match(queries[0].sql, /is_published = is_published/); } finally { await fs.promises.rm(uploadDir, { recursive: true, force: true }); } }); test('media library counts slide and template references', async () => { const queries = []; const pool = { async query(sql, params) { queries.push({ sql, params }); if (sql.includes('FROM c_slides')) { return [[{ ref_count: 2 }]]; } return [[{ ref_count: 1 }]]; } }; assert.equal(await countMediaAssetReferences(pool, '/media/uploads/shared.png'), 3); assert.equal(queries.length, 2); assert.equal(queries[0].params[0], '/media/uploads/shared.png'); assert.equal(queries[1].params[0], '/media/uploads/shared.png'); assert.match(queries[0].sql, /LOCATE/); });