1
0

PasteStatus.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. 'use strict';
  2. var common = require('../common');
  3. function urlStrings(schema, longUrl, shortUrl) {
  4. longUrl.schema = schema;
  5. shortUrl.schema = schema;
  6. let longUrlString = common.urlToString(longUrl),
  7. shortUrlString = common.urlToString(shortUrl);
  8. // ensure the two random URLs actually are sorted as expected
  9. if (longUrlString.length <= shortUrlString.length) {
  10. if (longUrlString.length === shortUrlString.length) {
  11. longUrl.address.unshift('a');
  12. longUrlString = common.urlToString(longUrl);
  13. } else {
  14. [longUrlString, shortUrlString] = [shortUrlString, longUrlString];
  15. }
  16. }
  17. return [longUrlString, shortUrlString];
  18. }
  19. describe('PasteStatus', function () {
  20. describe('createPasteNotification', function () {
  21. this.timeout(30000);
  22. it('creates a notification after a successful document upload', function () {
  23. const clean = jsdom();
  24. $('body').html('<a href="#" id="deletelink"><span></span></a><div id="pastelink"></div>');
  25. PrivateBin.PasteStatus.init();
  26. const expected1 = 'https://example.com/long';
  27. const expected2 = 'https://example.com/short';
  28. PrivateBin.PasteStatus.createPasteNotification(expected1, expected2);
  29. const result1 = $('#pasteurl')[0].href,
  30. result2 = $('#deletelink')[0].href;
  31. clean();
  32. assert.strictEqual(result1, expected1);
  33. assert.strictEqual(result2, expected2);
  34. });
  35. jsc.property(
  36. 'creates a notification after a successful document upload',
  37. common.jscUrl(),
  38. common.jscUrl(false),
  39. function (url1, url2) {
  40. // sometimes the generator returns incomplete objects, bail out
  41. if (!url1 || !url1.address || !url2 || !url2.address) {
  42. return true;
  43. }
  44. const expected1 = common.urlToString(url1).replace(/&(gt|lt)$/, '&$1a'),
  45. expected2 = common.urlToString(url2).replace(/&(gt|lt)$/, '&$1a'),
  46. clean = jsdom();
  47. $('body').html('<a href="#" id="deletelink"><span></span></a><div id="pastelink"></div>');
  48. PrivateBin.PasteStatus.init();
  49. PrivateBin.PasteStatus.createPasteNotification(expected1, expected2);
  50. const result1 = $('#pasteurl')[0].href,
  51. result2 = $('#deletelink')[0].href;
  52. clean();
  53. return result1 === expected1 && result2 === expected2;
  54. }
  55. );
  56. });
  57. describe('extractUrl', function () {
  58. this.timeout(30000);
  59. jsc.property(
  60. 'extracts and updates IDN URLs found in given response',
  61. common.jscSchemas(false),
  62. 'nestring',
  63. common.jscUrl(),
  64. function (schema, domain, url) {
  65. domain = domain.replace(/\P{Letter}|[\u{AA}-\u{BA}]/gu, '').toLowerCase();
  66. if (domain.length === 0) {
  67. domain = 'a';
  68. }
  69. url.schema = schema;
  70. url.address.unshift('.');
  71. url.address = domain.split('').concat(url.address);
  72. const urlString = common.urlToString(url),
  73. expected = urlString.substring((schema + '://' + domain).length),
  74. clean = jsdom();
  75. $('body').html('<div><div id="pastelink"></div></div>');
  76. PrivateBin.PasteStatus.init();
  77. PrivateBin.PasteStatus.createPasteNotification('', '');
  78. PrivateBin.PasteStatus.extractUrl(urlString);
  79. const result = $('#pasteurl')[0].href;
  80. clean();
  81. return result.endsWith(expected) && (
  82. result.startsWith(schema + '://xn--') ||
  83. result.startsWith(schema + '://' + domain)
  84. );
  85. }
  86. );
  87. // YOURLS API samples from: https://yourls.org/readme.html#API;apireturn
  88. jsc.property(
  89. 'extracts and updates URLs found in YOURLS API JSON response',
  90. common.jscSchemas(false),
  91. common.jscUrl(),
  92. common.jscUrl(false),
  93. function (schema, longUrl, shortUrl) {
  94. const [longUrlString, shortUrlString] = urlStrings(schema, longUrl, shortUrl),
  95. yourlsResponse = {
  96. url: {
  97. keyword: longUrl.address.join(''),
  98. url: longUrlString,
  99. title: 'example title',
  100. date: '2014-10-24 16:01:39',
  101. ip: '127.0.0.1'
  102. },
  103. status: 'success',
  104. message: longUrlString + ' added to database',
  105. title: 'example title',
  106. shorturl: shortUrlString,
  107. statusCode: 200
  108. },
  109. clean = jsdom();
  110. $('body').html('<div><div id="pastelink"></div></div>');
  111. PrivateBin.PasteStatus.init();
  112. PrivateBin.PasteStatus.createPasteNotification('', '');
  113. PrivateBin.PasteStatus.extractUrl(JSON.stringify(yourlsResponse, undefined, 4));
  114. const result = $('#pasteurl')[0].href;
  115. clean();
  116. return result === shortUrlString;
  117. }
  118. );
  119. jsc.property(
  120. 'extracts and updates URLs found in YOURLS API XML response',
  121. common.jscSchemas(false),
  122. common.jscUrl(),
  123. common.jscUrl(false),
  124. function (schema, longUrl, shortUrl) {
  125. const [longUrlString, shortUrlString] = urlStrings(schema, longUrl, shortUrl),
  126. yourlsResponse = '<result>\n' +
  127. ' <keyword>' + longUrl.address.join('') + '</keyword>\n' +
  128. ' <shorturl>' + shortUrlString + '</shorturl>\n' +
  129. ' <longurl>' + longUrlString + '</longurl>\n' +
  130. ' <message>success</message>\n' +
  131. ' <statusCode>200</statusCode>\n' +
  132. '</result>',
  133. clean = jsdom();
  134. $('body').html('<div><div id="pastelink"></div></div>');
  135. PrivateBin.PasteStatus.init();
  136. PrivateBin.PasteStatus.createPasteNotification('', '');
  137. PrivateBin.PasteStatus.extractUrl(yourlsResponse);
  138. const result = $('#pasteurl')[0].href;
  139. clean();
  140. return result === shortUrlString;
  141. }
  142. );
  143. jsc.property(
  144. 'extracts and updates URLs found in YOURLS proxy HTML response',
  145. common.jscSchemas(false),
  146. common.jscUrl(),
  147. common.jscUrl(false),
  148. function (schema, longUrl, shortUrl) {
  149. const [_, shortUrlString] = urlStrings(schema, longUrl, shortUrl),
  150. yourlsResponse = '<!DOCTYPE html>\n' +
  151. '<html lang="en">\n' +
  152. '\t<head>\n' +
  153. '\t\t<meta charset="utf-8" />\n' +
  154. '\t\t<meta name="robots" content="noindex" />\n' +
  155. '\t\t<meta name="google" content="notranslate">\n' +
  156. '\t\t<title>PrivateBin</title>\n' +
  157. '\t</head>\n' +
  158. '\t<body>\n' +
  159. '\t\t<p>Your document is <a id="pasteurl" href="' + shortUrlString + '">' + shortUrlString + '</a> <span id="copyhint">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span></p>\n' +
  160. '\t</body>\n' +
  161. '</html>',
  162. clean = jsdom();
  163. $('body').html('<div><div id="pastelink"></div></div>');
  164. PrivateBin.PasteStatus.init();
  165. PrivateBin.PasteStatus.createPasteNotification('', '');
  166. PrivateBin.PasteStatus.extractUrl(yourlsResponse);
  167. const result = $('#pasteurl')[0].href;
  168. clean();
  169. return result === shortUrlString;
  170. }
  171. );
  172. });
  173. describe('showRemainingTime', function () {
  174. this.timeout(30000);
  175. jsc.property(
  176. 'shows burn after reading message or remaining time',
  177. 'bool',
  178. 'nat',
  179. common.jscUrl(),
  180. function (burnafterreading, remainingTime, url) {
  181. let clean = jsdom('', {url: common.urlToString(url)}),
  182. result;
  183. $('body').html('<div id="remainingtime" class="hidden"></div>');
  184. PrivateBin.PasteStatus.init();
  185. PrivateBin.PasteStatus.showRemainingTime(PrivateBin.Helper.PasteFactory({
  186. 'adata': [null, null, null, burnafterreading],
  187. 'v': 2,
  188. 'meta': {
  189. 'time_to_live': remainingTime
  190. }
  191. }));
  192. if (burnafterreading) {
  193. result = $('#remainingtime').hasClass('foryoureyesonly') &&
  194. !$('#remainingtime').hasClass('hidden');
  195. } else if (remainingTime) {
  196. result =!$('#remainingtime').hasClass('foryoureyesonly') &&
  197. !$('#remainingtime').hasClass('hidden');
  198. } else {
  199. result = $('#remainingtime').hasClass('hidden') &&
  200. !$('#remainingtime').hasClass('foryoureyesonly');
  201. }
  202. clean();
  203. return result;
  204. }
  205. );
  206. });
  207. describe('hideMessages', function () {
  208. it(
  209. 'hides all messages',
  210. function() {
  211. $('body').html(
  212. '<div id="remainingtime"></div><div id="pastesuccess"></div>'
  213. );
  214. PrivateBin.PasteStatus.init();
  215. PrivateBin.PasteStatus.hideMessages();
  216. assert.ok($('#remainingtime').hasClass('hidden'));
  217. assert.ok($('#pastesuccess').hasClass('hidden'));
  218. }
  219. );
  220. });
  221. });