111 lines
5.1 KiB
JavaScript
111 lines
5.1 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const Module = require('module');
|
|
|
|
const originalResolveFilename = Module._resolveFilename;
|
|
Module._resolveFilename = function (request, parent, isMain, options) {
|
|
if (request === '#src/data/announcement-icons') {
|
|
return path.join(__dirname, '..', 'src', 'data', 'announcement-icons.js');
|
|
}
|
|
if (request === '#root/package.json') {
|
|
return path.join(__dirname, '..', 'package.json');
|
|
}
|
|
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
};
|
|
|
|
const { buildDuplicateAnnouncementName, buildDuplicateAnnouncement } = require('../src/web/routes/signage/announcements/duplicate');
|
|
const { buildAnnouncementFormViewModel } = require('../src/web/routes/signage/announcements/form-view-model');
|
|
const renderAnnouncementsPage = require('../src/web/routes/signage/announcements/list');
|
|
|
|
test('announcement duplicate helper copies editable fields and resets runtime state', () => {
|
|
const source = {
|
|
id: 7,
|
|
message: 'Maintenance starts soon.',
|
|
short_label: 'Maintenance',
|
|
announcement_type: 'top-banner',
|
|
color_key: 'warning',
|
|
icon_key: 'info-circle',
|
|
duration_seconds: 120,
|
|
expires_at: '2026-08-04T10:00:00.000Z',
|
|
screen_ids: [2, 5]
|
|
};
|
|
|
|
const duplicate = buildDuplicateAnnouncement(source, buildDuplicateAnnouncementName(source.short_label));
|
|
|
|
assert.equal(duplicate.id, null);
|
|
assert.equal(duplicate.short_label, 'Copy of Maintenance');
|
|
assert.equal(duplicate.expires_at, null);
|
|
assert.equal(duplicate.message, 'Maintenance starts soon.');
|
|
assert.equal(duplicate.announcement_type, 'top-banner');
|
|
assert.equal(duplicate.color_key, 'warning');
|
|
assert.equal(duplicate.icon_key, 'info-circle');
|
|
assert.equal(duplicate.duration_seconds, 120);
|
|
assert.deepEqual(duplicate.screen_ids, [2, 5]);
|
|
});
|
|
|
|
test('announcement duplicate form model keeps info toast variant and secondary actions', () => {
|
|
const model = buildAnnouncementFormViewModel({ id: null, short_label: 'Maintenance' }, 'Review the copied values and save when ready.', { permissionKeys: ['announcements.create'] }, { messageVariant: 'info', announcementTypes: [], announcementColors: [], announcementIcons: [], announcementScreens: [] }, false);
|
|
|
|
assert.equal(model.messageVariant, 'info');
|
|
assert.equal(model.showSaveSecondaryActions, true);
|
|
});
|
|
|
|
test('announcement form model disables play when there are no screen targets', () => {
|
|
const model = buildAnnouncementFormViewModel({ id: 7, short_label: 'Maintenance', screen_ids: [], expires_at: '2026-08-03T00:00:00.000Z' }, '', { permissionKeys: ['announcements.update'] }, { announcementTypes: [], announcementColors: [], announcementIcons: [], announcementScreens: [] }, true);
|
|
|
|
assert.equal(model.actionClassName, 'btn-outline-info');
|
|
assert.equal(model.actionDisabled, true);
|
|
assert.match(model.actionDisabledTitle, /Select at least one screen group/i);
|
|
});
|
|
|
|
test('announcement list renders a disabled info play button without targets', () => {
|
|
const html = renderAnnouncementsPage({
|
|
announcements: [
|
|
{
|
|
id: 7,
|
|
short_label: 'Maintenance',
|
|
message: 'Maintenance starts soon.',
|
|
icon_key: 'info-circle',
|
|
color_key: 'warning',
|
|
announcement_type: 'top-banner',
|
|
duration_seconds: null,
|
|
expires_at: '2026-08-03T00:00:00.000Z',
|
|
screen_target_count: 0,
|
|
total_screen_count: 2,
|
|
screen_targets_label: ''
|
|
}
|
|
],
|
|
pagination: { totalItems: 1, currentPage: 1 }
|
|
}, '', { permissionKeys: ['announcements.update'] });
|
|
|
|
assert.match(html, /class="btn btn-sm btn-outline-info" type="submit" disabled title="Select at least one screen group to play this announcement\."/);
|
|
});
|
|
|
|
test('announcement list template includes duplicate action', () => {
|
|
const template = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'views', 'signage', 'announcements', 'list.hbs'), 'utf8');
|
|
|
|
assert.match(template, /\/announcements\/{\{id\}\}\/duplicate/);
|
|
assert.match(template, />Dupe<\/a>/);
|
|
});
|
|
|
|
test('announcement form template uses an icon-backed type picker', () => {
|
|
const template = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'views', 'signage', 'announcements', 'form.hbs'), 'utf8');
|
|
|
|
assert.match(template, /data-announcement-type-picker-toggle/);
|
|
assert.match(template, /data-announcement-type-option/);
|
|
assert.match(template, /data-type-icon="\{\{icon\}\}"/);
|
|
});
|
|
|
|
test('announcement form template uses a checkbox card grid for screen groups', () => {
|
|
const template = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'views', 'signage', 'announcements', 'form.hbs'), 'utf8');
|
|
|
|
assert.match(template, /announcement-screen-picker/);
|
|
assert.match(template, /data-announcement-screen-select-all/);
|
|
assert.match(template, /data-announcement-screen-select-none/);
|
|
assert.match(template, /name="screen_ids\[\]"/);
|
|
assert.match(template, /announcement-screen-chip/);
|
|
assert.match(template, /announcement-screen-chip__check/);
|
|
assert.ok(!/announcement-screen-chip__icon/.test(template));
|
|
}); |