Merge branch 'js-unit-testing'

This commit is contained in:
El RIDO 2017-11-22 05:33:24 +01:00
commit e40da8b1a6
No known key found for this signature in database
GPG Key ID: 0F5C940A6BD81F92
10 changed files with 811 additions and 49 deletions

2
.gitattributes vendored
View File

@ -2,8 +2,6 @@ doc/ export-ignore
tst/ export-ignore tst/ export-ignore
js/.istanbul.yml export-ignore js/.istanbul.yml export-ignore
js/test.js export-ignore js/test.js export-ignore
js/mocha-3.2.0.js export-ignore
css/mocha-3.2.0.css export-ignore
.codeclimate.yml export-ignore .codeclimate.yml export-ignore
.csslintrc export-ignore .csslintrc export-ignore
.dockerignore export-ignore .dockerignore export-ignore

View File

@ -3,10 +3,11 @@ preset: recommended
risky: false risky: false
enabled: enabled:
- no_empty_comment
- align_equals - align_equals
- long_array_syntax
- concat_with_spaces - concat_with_spaces
- long_array_syntax
- no_empty_comment
- pre_increment
disabled: disabled:
- blank_line_after_opening_tag - blank_line_after_opening_tag
@ -23,6 +24,7 @@ disabled:
- phpdoc_separation - phpdoc_separation
- phpdoc_single_line_var_spacing - phpdoc_single_line_var_spacing
- phpdoc_summary - phpdoc_summary
- post_increment
- short_array_syntax - short_array_syntax
- single_line_after_imports - single_line_after_imports
- unalign_equals - unalign_equals

View File

