Files
PrivateBin/js/test/I18n.js

236 lines
10 KiB
JavaScript

'use strict';
var common = require('../common');
describe('I18n', function () {
describe('translate', function () {
this.timeout(30000);
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 pluralResult = PrivateBin.I18n.translate(plurals);
PrivateBin.I18n.reset();
var pluralAlias = PrivateBin.I18n._(plurals);
PrivateBin.I18n.reset();
var fakeResult = PrivateBin.I18n.translate(fake);
PrivateBin.I18n.reset();
var fakeAlias = PrivateBin.I18n._(fake);
PrivateBin.I18n.reset();
if (messageId.indexOf('<a') === -1) {
messageId = PrivateBin.Helper.htmlEntities(messageId);
} else {
messageId = DOMPurify.sanitize(
messageId, {
ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id']
}
);
}
return messageId === result && messageId === alias &&
messageId === pluralResult && messageId === pluralAlias &&
messageId === fakeResult && messageId === fakeAlias;
}
);
jsc.property(
'replaces %s in strings with first given parameter, encoding all, when no link is in the messageID',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
const translation = PrivateBin.Helper.htmlEntities(prefix + params[0] + postfix);
params.unshift(prefix + '%s' + postfix);
const result = PrivateBin.I18n.translate.apply(this, params);
PrivateBin.I18n.reset();
const alias = PrivateBin.I18n._.apply(this, params);
PrivateBin.I18n.reset();
return translation === result && translation === alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter, encoding params only, when a link is part of the messageID',
'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, '%%');
const translation = DOMPurify.sanitize(
prefix + '<a href="' + params[0] + '"></a>' + postfix, {
ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i,
ALLOWED_TAGS: ['a', 'i', 'span', 'kbd'],
ALLOWED_ATTR: ['href', 'id']
}
);
params.unshift(prefix + '<a href="%s"></a>' + postfix);
const result = PrivateBin.I18n.translate.apply(this, params);
PrivateBin.I18n.reset();
const alias = PrivateBin.I18n._.apply(this, params);
PrivateBin.I18n.reset();
return translation === result && translation === alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter into an element, encoding all, when no link is in the messageID',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
const tempDiv = document.createElement('textarea');
tempDiv.textContent = (prefix + params[0] + postfix);
const translation = tempDiv.textContent;
let args = Array.prototype.slice.call(params);
args.unshift(prefix + '%s' + postfix);
let clean = globalThis.cleanup();
document.body.innerHTML = '<div id="i18n"></div>';
const i18nElement = document.getElementById('i18n');
args.unshift(i18nElement);
PrivateBin.I18n.translate.apply(this, args);
const result = i18nElement.textContent;
PrivateBin.I18n.reset();
clean();
clean = globalThis.cleanup();
document.body.innerHTML = '<div id="i18n"></div>';
args[0] = document.getElementById('i18n');
PrivateBin.I18n._.apply(this, args);
const alias = document.getElementById('i18n').textContent;
PrivateBin.I18n.reset();
clean();
return translation === result && translation === alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter into an element, encoding params only, when a link is part of the messageID inserted',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%').trim();
params[0] = params[0].replace(/%(s|d)/g, '%%').trim();
postfix = postfix.replace(/%(s|d)/g, '%%').trim();
const translation = DOMPurify.sanitize(
prefix + '<a href="' + params[0] + '"></a>' + postfix, {
ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i,
ALLOWED_TAGS: ['a', 'i', 'span', 'kbd'],
ALLOWED_ATTR: ['href', 'id']
}
);
let args = Array.prototype.slice.call(params);
args.unshift(prefix + '<a href="%s"></a>' + postfix);
let clean = globalThis.cleanup();
document.body.innerHTML = '<div id="i18n"></div>';
const i18nElement2 = document.getElementById('i18n');
args.unshift(i18nElement2);
PrivateBin.I18n.translate.apply(this, args);
const result = i18nElement2.innerHTML;
PrivateBin.I18n.reset();
clean();
clean = globalThis.cleanup();
document.body.innerHTML = '<div id="i18n"></div>';
args[0] = document.getElementById('i18n');
PrivateBin.I18n._.apply(this, args);
const alias = document.getElementById('i18n').innerHTML;
PrivateBin.I18n.reset();
clean();
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) {
// cleanup
var clean = globalThis.cleanup('', {cookie: ['lang=en']});
PrivateBin.I18n.reset('en');
PrivateBin.I18n.loadTranslations();
clean();
// mock
clean = globalThis.cleanup('', {cookie: ['lang=' + language]});
// eslint-disable-next-line global-require
PrivateBin.I18n.reset(language, require('../../i18n/' + language + '.json'));
var loadedLang = PrivateBin.I18n.getLanguage(),
result = PrivateBin.I18n.translate('Never'),
alias = PrivateBin.I18n._('Never');
clean();
return language === loadedLang && result === alias;
}
);
jsc.property(
'should default to en',
function() {
var clean = globalThis.cleanup('', {url: 'https://privatebin.net/'});
// when navigator.userLanguage is undefined and no default language
// is specified, it would throw an error
[ 'language', 'userLanguage' ].forEach(function (key) {
Object.defineProperty(navigator, key, {
value: undefined,
writeable: false
});
});
PrivateBin.I18n.reset('en');
PrivateBin.I18n.loadTranslations();
var result = PrivateBin.I18n.translate('Never'),
alias = PrivateBin.I18n._('Never');
clean();
return 'Never' === result && 'Never' === alias;
}
);
});
});