ensuring internal variables of common module are not changed by providing getter functions, splitting out I18n tests

This commit is contained in:
El RIDO 2017-12-14 07:19:05 +01:00
parent dfd906900b
commit 3fed63ce28
No known key found for this signature in database
GPG key ID: 0F5C940A6BD81F92
3 changed files with 174 additions and 42 deletions

View file

@ -1,43 +1,12 @@
'use strict'; 'use strict';
exports.a2zString = ['a','b','c','d','e','f','g','h','i','j','k','l','m', // testing prerequisites
'n','o','p','q','r','s','t','u','v','w','x','y','z'];
exports.alnumString = exports.a2zString.concat(['0','1','2','3','4','5','6','7','8','9']);
exports.queryString = exports.alnumString.concat(['+','%','&','.','*','-','_']);
exports.base64String = exports.alnumString.concat(['+','/','=']).concat(
exports.a2zString.map(function(c) {
return c.toUpperCase();
})
);
// schemas supported by the whatwg-url library
exports.schemas = ['ftp','gopher','http','https','ws','wss'];
exports.supportedLanguages = ['de', 'es', 'fr', 'it', 'no', 'pl', 'pt', 'oc', 'ru', 'sl', 'zh'];
exports.mimeTypes = ['image/png', 'application/octet-stream'];
global.jsc = require('jsverify'); global.jsc = require('jsverify');
global.jsdom = require('jsdom-global'); global.jsdom = require('jsdom-global');
global.cleanup = global.jsdom(); global.cleanup = global.jsdom();
global.fs = require('fs'); global.fs = require('fs');
/** // application libraries to test
* character to HTML entity lookup table
*
* @see {@link https://github.com/janl/mustache.js/blob/master/mustache.js#L60}
*/
var entityMap = {
'&': '&',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;',
'`': '&#x60;',
'=': '&#x3D;'
},
logFile = fs.createWriteStream('test.log'),
mimeFile = fs.createReadStream('/etc/mime.types'),
mimeLine = '';
global.$ = global.jQuery = require('./jquery-3.1.1'); global.$ = global.jQuery = require('./jquery-3.1.1');
global.sjcl = require('./sjcl-1.0.6'); global.sjcl = require('./sjcl-1.0.6');
global.Base64 = require('./base64-2.1.9').Base64; global.Base64 = require('./base64-2.1.9').Base64;
@ -51,6 +20,38 @@ global.DOMPurify = require('./purify.min');
require('./bootstrap-3.3.7'); require('./bootstrap-3.3.7');
require('./privatebin'); require('./privatebin');
// internal variables
var a2zString = ['a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z'],
alnumString = a2zString.concat(['0','1','2','3','4','5','6','7','8','9']),
queryString = alnumString.concat(['+','%','&','.','*','-','_']),
base64String = alnumString.concat(['+','/','=']).concat(
a2zString.map(function(c) {
return c.toUpperCase();
})
),
schemas = ['ftp','gopher','http','https','ws','wss'],
supportedLanguages = ['de', 'es', 'fr', 'it', 'no', 'pl', 'pt', 'oc', 'ru', 'sl', 'zh'],
mimeTypes = ['image/png', 'application/octet-stream'],
/**
* character to HTML entity lookup table
*
* @see {@link https://github.com/janl/mustache.js/blob/master/mustache.js#L60}
*/
entityMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;',
'`': '&#x60;',
'=': '&#x3D;'
},
logFile = fs.createWriteStream('test.log'),
mimeFile = fs.createReadStream('/etc/mime.types'),
mimeLine = '';
// redirect console messages to log file // redirect console messages to log file
console.info = console.warn = console.error = function () { console.info = console.warn = console.error = function () {
logFile.write(Array.prototype.slice.call(arguments).join('') + '\n'); logFile.write(Array.prototype.slice.call(arguments).join('') + '\n');
@ -87,10 +88,12 @@ function parseMime(line) {
line = line.substring(0, index); line = line.substring(0, index);
} }
if (line.length > 0) { if (line.length > 0) {
exports.mimeTypes.push(line); mimeTypes.push(line);
} }
} }
// common testing helper functions
/** /**
* convert all applicable characters to HTML entities * convert all applicable characters to HTML entities
* *
@ -107,3 +110,28 @@ exports.htmlEntities = function(str) {
}); });
} }
// provides random lowercase characters from a to z
exports.jscA2zString = function() {
return jsc.elements(a2zString);
}
// provides random lowercase alpha numeric characters (a to z and 0 to 9)
exports.jscAlnumString = function() {
return jsc.elements(alnumString);
}
// provides random characters allowed in GET queries
exports.jscQueryString = function() {
return jsc.elements(queryString);
}
// provides a random URL schema supported by the whatwg-url library
exports.jscSchemas = function() {
return jsc.elements(schemas);
}
// provides a random supported language string
exports.jscSupportedLanguages = function() {
return jsc.elements(supportedLanguages);
}

View file

@ -53,7 +53,7 @@ describe('Helper', function () {
this.timeout(30000); this.timeout(30000);
jsc.property( jsc.property(
'selection contains content of given ID', 'selection contains content of given ID',
jsc.nearray(jsc.nearray(jsc.elements(common.alnumString))), jsc.nearray(jsc.nearray(common.jscAlnumString())),
'nearray string', 'nearray string',
function (ids, contents) { function (ids, contents) {
var html = '', var html = '',
@ -90,9 +90,9 @@ describe('Helper', function () {
'replaces URLs with anchors', 'replaces URLs with anchors',
'string', 'string',
jsc.elements(['http', 'https', 'ftp']), jsc.elements(['http', 'https', 'ftp']),
jsc.nearray(jsc.elements(common.a2zString)), jsc.nearray(common.jscA2zString()),
jsc.array(jsc.elements(common.queryString)), jsc.array(common.jscQueryString()),
jsc.array(jsc.elements(common.queryString)), jsc.array(common.jscQueryString()),
'string', 'string',
function (prefix, schema, address, query, fragment, postfix) { function (prefix, schema, address, query, fragment, postfix) {
var query = query.join(''), var query = query.join(''),
@ -117,7 +117,7 @@ describe('Helper', function () {
jsc.property( jsc.property(
'replaces magnet links with anchors', 'replaces magnet links with anchors',
'string', 'string',
jsc.array(jsc.elements(common.queryString)), jsc.array(common.jscQueryString()),
'string', 'string',
function (prefix, query, postfix) { function (prefix, query, postfix) {
var url = 'magnet:?' + query.join('').replace(/^&+|&+$/gm,''), var url = 'magnet:?' + query.join('').replace(/^&+|&+$/gm,''),
@ -244,9 +244,9 @@ describe('Helper', function () {
jsc.property( jsc.property(
'returns the URL without query & fragment', 'returns the URL without query & fragment',
jsc.elements(common.schemas), common.jscSchemas(),
jsc.nearray(jsc.elements(common.a2zString)), jsc.nearray(common.jscA2zString()),
jsc.array(jsc.elements(common.queryString)), jsc.array(common.jscQueryString()),
'string', 'string',
function (schema, address, query, fragment) { function (schema, address, query, fragment) {
var expected = schema + '://' + address.join('') + '/', var expected = schema + '://' + address.join('') + '/',

104
js/test/I18n.js Normal file
View file

@ -0,0 +1,104 @@
'use strict';
var common = require('../common');
describe('I18n', function () {
describe('translate', function () {
before(function () {
$.PrivateBin.I18n.reset();
});
jsc.property(
'returns message ID unchanged if no translation found',
'string',
function (messageId) {
messageId = messageId.replace(/%(s|d)/g, '%%');
var plurals = [messageId, messageId + 's'],
fake = [messageId],
result = $.PrivateBin.I18n.translate(messageId);
$.PrivateBin.I18n.reset();
var alias = $.PrivateBin.I18n._(messageId);
$.PrivateBin.I18n.reset();
var p_result = $.PrivateBin.I18n.translate(plurals);
$.PrivateBin.I18n.reset();
var p_alias = $.PrivateBin.I18n._(plurals);
$.PrivateBin.I18n.reset();
var f_result = $.PrivateBin.I18n.translate(fake);
$.PrivateBin.I18n.reset();
var f_alias = $.PrivateBin.I18n._(fake);
$.PrivateBin.I18n.reset();
return messageId === result && messageId === alias &&
messageId === p_result && messageId === p_alias &&
messageId === f_result && messageId === f_alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%');
params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%');
var translation = prefix + params[0] + postfix;
params.unshift(prefix + '%s' + postfix);
var result = $.PrivateBin.I18n.translate.apply(this, params);
$.PrivateBin.I18n.reset();
var alias = $.PrivateBin.I18n._.apply(this, params);
$.PrivateBin.I18n.reset();
return translation === result && translation === alias;
}
);
});
describe('getPluralForm', function () {
before(function () {
$.PrivateBin.I18n.reset();
});
jsc.property(
'returns valid key for plural form',
common.jscSupportedLanguages(),
'integer',
function(language, n) {
$.PrivateBin.I18n.reset(language);
var result = $.PrivateBin.I18n.getPluralForm(n);
// arabic seems to have the highest plural count with 6 forms
return result >= 0 && result <= 5;
}
);
});
// loading of JSON via AJAX needs to be tested in the browser, this just mocks it
// TODO: This needs to be tested using a browser.
describe('loadTranslations', function () {
this.timeout(30000);
before(function () {
$.PrivateBin.I18n.reset();
});
jsc.property(
'downloads and handles any supported language',
common.jscSupportedLanguages(),
function(language) {
var clean = jsdom('', {url: 'https://privatebin.net/', cookie: ['lang=' + language]});
$.PrivateBin.I18n.reset('en');
$.PrivateBin.I18n.loadTranslations();
$.PrivateBin.I18n.reset(language, require('../../i18n/' + language + '.json'));
var result = $.PrivateBin.I18n.translate('en'),
alias = $.PrivateBin.I18n._('en');
clean();
return language === result && language === alias;
}
);
});
});