@ -302,8 +302,6 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* internationalization module * internationalization module
* *
* @name I18n * @name I18n
* @param {object} window
* @param {object} document
* @class * @class
*/ */
var I18n = (function () { var I18n = (function () {
@ -414,7 +412,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
var orgArguments = arguments; var orgArguments = arguments;
$(document).on(languageLoadedEvent, function () { $(document).on(languageLoadedEvent, function () {
// log to show that the previous error could be mitigated // log to show that the previous error could be mitigated
console.log('Fix missing translation of \'' + messageId + '\' with now loaded language ' + language); console.warn('Fix missing translation of \'' + messageId + '\' with now loaded language ' + language);
// re-execute this function // re-execute this function
me.translate.apply(this, orgArguments); me.translate.apply(this, orgArguments);
}); });
@ -845,11 +843,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* everything directly UI-related, which fits nowhere else * everything directly UI-related, which fits nowhere else
* *
* @name UiHelper * @name UiHelper
* @param {object} window
* @param {object} document
* @class * @class
*/ */
var UiHelper = (function (window, document) { var UiHelper = (function () {
var me = {}; var me = {};
/** /**
@ -866,7 +862,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
{ {
var currentLocation = Helper.baseUri(); var currentLocation = Helper.baseUri();
if (event.originalEvent.state === null && // no state object passed if (event.originalEvent.state === null && // no state object passed
event.originalEvent.target.location.href === currentLocation && // target location is home page event.target.location.href === currentLocation && // target location is home page
window.location.href === currentLocation // and we are not already on the home page window.location.href === currentLocation // and we are not already on the home page
) { ) {
// redirect to home page // redirect to home page
@ -958,6 +954,23 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
}); });
} }
/**
* trigger a history (pop) state change
*
* used to test the UiHelper.historyChange private function
*
* @name UiHelper.mockHistoryChange
* @function
* @param {string} state (optional) state to mock
*/
me.mockHistoryChange = function(state)
{
if (typeof state === 'undefined') {
state = null;
}
historyChange($.Event('popstate', {originalEvent: new PopStateEvent('popstate', {state: state}), target: window}));
}
/** /**
* initialize * initialize
* *
@ -973,7 +986,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
} }
return me; return me;
})(window, document); })();
/** /**
* Alert/error manager * Alert/error manager
@ -989,12 +1002,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
$statusMessage, $statusMessage,
$remainingTime; $remainingTime;
var currentIcon = [ var currentIcon;
'glyphicon-time', // loading icon
'glyphicon-info-sign', // status icon
'', // resevered for warning, not used yet
'glyphicon-alert' // error icon
];
var alertType = [ var alertType = [
'loading', // not in bootstrap, but using a good value here 'loading', // not in bootstrap, but using a good value here
@ -1090,7 +1098,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
*/ */
me.showStatus = function(message, icon, dismissable, autoclose) me.showStatus = function(message, icon, dismissable, autoclose)
{ {
console.log('status shown: ', message); console.info('status shown: ', message);
// @TODO: implement dismissable // @TODO: implement dismissable
// @TODO: implement autoclose // @TODO: implement autoclose
@ -1133,7 +1141,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
*/ */
me.showRemaining = function(message) me.showRemaining = function(message)
{ {
console.log('remaining message shown: ', message); console.info('remaining message shown: ', message);
handleNotification(1, $remainingTime, message); handleNotification(1, $remainingTime, message);
} }
@ -1151,7 +1159,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
me.showLoading = function(message, percentage, icon) me.showLoading = function(message, percentage, icon)
{ {
if (typeof message !== 'undefined' && message !== null) { if (typeof message !== 'undefined' && message !== null) {
console.log('status changed: ', message); console.info('status changed: ', message);
} }
// default message text // default message text
@ -1238,6 +1246,13 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
$loadingIndicator = $('#loadingindicator'); $loadingIndicator = $('#loadingindicator');
$statusMessage = $('#status'); $statusMessage = $('#status');
$remainingTime = $('#remainingtime'); $remainingTime = $('#remainingtime');
currentIcon = [
'glyphicon-time', // loading icon
'glyphicon-info-sign', // status icon
'', // reserved for warning, not used yet
'glyphicon-alert' // error icon
];
} }
return me; return me;
@ -1247,10 +1262,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* handles paste status/result * handles paste status/result
* *
* @name PasteStatus * @name PasteStatus
* @param {object} window
* @class * @class
*/ */
var PasteStatus = (function (window) { var PasteStatus = (function () {
var me = {}; var me = {};
var $pasteSuccess, var $pasteSuccess,
@ -1351,7 +1365,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
]; ];
Alert.showRemaining([expirationLabel, expiration[0]]); Alert.showRemaining([expirationLabel, expiration[0]]);
$remainingTime.removeClass('foryoureyesonly') $remainingTime.removeClass('foryoureyesonly');
} else { } else {
// never expires // never expires
return; return;
@ -1383,7 +1397,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
*/ */
me.init = function() me.init = function()
{ {
$pasteSuccess = $('#pasteSuccess'); $pasteSuccess = $('#pastesuccess');
// $pasteUrl is saved in me.createPasteNotification() after creation // $pasteUrl is saved in me.createPasteNotification() after creation
$remainingTime = $('#remainingtime'); $remainingTime = $('#remainingtime');
$shortenButton = $('#shortenbutton'); $shortenButton = $('#shortenbutton');
@ -1393,7 +1407,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
} }
return me; return me;
})(window); })();
/** /**
* password prompt * password prompt
@ -1454,7 +1468,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
throw 'password prompt canceled'; throw 'password prompt canceled';
} }
if (password.length === 0) { if (password.length === 0) {
// recursive… // recurse…
return me.requestPassword(); return me.requestPassword();
} }
@ -1825,7 +1839,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* *
* @name PasteViewer.setFormat * @name PasteViewer.setFormat
* @function * @function
* @param {string} newFormat the the new format * @param {string} newFormat the new format
*/ */
me.setFormat = function(newFormat) me.setFormat = function(newFormat)
{ {
@ -1834,7 +1848,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
return; return;
} }
// needs to update display too, if from or to Markdown is switched // needs to update display too, if we switch from or to Markdown
if (format === 'markdown' || newFormat === 'markdown') { if (format === 'markdown' || newFormat === 'markdown') {
isDisplayed = false; isDisplayed = false;
} }
@ -1963,6 +1977,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
// get default option from template/HTML or fall back to set value // get default option from template/HTML or fall back to set value
format = Model.getFormatDefault() || format; format = Model.getFormatDefault() || format;
text = '';
isDisplayed = false;
isChanged = true;
} }
return me; return me;
@ -2639,7 +2656,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
me.showViewButtons = function() me.showViewButtons = function()
{ {
if (viewButtonsDisplayed) { if (viewButtonsDisplayed) {
console.log('showViewButtons: view buttons are already displayed'); console.warn('showViewButtons: view buttons are already displayed');
return; return;
} }
@ -2659,7 +2676,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
me.hideViewButtons = function() me.hideViewButtons = function()
{ {
if (!viewButtonsDisplayed) { if (!viewButtonsDisplayed) {
console.log('hideViewButtons: view buttons are already hidden'); console.warn('hideViewButtons: view buttons are already hidden');
return; return;
} }
@ -2691,7 +2708,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
me.showCreateButtons = function() me.showCreateButtons = function()
{ {
if (createButtonsDisplayed) { if (createButtonsDisplayed) {
console.log('showCreateButtons: create buttons are already displayed'); console.warn('showCreateButtons: create buttons are already displayed');
return; return;
} }
@ -2716,7 +2733,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
me.hideCreateButtons = function() me.hideCreateButtons = function()
{ {
if (!createButtonsDisplayed) { if (!createButtonsDisplayed) {
console.log('hideCreateButtons: create buttons are already hidden'); console.warn('hideCreateButtons: create buttons are already hidden');
return; return;
} }
@ -3968,7 +3985,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
Uploader.setUnencryptedData('deletetoken', deleteToken); Uploader.setUnencryptedData('deletetoken', deleteToken);
Uploader.setFailure(function () { Uploader.setFailure(function () {
Controller.showError(I18n._('Could not delete the paste, it was not stored in burn after reading mode.')); Alert.showError(I18n._('Could not delete the paste, it was not stored in burn after reading mode.'));
}) })
Uploader.run(); Uploader.run();
} }

View File

@ -22,11 +22,16 @@ global.sjcl = require('./sjcl-1.0.6');
global.Base64 = require('./base64-2.1.9').Base64; global.Base64 = require('./base64-2.1.9').Base64;
global.RawDeflate = require('./rawdeflate-0.5').RawDeflate; global.RawDeflate = require('./rawdeflate-0.5').RawDeflate;
global.RawDeflate.inflate = require('./rawinflate-0.3').RawDeflate.inflate; global.RawDeflate.inflate = require('./rawinflate-0.3').RawDeflate.inflate;
require('./prettify');
global.prettyPrint = window.PR.prettyPrint;
global.prettyPrintOne = window.PR.prettyPrintOne;
global.showdown = require('./showdown-1.6.1');
require('./bootstrap-3.3.7');
require('./privatebin'); require('./privatebin');
// redirect console messages to log file // redirect console messages to log file
console.warn = console.error = function (msg) { console.info = console.warn = console.error = function () {
logFile.write(msg + '\n'); logFile.write(Array.prototype.slice.call(arguments).join('') + '\n');
} }
describe('Helper', function () { describe('Helper', function () {
@ -182,7 +187,7 @@ describe('Helper', function () {
jsc.array(jsc.elements(queryString)), jsc.array(jsc.elements(queryString)),
'string', 'string',
function (prefix, query, postfix) { function (prefix, query, postfix) {
var url = 'magnet:?' + query.join(''), var url = 'magnet:?' + query.join('').replace(/^&+|&+$/gm,''),
prefix = $.PrivateBin.Helper.htmlEntities(prefix), prefix = $.PrivateBin.Helper.htmlEntities(prefix),
postfix = $.PrivateBin.Helper.htmlEntities(postfix), postfix = $.PrivateBin.Helper.htmlEntities(postfix),
element = $('<div>' + prefix + url + ' ' + postfix + '</div>'); element = $('<div>' + prefix + url + ' ' + postfix + '</div>');
@ -599,6 +604,82 @@ describe('Model', function () {
); );
}); });
describe('getFormatDefault', function () {
before(function () {
$.PrivateBin.Model.reset();
cleanup();
});
jsc.property(
'returns the contents of the element with id "pasteFormatter"',
'array asciinestring',
'string',
'small nat',
function (keys, value, key) {
keys = keys.map($.PrivateBin.Helper.htmlEntities);
value = $.PrivateBin.Helper.htmlEntities(value);
var content = keys.length > key ? keys[key] : (keys.length > 0 ? keys[0] : 'null'),
contents = '<select id="pasteFormatter" name="pasteFormatter">';
keys.forEach(function(item) {
contents += '<option value="' + item + '"';
if (item === content) {
contents += ' selected="selected"';
}
contents += '>' + value + '</option>';
});
contents += '</select>';
$('body').html(contents);
var result = $.PrivateBin.Helper.htmlEntities(
$.PrivateBin.Model.getFormatDefault()
);
$.PrivateBin.Model.reset();
return content === result;
}
);
});
describe('hasCipherData', function () {
before(function () {
$.PrivateBin.Model.reset();
cleanup();
});
jsc.property(
'checks if the element with id "cipherdata" contains any data',
'asciistring',
function (value) {
value = $.PrivateBin.Helper.htmlEntities(value).trim();
$('body').html('<div id="cipherdata">' + value + '</div>');
$.PrivateBin.Model.init();
var result = $.PrivateBin.Model.hasCipherData();
$.PrivateBin.Model.reset();
return (value.length > 0) === result;
}
);
});
describe('getCipherData', function () {
before(function () {
$.PrivateBin.Model.reset();
cleanup();
});
jsc.property(
'returns the contents of the element with id "cipherdata"',
'asciistring',
function (value) {
value = $.PrivateBin.Helper.htmlEntities(value).trim();
$('body').html('<div id="cipherdata">' + value + '</div>');
$.PrivateBin.Model.init();
var result = $.PrivateBin.Helper.htmlEntities(
$.PrivateBin.Model.getCipherData()
);
$.PrivateBin.Model.reset();
return value === result;
}
);
});
describe('getPasteId', function () { describe('getPasteId', function () {
this.timeout(30000); this.timeout(30000);
before(function () { before(function () {
@ -710,4 +791,657 @@ describe('Model', function () {
} }
); );
}); });
describe('getTemplate', function () {
before(function () {
$.PrivateBin.Model.reset();
cleanup();
}); });
jsc.property(
'returns the contents of the element with id "[name]template"',
jsc.nearray(jsc.elements(alnumString)),
jsc.nearray(jsc.elements(a2zString)),
jsc.nearray(jsc.elements(alnumString)),
function (id, element, value) {
id = id.join('');
element = element.join('');
value = value.join('').trim();
// <br>, <hr>, <img> and <wbr> tags can't contain strings,
// table tags can't be alone, so test with a <p> instead
if (['br', 'col', 'hr', 'img', 'tr', 'td', 'th', 'wbr'].indexOf(element) >= 0) {
element = 'p';
}
$('body').html(
'<div id="templates"><' + element + ' id="' + id +
'template">' + value + '</' + element + '></div>'
);
$.PrivateBin.Model.init();
var template = '<' + element + ' id="' + id + '">' + value +
'</' + element + '>',
result = $.PrivateBin.Model.getTemplate(id).wrap('<p/>').parent().html();
$.PrivateBin.Model.reset();
return template === result;
}
);
});
});
describe('UiHelper', function () {
// TODO: As per https://github.com/tmpvar/jsdom/issues/1565 there is no navigation support in jsdom, yet.
// for now we use a mock function to trigger the event
describe('historyChange', function () {
this.timeout(30000);
before(function () {
$.PrivateBin.Helper.reset();
});
jsc.property(
'redirects to home, when the state is null',
jsc.elements(schemas),
jsc.nearray(jsc.elements(a2zString)),
function (schema, address) {
var expected = schema + '://' + address.join('') + '/',
clean = jsdom('', {url: expected});
// make window.location.href writable
Object.defineProperty(window.location, 'href', {
writable: true,
value: window.location.href
});
$.PrivateBin.UiHelper.mockHistoryChange();
$.PrivateBin.Helper.reset();
var result = window.location.href;
clean();
return expected === result;
}
);
jsc.property(
'does not redirect to home, when a new paste is created',
jsc.elements(schemas),
jsc.nearray(jsc.elements(a2zString)),
jsc.array(jsc.elements(queryString)),
jsc.nearray(jsc.elements(base64String)),
function (schema, address, query, fragment) {
var expected = schema + '://' + address.join('') + '/' + '?' +
query.join('') + '#' + fragment.join(''),
clean = jsdom('', {url: expected});
// make window.location.href writable
Object.defineProperty(window.location, 'href', {
writable: true,
value: window.location.href
});
$.PrivateBin.UiHelper.mockHistoryChange([
{type: 'newpaste'}, '', expected
]);
$.PrivateBin.Helper.reset();
var result = window.location.href;
clean();
return expected === result;
}
);
});
describe('reloadHome', function () {
this.timeout(30000);
before(function () {
$.PrivateBin.Helper.reset();
});
jsc.property(
'redirects to home',
jsc.elements(schemas),
jsc.nearray(jsc.elements(a2zString)),
jsc.array(jsc.elements(queryString)),
jsc.nearray(jsc.elements(base64String)),
function (schema, address, query, fragment) {
var expected = schema + '://' + address.join('') + '/',
clean = jsdom('', {
url: expected + '?' + query.join('') + '#' + fragment.join('')
});
// make window.location.href writable
Object.defineProperty(window.location, 'href', {
writable: true,
value: window.location.href
});
$.PrivateBin.UiHelper.reloadHome();
$.PrivateBin.Helper.reset();
var result = window.location.href;
clean();
return expected === result;
}
);
});
describe('isVisible', function () {
// TODO As per https://github.com/tmpvar/jsdom/issues/1048 there is no layout support in jsdom, yet.
// once it is supported or a workaround is found, uncomment the section below
/*
before(function () {
$.PrivateBin.Helper.reset();
});
jsc.property(
'detect visible elements',
jsc.nearray(jsc.elements(alnumString)),
jsc.nearray(jsc.elements(a2zString)),
function (id, element) {
id = id.join('');
element = element.join('');
var clean = jsdom(
'<' + element + ' id="' + id + '"></' + element + '>'
);
var result = $.PrivateBin.UiHelper.isVisible($('#' + id));
clean();
return result;
}
);
*/
});
describe('scrollTo', function () {
// TODO Did not find a way to test that, see isVisible test above
});
});
describe('Alert', function () {
describe('showStatus', function () {
before(function () {
cleanup();
});
jsc.property(
'shows a status message',
jsc.array(jsc.elements(alnumString)),
jsc.array(jsc.elements(alnumString)),
function (icon, message) {
icon = icon.join('');
message = message.join('');
var expected = '<div id="status" role="alert" ' +
'class="statusmessage alert alert-info"><span ' +
'class="glyphicon glyphicon-' + icon +
'" aria-hidden="true"></span> ' + message + '</div>';
$('body').html(
'<div id="status" role="alert" class="statusmessage ' +
'alert alert-info hidden"><span class="glyphicon ' +
'glyphicon-info-sign" aria-hidden="true"></span> </div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showStatus(message, icon);
var result = $('body').html();
return expected === result;
}
);
});
describe('showError', function () {
before(function () {
cleanup();
});
jsc.property(
'shows an error message',
jsc.array(jsc.elements(alnumString)),
jsc.array(jsc.elements(alnumString)),
function (icon, message) {
icon = icon.join('');
message = message.join('');
var expected = '<div id="errormessage" role="alert" ' +
'class="statusmessage alert alert-danger"><span ' +
'class="glyphicon glyphicon-' + icon +
'" aria-hidden="true"></span> ' + message + '</div>';
$('body').html(
'<div id="errormessage" role="alert" class="statusmessage ' +
'alert alert-danger hidden"><span class="glyphicon ' +
'glyphicon-alert" aria-hidden="true"></span> </div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showError(message, icon);
var result = $('body').html();
return expected === result;
}
);
});
describe('showRemaining', function () {
before(function () {
cleanup();
});
jsc.property(
'shows remaining time',
jsc.array(jsc.elements(alnumString)),
jsc.array(jsc.elements(alnumString)),
'integer',
function (message, string, number) {
message = message.join('');
string = string.join('');
var expected = '<div id="remainingtime" role="alert" ' +
'class="alert alert-info"><span ' +
'class="glyphicon glyphicon-fire" aria-hidden="true">' +
'</span> ' + string + message + number + '</div>';
$('body').html(
'<div id="remainingtime" role="alert" class="hidden ' +
'alert alert-info"><span class="glyphicon ' +
'glyphicon-fire" aria-hidden="true"></span> </div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showRemaining(['%s' + message + '%d', string, number]);
var result = $('body').html();
return expected === result;
}
);
});
describe('showLoading', function () {
before(function () {
cleanup();
});
jsc.property(
'shows a loading message',
jsc.array(jsc.elements(alnumString)),
jsc.array(jsc.elements(alnumString)),
'integer',
function (icon, message, number) {
icon = icon.join('');
message = message.join('');
var default_message = 'Loading…';
if (message.length == 0) {
message = default_message;
}
var expected = '<ul class="nav navbar-nav"><li ' +
'id="loadingindicator" class="navbar-text"><span ' +
'class="glyphicon glyphicon-' + icon +
'" aria-hidden="true"></span> ' + message + '</li></ul>';
$('body').html(
'<ul class="nav navbar-nav"><li id="loadingindicator" ' +
'class="navbar-text hidden"><span class="glyphicon ' +
'glyphicon-time" aria-hidden="true"></span> ' +
default_message + '</li></ul>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showLoading(message, number, icon);
var result = $('body').html();
return expected === result;
}
);
});
describe('hideLoading', function () {
before(function () {
cleanup();
});
it(
'hides the loading message',
function() {
$('body').html(
'<ul class="nav navbar-nav"><li id="loadingindicator" ' +
'class="navbar-text"><span class="glyphicon ' +
'glyphicon-time" aria-hidden="true"></span> ' +
'Loading…</li></ul>'
);
$('body').addClass('loading');
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.hideLoading();
return !$('body').hasClass('loading') &&
$('#loadingindicator').hasClass('hidden');
}
);
});
describe('hideMessages', function () {
before(function () {
cleanup();
});
it(
'hides all messages',
function() {
$('body').html(
'<div id="status" role="alert" class="statusmessage ' +
'alert alert-info"><span class="glyphicon ' +
'glyphicon-info-sign" aria-hidden="true"></span> </div>' +
'<div id="errormessage" role="alert" class="statusmessage ' +
'alert alert-danger"><span class="glyphicon ' +
'glyphicon-alert" aria-hidden="true"></span> </div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.hideMessages();
return $('#statusmessage').hasClass('hidden') &&
$('#errormessage').hasClass('hidden');
}
);
});
describe('setCustomHandler', function () {
before(function () {
cleanup();
});
jsc.property(
'calls a given handler function',
'nat 3',
jsc.array(jsc.elements(alnumString)),
function (trigger, message) {
message = message.join('');
var handlerCalled = false,
default_message = 'Loading…',
functions = [
$.PrivateBin.Alert.showStatus,
$.PrivateBin.Alert.showError,
$.PrivateBin.Alert.showRemaining,
$.PrivateBin.Alert.showLoading
];
if (message.length == 0) {
message = default_message;
}
$('body').html(
'<ul class="nav navbar-nav"><li id="loadingindicator" ' +
'class="navbar-text hidden"><span class="glyphicon ' +
'glyphicon-time" aria-hidden="true"></span> ' +
default_message + '</li></ul>' +
'<div id="remainingtime" role="alert" class="hidden ' +
'alert alert-info"><span class="glyphicon ' +
'glyphicon-fire" aria-hidden="true"></span> </div>' +
'<div id="status" role="alert" class="statusmessage ' +
'alert alert-info"><span class="glyphicon ' +
'glyphicon-info-sign" aria-hidden="true"></span> </div>' +
'<div id="errormessage" role="alert" class="statusmessage ' +
'alert alert-danger"><span class="glyphicon ' +
'glyphicon-alert" aria-hidden="true"></span> </div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.setCustomHandler(function(id, $element) {
handlerCalled = true;
return jsc.random(0, 1) ? true : $element;
});
functions[trigger](message);
return handlerCalled;
}
);
});
});
describe('PasteStatus', function () {
describe('createPasteNotification', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'creates a notification after a successfull paste upload',
jsc.elements(schemas),
jsc.nearray(jsc.elements(a2zString)),
jsc.array(jsc.elements(queryString)),
'string',
jsc.elements(schemas),
jsc.nearray(jsc.elements(a2zString)),
jsc.array(jsc.elements(queryString)),
function (
schema1, address1, query1, fragment1,
schema2, address2, query2
) {
var expected1 = schema1 + '://' + address1.join('') + '/?' +
encodeURI(query1.join('').replace(/^&+|&+$/gm,'') + '#' + fragment1),
expected2 = schema2 + '://' + address2.join('') + '/?' +
encodeURI(query2.join('')),
clean = jsdom();
$('body').html('<div><div id="deletelink"></div><div id="pastelink"></div></div>');
$.PrivateBin.PasteStatus.init();
$.PrivateBin.PasteStatus.createPasteNotification(expected1, expected2);
var result1 = $('#pasteurl')[0].href,
result2 = $('#deletelink a')[0].href;
clean();
return result1 == expected1 && result2 == expected2;
}
);
});
describe('showRemainingTime', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'shows burn after reading message or remaining time',
'bool',
'nat',
jsc.nearray(jsc.elements(a2zString)),
jsc.nearray(jsc.elements(a2zString)),
jsc.array(jsc.elements(queryString)),
'string',
function (
burnafterreading, remaining_time,
schema, address, query, fragment
) {
var clean = jsdom('', {
url: schema.join('') + '://' + address.join('') +
'/?' + queryString + '#' + fragment
});
$('body').html('<div id="remainingtime" class="hidden"></div>');
$.PrivateBin.PasteStatus.init();
$.PrivateBin.PasteStatus.showRemainingTime({
'burnafterreading': burnafterreading,
'remaining_time': remaining_time,
'expire_date': remaining_time ? ((new Date()).getTime() / 1000) + remaining_time : 0
});
if (burnafterreading) {
var result = $('#remainingtime').hasClass('foryoureyesonly') &&
!$('#remainingtime').hasClass('hidden');
} else if (remaining_time) {
var result =!$('#remainingtime').hasClass('foryoureyesonly') &&
!$('#remainingtime').hasClass('hidden');
} else {
var result = $('#remainingtime').hasClass('hidden') &&
!$('#remainingtime').hasClass('foryoureyesonly');
}
clean();
return result;
}
);
});
describe('hideMessages', function () {
before(function () {
cleanup();
});
it(
'hides all messages',
function() {
$('body').html(
'<div id="remainingtime"></div><div id="pastesuccess"></div>'
);
$.PrivateBin.PasteStatus.init();
$.PrivateBin.PasteStatus.hideMessages();
return $('#remainingtime').hasClass('hidden') &&
$('#pastesuccess').hasClass('hidden');
}
);
});
});
describe('Prompt', function () {
// TODO: this does not test the prompt() fallback, since that isn't available
// in nodejs -> replace the prompt in the "page" template with a modal
describe('requestPassword & getPassword', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'returns the password fed into the dialog',
'string',
function (password) {
password = password.replace(/\r+/g, '');
var clean = jsdom('', {url: 'ftp://example.com/#0'});
$('body').html(
'<div id="passwordmodal" class="modal fade" role="dialog">' +
'<div class="modal-dialog"><div class="modal-content">' +
'<div class="modal-body"><form id="passwordform" role="form">' +
'<div class="form-group"><input id="passworddecrypt" ' +
'type="password" class="form-control" placeholder="Enter ' +
'password"></div><button type="submit">Decrypt</button>' +
'</form></div></div></div></div><div id="cipherdata">{}</div>'
);
$.PrivateBin.Model.init();
$.PrivateBin.Prompt.init();
$.PrivateBin.Prompt.requestPassword();
$('#passworddecrypt').val(password);
$('#passwordform').submit();
var result = $.PrivateBin.Prompt.getPassword();
clean();
return result == password;
}
);
});
});
describe('Editor', function () {
describe('show, hide, getText, setText & isPreview', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'returns text fed into the textarea, handles editor tabs',
'string',
function (text) {
var clean = jsdom(),
results = [];
$('body').html(
'<ul id="editorTabs" class="nav nav-tabs hidden"><li ' +
'role="presentation" class="active"><a id="messageedit" ' +
'href="#">Editor</a></li><li role="presentation"><a ' +
'id="messagepreview" href="#">Preview</a></li></ul><div ' +
'id="placeholder" class="hidden">+++ no paste text +++</div>' +
'<div id="prettymessage" class="hidden"><pre id="prettyprint" ' +
'class="prettyprint linenums:1"></pre></div><div ' +
'id="plaintext" class="hidden"></div><p><textarea ' +
'id="message" name="message" cols="80" rows="25" ' +
'class="form-control hidden"></textarea></p>'
);
$.PrivateBin.Editor.init();
results.push(
$('#editorTabs').hasClass('hidden') &&
$('#message').hasClass('hidden')
);
$.PrivateBin.Editor.show();
results.push(
!$('#editorTabs').hasClass('hidden') &&
!$('#message').hasClass('hidden')
);
$.PrivateBin.Editor.hide();
results.push(
$('#editorTabs').hasClass('hidden') &&
$('#message').hasClass('hidden')
);
$.PrivateBin.Editor.show();
$.PrivateBin.Editor.focusInput();
results.push(
$.PrivateBin.Editor.getText().length == 0
);
$.PrivateBin.Editor.setText(text);
results.push(
$.PrivateBin.Editor.getText() == $('#message').val()
);
$.PrivateBin.Editor.setText();
results.push(
!$.PrivateBin.Editor.isPreview() &&
!$('#message').hasClass('hidden')
);
$('#messagepreview').click();
results.push(
$.PrivateBin.Editor.isPreview() &&
$('#message').hasClass('hidden')
);
$('#messageedit').click();
results.push(
!$.PrivateBin.Editor.isPreview() &&
!$('#message').hasClass('hidden')
);
clean();
return results.every(element => element);
}
);
});
});
describe('PasteViewer', function () {
describe('run, hide, getText, setText, getFormat, setFormat & isPrettyPrinted', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'displays text according to format',
jsc.elements(['plaintext', 'markdown', 'syntaxhighlighting']),
'nestring',
function (format, text) {
var clean = jsdom(),
results = [];
$('body').html(
'<div id="placeholder" class="hidden">+++ no paste text ' +
'+++</div><div id="prettymessage" class="hidden"><pre ' +
'id="prettyprint" class="prettyprint linenums:1"></pre>' +
'</div><div id="plaintext" class="hidden"></div>'
);
$.PrivateBin.PasteViewer.init();
$.PrivateBin.PasteViewer.setFormat(format);
$.PrivateBin.PasteViewer.setText('');
results.push(
$('#placeholder').hasClass('hidden') &&
$('#prettymessage').hasClass('hidden') &&
$('#plaintext').hasClass('hidden') &&
$.PrivateBin.PasteViewer.getFormat() == format &&
$.PrivateBin.PasteViewer.getText() == ''
);
$.PrivateBin.PasteViewer.run();
results.push(
!$('#placeholder').hasClass('hidden') &&
$('#prettymessage').hasClass('hidden') &&
$('#plaintext').hasClass('hidden')
);
$.PrivateBin.PasteViewer.hide();
results.push(
$('#placeholder').hasClass('hidden') &&
$('#prettymessage').hasClass('hidden') &&
$('#plaintext').hasClass('hidden')
);
$.PrivateBin.PasteViewer.setText(text);
$.PrivateBin.PasteViewer.run();
results.push(
$('#placeholder').hasClass('hidden') &&
!$.PrivateBin.PasteViewer.isPrettyPrinted() &&
$.PrivateBin.PasteViewer.getText() == text
);
if (format == 'markdown') {
results.push(
$('#prettymessage').hasClass('hidden') &&
!$('#plaintext').hasClass('hidden')
);
} else {
results.push(
!$('#prettymessage').hasClass('hidden') &&
$('#plaintext').hasClass('hidden')
);
}
clean();
return results.every(element => element);
}
);
});
});

View File

@ -64,7 +64,7 @@ class Filter
$i = 0; $i = 0;
while (($size / 1024) >= 1) { while (($size / 1024) >= 1) {
$size = $size / 1024; $size = $size / 1024;
$i++; ++$i;
} }
return number_format($size, ($i ? 2 : 0), '.', ' ') . ' ' . I18n::_($iec[$i]); return number_format($size, ($i ? 2 : 0), '.', ' ') . ' ' . I18n::_($iec[$i]);
} }
@ -82,7 +82,7 @@ class Filter
public static function slowEquals($a, $b) public static function slowEquals($a, $b)
{ {
$diff = strlen($a) ^ strlen($b); $diff = strlen($a) ^ strlen($b);
for ($i = 0; $i < strlen($a) && $i < strlen($b); $i++) { for ($i = 0; $i < strlen($a) && $i < strlen($b); ++$i) {
$diff |= ord($a[$i]) ^ ord($b[$i]); $diff |= ord($a[$i]) ^ ord($b[$i]);
} }
return $diff === 0; return $diff === 0;

View File

@ -69,7 +69,7 @@ if ($MARKDOWN):
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-gTAGAlxWTLH1PaXA4q9l0kME8wPPWi2iub5uU7HZ3A2bisLtjMIsaZ/Ecu4+sawFvvedAzbh9Y4rR34Ct3oF5Q==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-NWkO7YojpZyTn/xpIjVwo+VBSVKIfxHjE9NC41GzcWgt3w36XNZ+wYZZjXLJh44rBj9qBmZiXvvt9g5iNkadlg==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->
@ -230,6 +230,17 @@ if ($isCpct):
?> ?>
</ul> </ul>
<select id="pasteFormatter" name="pasteFormatter" class="hidden"> <select id="pasteFormatter" name="pasteFormatter" class="hidden">
<?php
foreach ($FORMATTER as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $FORMATTERDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
<?php
endforeach;
?>
</select> </select>
</li> </li>
<?php <?php
@ -423,7 +434,7 @@ endif;
<a href="https://www.opera.com/">Opera</a>, <a href="https://www.opera.com/">Opera</a>,
<a href="https://www.google.com/chrome">Chrome</a> <a href="https://www.google.com/chrome">Chrome</a>
</div> </div>
<div id="pasteSuccess" role="alert" class="hidden alert alert-success"> <div id="pastesuccess" role="alert" class="hidden alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
<div id="deletelink"></div> <div id="deletelink"></div>
<div id="pastelink"> <div id="pastelink">

View File

@ -47,7 +47,7 @@ if ($MARKDOWN):
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-gTAGAlxWTLH1PaXA4q9l0kME8wPPWi2iub5uU7HZ3A2bisLtjMIsaZ/Ecu4+sawFvvedAzbh9Y4rR34Ct3oF5Q==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-NWkO7YojpZyTn/xpIjVwo+VBSVKIfxHjE9NC41GzcWgt3w36XNZ+wYZZjXLJh44rBj9qBmZiXvvt9g5iNkadlg==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->
@ -184,7 +184,7 @@ if (strlen($LANGUAGESELECTION)):
endif; endif;
?> ?>
</div> </div>
<div id="pasteresult" class="hidden"> <div id="pastesuccess" class="hidden">
<div id="deletelink"></div> <div id="deletelink"></div>
<div id="pastelink"> <div id="pastelink">
<?php <?php