92 lines
4.1 KiB
JavaScript
92 lines
4.1 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const path = require('node:path');
|
|
const fs = require('node:fs');
|
|
const Handlebars = require('handlebars');
|
|
|
|
const { registerHandlebars } = require('../src/web/handlebars');
|
|
|
|
function compileActionButtons(hash) {
|
|
const hb = Handlebars.create();
|
|
registerHandlebars(hb, {
|
|
viewsRoot: path.join(__dirname, '..', 'src', 'web', 'views'),
|
|
hasPermission: () => true,
|
|
hasAnyPermission: () => true
|
|
});
|
|
|
|
const template = hb.compile('{{{saveActionButtons ' + Object.entries(hash).map(function ([key, value]) {
|
|
return key + '="' + String(value).replace(/"/g, '"') + '"';
|
|
}).join(' ') + '}}}');
|
|
|
|
return String(template({}));
|
|
}
|
|
|
|
test('save action buttons render save close new cancel and delete controls', () => {
|
|
const html = compileActionButtons({
|
|
formId: 'example-form',
|
|
saveUrl: '/items/1',
|
|
cancelUrl: '/items',
|
|
deleteUrl: '/items/1/delete',
|
|
deleteConfirmMessage: 'Delete this item?',
|
|
deleteTitle: 'Delete is disabled.',
|
|
showSaveAndClose: true,
|
|
showSaveAndNew: true,
|
|
showDelete: true
|
|
});
|
|
|
|
assert.match(html, /<button type="submit" class="btn btn-success" form="example-form" name="save_action" value="save">Save<\/button>/);
|
|
assert.match(html, /name="save_action" value="close">Save and Close<\/button>/);
|
|
assert.match(html, /name="save_action" value="new">Save and New<\/button>/);
|
|
assert.match(html, /<a class="btn btn-warning" href="\/items" data-confirm-unsaved="You have unsaved changes\. Leave this page\?">Cancel<\/a>/);
|
|
assert.match(html, /<button type="button" class="btn btn-danger" data-delete-action-url="\/items\/1\/delete" data-confirm-message="Delete this item\?">Delete<\/button>/);
|
|
});
|
|
|
|
test('save action buttons can hide the secondary dropdown and delete control', () => {
|
|
const html = compileActionButtons({
|
|
formId: 'example-form',
|
|
saveUrl: '/items/1',
|
|
cancelUrl: '/items',
|
|
showSaveAndClose: false,
|
|
showSaveAndNew: false,
|
|
showDelete: false
|
|
});
|
|
|
|
assert.match(html, /<button type="submit" class="btn btn-success" form="example-form" name="save_action" value="save">Save<\/button>/);
|
|
assert.doesNotMatch(html, /Save and Close/);
|
|
assert.doesNotMatch(html, /Save and New/);
|
|
assert.match(html, /<a class="btn btn-warning" href="\/items" data-confirm-unsaved="You have unsaved changes\. Leave this page\?">Cancel<\/a>/);
|
|
assert.doesNotMatch(html, /Delete<\/button>/);
|
|
});
|
|
|
|
test('save action buttons keep the new action wired for create pages', () => {
|
|
const html = compileActionButtons({
|
|
formId: 'example-form',
|
|
saveUrl: '/settings/users',
|
|
cancelUrl: '/settings/users',
|
|
showSaveAndClose: true,
|
|
showSaveAndNew: true,
|
|
showDelete: true
|
|
});
|
|
|
|
assert.match(html, /name="save_action" value="new">Save and New<\/button>/);
|
|
assert.match(html, /name="save_action" value="close">Save and Close<\/button>/);
|
|
});
|
|
|
|
test('playlist slide picker follows confirm then cancel button conventions', () => {
|
|
const source = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'views', 'signage', 'playlists', 'form.hbs'), 'utf8');
|
|
|
|
assert.match(source, /<button type="button" class="btn btn-success" id="playlist-confirm-add-slides" disabled>Add selected slides<\/button>\s*<button type="button" class="btn btn-warning" data-bs-dismiss="modal">Cancel<\/button>/);
|
|
});
|
|
|
|
test('playlist schedule actions are separate spaced buttons', () => {
|
|
const source = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'views', 'signage', 'playlists', 'slide-config.hbs'), 'utf8');
|
|
|
|
assert.match(source, /<div class="card-footer d-flex justify-content-end gap-2">\s*<button type="submit" class="btn btn-primary">Save schedule<\/button>\s*<button type="button" class="btn btn-warning" data-schedule-cancel/);
|
|
assert.doesNotMatch(source, /\bbtn-group\b/);
|
|
});
|
|
|
|
test('playlist schedule footer excludes the clearfix spacer from its flex actions', () => {
|
|
const source = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'public', 'css', 'theme-custom.css'), 'utf8');
|
|
|
|
assert.match(source, /^\.slide-schedule-card > form > \.card-footer::after\s*\{\s*content: none;\s*\}/m);
|
|
}); |