refactor URL generators

This commit is contained in:
El RIDO 2024-01-07 15:47:29 +01:00
parent 37ee3b1c7c
commit d493ba7337
2 changed files with 52 additions and 88 deletions

View file

@ -96,36 +96,34 @@ describe('Helper', function () {
jsc.property( jsc.property(
'replaces URLs with anchors', 'replaces URLs with anchors',
'string', 'string',
jsc.elements(['http', 'https', 'ftp']), common.jscUrl(),
jsc.nearray(common.jscA2zString()),
jsc.array(common.jscQueryString()),
jsc.array(common.jscHashString()), jsc.array(common.jscHashString()),
'string', 'string',
function (prefix, schema, address, query, fragment, postfix) { function (prefix, url, fragment, postfix) {
query = query.join('');
fragment = fragment.join('');
prefix = prefix.replace(/\r|\f/g, '\n').replace(/\u0000/g, '').replace(/\u000b/g, ''); prefix = prefix.replace(/\r|\f/g, '\n').replace(/\u0000/g, '').replace(/\u000b/g, '');
postfix = ' ' + postfix.replace(/\r/g, '\n').replace(/\u0000/g, ''); postfix = ' ' + postfix.replace(/\r/g, '\n').replace(/\u0000/g, '');
let url = schema + '://' + address.join('') + '/?' + query + '#' + fragment, url.fragment = fragment.join('');
let urlString = common.urlToString(url),
clean = jsdom(); clean = jsdom();
$('body').html('<div id="foo"></div>'); $('body').html('<div id="foo"></div>');
let e = $('#foo'); let e = $('#foo');
// special cases: When the query string and fragment imply the beginning of an HTML entity, eg. &#0 or &#x // special cases: When the query string and fragment imply the beginning of an HTML entity, eg. &#0 or &#x
if ( if (
query.slice(-1) === '&' && url.query[-1] === '&' &&
(parseInt(fragment.substring(0, 1), 10) >= 0 || fragment.charAt(0) === 'x' ) (parseInt(url.fragment.charAt(0), 10) >= 0 || url.fragment.charAt(0) === 'x')
) ) {
{ url.query.pop();
url = schema + '://' + address.join('') + '/?' + query.substring(0, query.length - 1); urlString = common.urlToString(url);
postfix = ''; postfix = '';
} }
e.text(prefix + url + postfix); e.text(prefix + urlString + postfix);
$.PrivateBin.Helper.urls2links(e); $.PrivateBin.Helper.urls2links(e);
let result = e.html(); let result = e.html();
clean(); clean();
url = $('<div />').text(url).html(); urlString = $('<div />').text(urlString).html();
return $('<div />').text(prefix).html() + '<a href="' + url + '" target="_blank" rel="nofollow noopener noreferrer">' + url + '</a>' + $('<div />').text(postfix).html() === result; const expected = $('<div />').text(prefix).html() + '<a href="' + urlString + '" target="_blank" rel="nofollow noopener noreferrer">' + urlString + '</a>' + $('<div />').text(postfix).html();
return $('<div />').text(prefix).html() + '<a href="' + urlString + '" target="_blank" rel="nofollow noopener noreferrer">' + urlString + '</a>' + $('<div />').text(postfix).html() === result;
} }
); );
jsc.property( jsc.property(

View file

@ -80,23 +80,22 @@ describe('Model', function () {
jsc.property( jsc.property(
'returns the query string without separator, if any', 'returns the query string without separator, if any',
jsc.nearray(common.jscA2zString()), common.jscUrl(),
jsc.nearray(common.jscA2zString()),
jsc.tuple(new Array(16).fill(common.jscHexString)), jsc.tuple(new Array(16).fill(common.jscHexString)),
jsc.array(common.jscQueryString()), jsc.array(common.jscQueryString()),
jsc.array(common.jscQueryString()), jsc.array(common.jscQueryString()),
'string', function (url, pasteId, queryStart, queryEnd) {
function (schema, address, pasteId, queryStart, queryEnd, fragment) { if (queryStart.length > 0) {
var pasteIdString = pasteId.join(''), queryStart.push('&');
queryStartString = queryStart.join('') + (queryStart.length > 0 ? '&' : ''), }
queryEndString = (queryEnd.length > 0 ? '&' : '') + queryEnd.join(''), if (queryEnd.length > 0) {
queryString = queryStartString + pasteIdString + queryEndString, queryEnd.unshift('&');
clean = jsdom('', { }
url: schema.join('') + '://' + address.join('') + url.query = queryStart.concat(pasteId, queryEnd);
'/?' + queryString + '#' + fragment const pasteIdString = pasteId.join(''),
}); clean = jsdom('', {url: common.urlToString(url)});
global.URL = require('jsdom-url').URL; global.URL = require('jsdom-url').URL;
var result = $.PrivateBin.Model.getPasteId(); const result = $.PrivateBin.Model.getPasteId();
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
clean(); clean();
return pasteIdString === result; return pasteIdString === result;
@ -104,14 +103,9 @@ describe('Model', function () {
); );
jsc.property( jsc.property(
'throws exception on empty query string', 'throws exception on empty query string',
jsc.nearray(common.jscA2zString()), common.jscUrl(true, false),
jsc.nearray(common.jscA2zString()), function (url) {
'string', let clean = jsdom('', {url: common.urlToString(url)}),
function (schema, address, fragment) {
var clean = jsdom('', {
url: schema.join('') + '://' + address.join('') +
'/#' + fragment
}),
result = false; result = false;
global.URL = require('jsdom-url').URL; global.URL = require('jsdom-url').URL;
try { try {
@ -135,35 +129,24 @@ describe('Model', function () {
jsc.property( jsc.property(
'returns the fragment of a v1 URL', 'returns the fragment of a v1 URL',
jsc.nearray(common.jscA2zString()), common.jscUrl(),
jsc.nearray(common.jscA2zString()), function (url) {
jsc.array(common.jscQueryString()), url.fragment = common.btoa(url.fragment.padStart(32, '\u0000'));
'nestring', const clean = jsdom('', {url: common.urlToString(url)}),
function (schema, address, query, fragment) {
const fragmentString = common.btoa(fragment.padStart(32, '\u0000'));
let clean = jsdom('', {
url: schema.join('') + '://' + address.join('') +
'/?' + query.join('') + '#' + fragmentString
}),
result = $.PrivateBin.Model.getPasteKey(); result = $.PrivateBin.Model.getPasteKey();
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
clean(); clean();
return fragmentString === result; return url.fragment === result;
} }
); );
jsc.property( jsc.property(
'returns the v1 fragment stripped of trailing query parts', 'returns the v1 fragment stripped of trailing query parts',
jsc.nearray(common.jscA2zString()), common.jscUrl(),
jsc.nearray(common.jscA2zString()),
jsc.array(common.jscQueryString()),
'nestring',
jsc.array(common.jscHashString()), jsc.array(common.jscHashString()),
function (schema, address, query, fragment, trail) { function (url, trail) {
const fragmentString = common.btoa(fragment.padStart(32, '\u0000')); const fragmentString = common.btoa(url.fragment.padStart(32, '\u0000'));
let clean = jsdom('', { url.fragment = fragmentString + '&' + trail.join('');
url: schema.join('') + '://' + address.join('') + '/?' + const clean = jsdom('', {url: common.urlToString(url)}),
query.join('') + '#' + fragmentString + '&' + trail.join('')
}),
result = $.PrivateBin.Model.getPasteKey(); result = $.PrivateBin.Model.getPasteKey();
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
clean(); clean();
@ -172,18 +155,12 @@ describe('Model', function () {
); );
jsc.property( jsc.property(
'returns the fragment of a v2 URL', 'returns the fragment of a v2 URL',
jsc.nearray(common.jscA2zString()), common.jscUrl(),
jsc.nearray(common.jscA2zString()), function (url) {
jsc.array(common.jscQueryString()),
'nestring',
function (schema, address, query, fragment) {
// base58 strips leading NULL bytes, so the string is padded with these if not found // base58 strips leading NULL bytes, so the string is padded with these if not found
fragment = fragment.padStart(32, '\u0000'); const fragment = url.fragment.padStart(32, '\u0000');
let fragmentString = $.PrivateBin.CryptTool.base58encode(fragment), url.fragment = $.PrivateBin.CryptTool.base58encode(fragment);
clean = jsdom('', { const clean = jsdom('', {url: common.urlToString(url)}),
url: schema.join('') + '://' + address.join('') +
'/?' + query.join('') + '#' + fragmentString
}),
result = $.PrivateBin.Model.getPasteKey(); result = $.PrivateBin.Model.getPasteKey();
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
clean(); clean();
@ -192,19 +169,13 @@ describe('Model', function () {
); );
jsc.property( jsc.property(
'returns the v2 fragment stripped of trailing query parts', 'returns the v2 fragment stripped of trailing query parts',
jsc.nearray(common.jscA2zString()), common.jscUrl(),
jsc.nearray(common.jscA2zString()),
jsc.array(common.jscQueryString()),
'nestring',
jsc.array(common.jscHashString()), jsc.array(common.jscHashString()),
function (schema, address, query, fragment, trail) { function (url, trail) {
// base58 strips leading NULL bytes, so the string is padded with these if not found // base58 strips leading NULL bytes, so the string is padded with these if not found
fragment = fragment.padStart(32, '\u0000'); const fragment = url.fragment.padStart(32, '\u0000');
let fragmentString = $.PrivateBin.CryptTool.base58encode(fragment), url.fragment = $.PrivateBin.CryptTool.base58encode(fragment) + '&' + trail.join('');
clean = jsdom('', { const clean = jsdom('', {url: common.urlToString(url)}),
url: schema.join('') + '://' + address.join('') + '/?' +
query.join('') + '#' + fragmentString + '&' + trail.join('')
}),
result = $.PrivateBin.Model.getPasteKey(); result = $.PrivateBin.Model.getPasteKey();
$.PrivateBin.Model.reset(); $.PrivateBin.Model.reset();
clean(); clean();
@ -213,14 +184,9 @@ describe('Model', function () {
); );
jsc.property( jsc.property(
'throws exception on empty fragment of the URL', 'throws exception on empty fragment of the URL',
jsc.nearray(common.jscA2zString()), common.jscUrl(false, false),
jsc.nearray(common.jscA2zString()), function (url) {
jsc.array(common.jscQueryString()), let clean = jsdom('', {url: common.urlToString(url)}),
function (schema, address, query) {
var clean = jsdom('', {
url: schema.join('') + '://' + address.join('') +
'/?' + query.join('')
}),
result = false; result = false;
try { try {
$.PrivateBin.Model.getPasteKey(); $.PrivateBin.Model.getPasteKey();