'use strict';
const common = require('../common');
const fc = require('fast-check');
const path = require('path');
/**
* icon markup of the bootstrap5 template
*
* @param {string} name - bootstrap icon name
* @returns {string}
*/
function icon(name) {
return '';
}
describe('Alert', function () {
describe('showStatus', function () {
it('shows a status message (basic)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
function (icon, message) {
icon = icon.join('');
message = message.join('');
const expected = '
' + message + '
';
document.body.innerHTML =
'';
PrivateBin.Alert.init();
PrivateBin.Alert.showStatus(message, icon);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('shows a status message (bootstrap)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
function (message) {
message = message.join('');
const expected = '' +
'
' + icon('info-circle') + ' ' +
message + '
';
document.body.innerHTML =
'' +
'
' + icon('info-circle') + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showStatus(message);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('shows a status message (bootstrap, custom icon)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
function (customIcon, message) {
customIcon = customIcon.join('');
message = message.join('');
const expected = '' +
'
' + icon(customIcon || 'info-circle') + ' ' +
message + '
';
document.body.innerHTML =
'' +
'
' + icon('info-circle') + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showStatus(message, customIcon);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('replaces a status message rendered by the server, keeping its buttons (bootstrap)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString(), {minLength: 1}),
fc.array(common.fcAlnumString(), {minLength: 1}),
function (serverMessage, message) {
serverMessage = 'server ' + serverMessage.join('');
message = message.join('');
const button = '';
document.body.innerHTML =
'' +
icon('info-circle') + ' ' + serverMessage + '
' +
button + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showStatus(message);
const status = document.getElementById('status');
return status.innerHTML === '' + icon('info-circle') +
' ' + message + '
' + button &&
status.textContent.indexOf(serverMessage) === -1;
}
));
});
});
describe('showWarning', function () {
it('shows a warning message (basic)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
function (icon, message) {
icon = icon.join('');
message = message.join('');
const expected = '' + message + '
';
document.body.innerHTML =
'';
PrivateBin.Alert.init();
PrivateBin.Alert.showWarning(message, icon);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('shows a warning message (bootstrap)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
function (message) {
message = message.join('');
const expected = '' + icon('exclamation-triangle') +
' ' + message + '
';
document.body.innerHTML =
'' + icon('exclamation-triangle') + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showWarning(message);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('shows a warning message (bootstrap, custom icon)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
function (customIcon, message) {
customIcon = customIcon.join('');
message = message.join('');
const expected = '' +
icon(customIcon || 'exclamation-triangle') +
' ' + message + '
';
document.body.innerHTML =
'' + icon('exclamation-triangle') + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showWarning(message, customIcon);
const result = document.body.innerHTML;
return expected === result;
}
));
});
});
describe('showError', function () {
it('shows an error message (basic)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
function (icon, message) {
icon = icon.join('');
message = message.join('');
const expected = '' + message + '
';
document.body.innerHTML =
'';
PrivateBin.Alert.init();
PrivateBin.Alert.showError(message, icon);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('shows an error message (bootstrap)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
function (message) {
message = message.join('');
const expected = '' + icon('exclamation-triangle') +
' ' + message + '
';
document.body.innerHTML =
'' + icon('exclamation-triangle') + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showError(message);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('shows an error message (bootstrap, custom icon)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
function (customIcon, message) {
customIcon = customIcon.join('');
message = message.join('');
const expected = '' +
icon(customIcon || 'exclamation-triangle') +
' ' + message + '
';
document.body.innerHTML =
'' + icon('exclamation-triangle') + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showError(message, customIcon);
const result = document.body.innerHTML;
return expected === result;
}
));
});
});
describe('showRemaining', function () {
it('shows remaining time (basic)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
fc.integer(),
function (message, string, number) {
message = message.join('');
string = string.join('');
const expected = '' + string + message + number + '
';
document.body.innerHTML =
'';
PrivateBin.Alert.init();
PrivateBin.Alert.showRemaining(['%s' + message + '%d', string, number]);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('shows remaining time (bootstrap)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
fc.integer(),
function (message, string, number) {
message = message.join('');
string = string.join('');
const expected = '' + icon('fire') +
' ' + string + message + number + '
';
document.body.innerHTML =
'' + icon('fire') + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showRemaining(['%s' + message + '%d', string, number]);
const result = document.body.innerHTML;
return expected === result;
}
));
});
});
describe('showLoading', function () {
it('shows a loading message (basic)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
function (message, icon) {
message = message.join('');
icon = icon.join('');
const defaultMessage = 'Loading…';
if (message.length === 0) {
message = defaultMessage;
}
const expected = '' + message + '
';
document.body.innerHTML =
'' + defaultMessage + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showLoading(message, icon);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('shows a loading message (bootstrap)', () => {
fc.assert(fc.property(
fc.array(common.fcAlnumString()),
fc.array(common.fcAlnumString()),
function (message, customIcon) {
message = message.join('');
customIcon = customIcon.join('');
const defaultMessage = 'Loading…';
if (message.length === 0) {
message = defaultMessage;
}
const expected = '- ' +
icon(customIcon || 'clock') + ' ' + message +
'
';
document.body.innerHTML =
'- ' + icon('clock') +
' ' + defaultMessage + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.showLoading(message, customIcon);
const result = document.body.innerHTML;
return expected === result;
}
));
});
it('keeps the previous icon, if none is given (bootstrap)', () => {
fc.assert(fc.property(
fc.constantFrom('clock', 'cloud-download', 'cloud-upload'),
fc.constantFrom(undefined, null, ''),
function (customIcon, noIcon) {
document.body.innerHTML =
'- ' + icon('clock') +
' Loading…
';
PrivateBin.Alert.init();
PrivateBin.Alert.showLoading('first', customIcon);
PrivateBin.Alert.hideLoading();
PrivateBin.Alert.showLoading('second', noIcon);
const use = document.querySelector('#loadingindicator use');
return use.getAttribute('href') === 'img/bootstrap-icons.svg#' + customIcon &&
document.querySelectorAll('#loadingindicator svg').length === 1 &&
document.querySelector('#loadingindicator span').textContent === 'second';
}
));
});
});
describe('hideLoading', function () {
it(
'hides the loading message',
function() {
document.body.innerHTML =
'- ' + icon('clock') +
' Loading…
';
document.body.classList.add('loading');
PrivateBin.Alert.init();
PrivateBin.Alert.hideLoading();
assert.ok(!document.body.classList.contains('loading'));
assert.ok(document.getElementById('loadingindicator').classList.contains('hidden'));
}
);
});
describe('hideMessages', function () {
it(
'hides all messages',
function() {
document.body.innerHTML =
'' +
icon('info-circle') + '
' +
'' + icon('exclamation-triangle') + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.hideMessages();
assert.ok(document.getElementById('status').classList.contains('hidden'));
assert.ok(document.getElementById('errormessage').classList.contains('hidden'));
}
);
});
describe('setCustomHandler', function () {
it('calls a given handler function', () => {
fc.assert(fc.property(
fc.integer({min: 0, max: 3}),
fc.array(common.fcAlnumString()),
function (trigger, message) {
message = message.join('');
let handlerCalled = false,
defaultMessage = 'Loading…',
functions = [
PrivateBin.Alert.showStatus,
PrivateBin.Alert.showError,
PrivateBin.Alert.showRemaining,
PrivateBin.Alert.showLoading
];
if (message.length === 0) {
message = defaultMessage;
}
document.body.innerHTML =
'- ' + icon('clock') +
' ' + defaultMessage + '
' +
'' + icon('fire') + '
' +
'' +
icon('info-circle') + '
' +
'' + icon('exclamation-triangle') + '
';
PrivateBin.Alert.init();
PrivateBin.Alert.setCustomHandler(function(id, element) {
handlerCalled = true;
return Math.random() > 0.5 ? true : element;
});
functions[trigger](message);
PrivateBin.Alert.setCustomHandler(null);
return handlerCalled;
}
));
});
});
describe('icons', function () {
it('only uses icons that exist in the icon sprite', function () {
const source = fs.readFileSync(path.join(__dirname, '..', 'privatebin.js'), 'utf8');
const sprite = fs.readFileSync(path.join(__dirname, '..', '..', 'img', 'bootstrap-icons.svg'), 'utf8');
const calls = source.match(/(Alert\.show(Status|Warning|Error|Loading)|Helper\.setIcon)\([^;]*\);/g);
assert.ok(calls.length > 0, 'found icon setting calls');
let names = [];
calls.forEach(function (call) {
// skip the first argument, the message or element
const icons = call.substring(call.indexOf(',')).match(/'[a-z][a-z0-9-]*'/g) || [];
names = names.concat(icons.map(name => name.slice(1, -1)));
});
assert.ok(names.length > 0, 'found icon names');
names.forEach(function (name) {
assert.ok(sprite.includes('id="' + name + '"'), 'icon ' + name + ' exists in sprite');
});
});
});
});