Files
pulse-signage/test/fonts-routes.test.js
T
lzstealth 05c9341b08
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m50s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 34s
Release v2.15.4
2026-10-17 16:01:00 +01:00

277 lines
8.5 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
require('../src/common');
const fontLibrary = require('../src/web/lib/media/font-library');
const registerFontRoutes = require('../src/web/routes/settings/fonts');
const renderFontsPage = require('../src/web/routes/settings/fonts/list');
function createHandlers() {
const handlers = {};
const app = {
get(path, ...routeHandlers) {
handlers[`GET ${path}`] = routeHandlers;
},
post(path, ...routeHandlers) {
handlers[`POST ${path}`] = routeHandlers;
}
};
return { app, handlers };
}
test('fonts route filters and paginates managed fonts', async () => {
const originalLoadFontLibrary = fontLibrary.loadFontLibrary;
const { app, handlers } = createHandlers();
fontLibrary.loadFontLibrary = function () {
return {
fonts: [
{ id: 'alpha', family: 'Alpha Sans', fileName: 'alpha.woff2', format: 'woff2', enabled: true },
{ id: 'beta', family: 'Beta Sans', fileName: 'beta.woff2', format: 'woff2', enabled: false },
{ id: 'gamma', family: 'Gamma Sans', fileName: 'gamma.woff2', format: 'woff2', enabled: true }
],
stylesheetHref: '/media/fonts/fonts.css'
};
};
try {
registerFontRoutes(app, {
pool: {
async query() {
return [[{ match_count: 0 }]];
}
},
common: {
getSearchQuery() {
return 'beta';
}
},
pages: {
renderFontsPage(data) {
return JSON.stringify(data);
}
},
upload: {
single() {
return function (_req, _res, next) {
next();
};
}
},
uploadDir: 'e:/Projects Git/pulse-signage/media',
backgroundTaskQueue: null,
setAuthMessageCookie() {}
});
const response = {
statusCode: 200,
body: null,
send(value) {
this.body = value;
return this;
}
};
await handlers['GET /settings/fonts'][1]({
query: {
page: '2'
},
currentUser: {
id: 1,
permissions: ['fonts.read']
}
}, response, function () {});
const rendered = JSON.parse(response.body);
assert.equal(rendered.fonts.length, 1);
assert.equal(rendered.fonts[0].id, 'beta');
assert.equal(rendered.pagination.currentPage, 1);
assert.equal(rendered.pagination.totalItems, 1);
} finally {
fontLibrary.loadFontLibrary = originalLoadFontLibrary;
}
});
test('fonts route sorts by format and status', async () => {
const originalLoadFontLibrary = fontLibrary.loadFontLibrary;
const { app, handlers } = createHandlers();
fontLibrary.loadFontLibrary = function () {
return {
fonts: [
{ id: 'alpha', family: 'Alpha Sans', fileName: 'alpha.woff2', format: 'woff2', enabled: true },
{ id: 'beta', family: 'Beta Sans', fileName: 'beta.otf', format: 'opentype', enabled: false },
{ id: 'gamma', family: 'Gamma Sans', fileName: 'gamma.ttf', format: 'truetype', enabled: true }
],
stylesheetHref: '/media/fonts/fonts.css'
};
};
try {
registerFontRoutes(app, {
pool: {
async query() {
return [[{ match_count: 0 }]];
}
},
common: {
getSearchQuery() {
return '';
},
getSortQuery(req) {
return req.query.sort;
},
getSortDirectionQuery(req) {
return req.query.direction;
}
},
pages: {
renderFontsPage(data) {
return JSON.stringify(data);
}
},
upload: {
single() {
return function (_req, _res, next) {
next();
};
}
},
uploadDir: 'e:/Projects Git/pulse-signage/media',
backgroundTaskQueue: null,
setAuthMessageCookie() {}
});
const response = {
statusCode: 200,
body: null,
send(value) {
this.body = value;
return this;
}
};
await handlers['GET /settings/fonts'][1]({
query: {
sort: 'format',
direction: 'asc'
},
currentUser: {
id: 1,
permissions: ['fonts.read']
}
}, response, function () {});
let rendered = JSON.parse(response.body);
assert.deepEqual(rendered.fonts.map(function (font) { return font.id; }), ['beta', 'gamma', 'alpha']);
await handlers['GET /settings/fonts'][1]({
query: {
sort: 'status',
direction: 'asc'
},
currentUser: {
id: 1,
permissions: ['fonts.read']
}
}, response, function () {});
rendered = JSON.parse(response.body);
assert.deepEqual(rendered.fonts.map(function (font) { return font.id; }), ['beta', 'alpha', 'gamma']);
} finally {
fontLibrary.loadFontLibrary = originalLoadFontLibrary;
}
});
test('fonts page renders the upload card above the table card', () => {
const html = renderFontsPage({
fonts: [
{
id: 'alpha',
family: 'Alpha Sans',
fileName: 'alpha.woff2',
format: 'woff2',
enabled: true,
inUse: false
}
],
pagination: {
hasMultiplePages: true,
startItem: 1,
endItem: 1,
totalItems: 1,
itemLabel: 'fonts',
ariaLabel: 'Font pages',
hasPrevious: false,
hasNext: true,
previousUrl: '',
nextUrl: '?page=2',
pages: [{ number: 1, active: true, url: '' }]
},
stylesheetHref: '/media/fonts/fonts.css?v=1'
}, '', { id: 1 });
assert.ok(html.indexOf('Upload font') < html.indexOf('Managed fonts'));
assert.match(html, /data-table-search-container/);
assert.match(html, /table-pagination/);
assert.match(html, /data-async-command/);
assert.match(html, /data-font-toggle-row/);
assert.match(html, /data-font-status-badge/);
assert.match(html, /<link rel="stylesheet" href="\/media\/fonts\/fonts\.css\?v&#x3D;1" \/>/);
assert.match(html, /<th>Preview<\/th>/);
assert.match(html, /font-family: 'Alpha Sans';/);
assert.match(html, /data-table-sort-key="family"/);
assert.match(html, /data-table-sort-key="file"/);
assert.match(html, /data-table-sort-key="format"/);
assert.match(html, /data-table-sort-key="status"/);
});
test('font upload, status changes, and deletion are audited', async () => {
const originals = {
loadFontLibrary: fontLibrary.loadFontLibrary,
addFontFile: fontLibrary.addFontFile,
setFontEnabled: fontLibrary.setFontEnabled,
deleteFontFile: fontLibrary.deleteFontFile
};
const { app, handlers } = createHandlers();
const events = [];
const font = { id: 'alpha.woff2', family: 'Alpha Sans', name: 'Alpha Sans', fileName: 'alpha.woff2', format: 'woff2', enabled: true };
fontLibrary.loadFontLibrary = function () { return { fonts: [font], stylesheetHref: '' }; };
fontLibrary.addFontFile = async function () { return { font: font, fonts: [font] }; };
fontLibrary.setFontEnabled = async function (_dir, _id, enabled) { return Object.assign({}, font, { enabled: enabled }); };
fontLibrary.deleteFontFile = async function () { return font; };
try {
registerFontRoutes(app, {
pool: { async query() { return [[{ match_count: 0 }]]; } },
pages: { renderFontsPage() { return ''; } },
upload: { single() { return function (_req, _res, next) { next(); }; } },
uploadDir: 'unused',
backgroundTaskQueue: null,
recordRequestAuditEvent(_pool, _req, event) { events.push(event); }
});
const response = { redirect() { return this; } };
const next = function (error) { if (error) throw error; };
const currentUser = { id: 12, permissionKeys: ['fonts.create', 'fonts.update', 'fonts.delete'] };
await handlers['POST /settings/fonts'].at(-1)(
{ currentUser: currentUser, body: { font_family: 'Alpha Sans' }, file: { path: 'unused' } }, response, next
);
await handlers['POST /settings/fonts/:id/toggle'].at(-1)(
{ currentUser: currentUser, params: { id: font.id }, body: { enabled: '0' } }, response, next
);
await handlers['POST /settings/fonts/:id/delete'].at(-1)(
{ currentUser: currentUser, params: { id: font.id } }, response, next
);
assert.deepEqual(events.map(function (event) { return event.eventType; }), ['font.uploaded', 'font.disabled', 'font.deleted']);
assert.ok(events.every(function (event) { return event.category === 'media-assets' && event.actorUserId === 12; }));
} finally {
fontLibrary.loadFontLibrary = originals.loadFontLibrary;
fontLibrary.addFontFile = originals.addFontFile;
fontLibrary.setFontEnabled = originals.setFontEnabled;
fontLibrary.deleteFontFile = originals.deleteFontFile;
}
});