Release v2.13.1
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m15s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 32s

This commit is contained in:
2026-09-11 20:46:37 +01:00
parent 0a03cdd0b7
commit 394d23bb4d
47 changed files with 2408 additions and 559 deletions
+91
View File
@@ -0,0 +1,91 @@
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/);
});