PasteStatus.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. jsc.property(
  23. 'creates a notification after a successfull paste upload',
  24. common.jscUrl(),
  25. common.jscUrl(false),
  26. function (url1, url2) {
  27. const expected1 = common.urlToString(url1).replace(/&(gt|lt)$/, '&$1a'),
  28. expected2 = common.urlToString(url2).replace(/&(gt|lt)$/, '&$1a'),
  29. clean = jsdom();
  30. $('body').html('<a href="#" id="deletelink"><span></span></a><div id="pastelink"></div>');
  31. $.PrivateBin.PasteStatus.init();
  32. $.PrivateBin.PasteStatus.createPasteNotification(expected1, expected2);
  33. const result1 = $('#pasteurl')[0].href,
  34. result2 = $('#deletelink')[0].href;
  35. clean();
  36. return result1 === expected1 && result2 === expected2;
  37. }
  38. );
  39. });
  40. describe('extractUrl', function () {
  41. this.timeout(30000);
  42. jsc.property(
  43. 'extracts and updates IDN URLs found in given response',
  44. common.jscSchemas(false),
  45. 'nestring',
  46. common.jscUrl(),
  47. function (schema, domain, url) {
  48. domain = domain.replace(/\P{Letter}|[\u00AA-\u00BA]/gu, '').toLowerCase();
  49. if (domain.length === 0) {
  50. domain = 'a';
  51. }
  52. url.schema = schema;
  53. url.address.unshift('.');
  54. url.address = domain.split('').concat(url.address);
  55. const urlString = common.urlToString(url),
  56. expected = urlString.substring((schema + '://' + domain).length),
  57. clean = jsdom();
  58. $('body').html('<div><div id="pastelink"></div></div>');
  59. $.PrivateBin.PasteStatus.init();
  60. $.PrivateBin.PasteStatus.createPasteNotification('', '');
  61. $.PrivateBin.PasteStatus.extractUrl(urlString);
  62. const result = $('#pasteurl')[0].href;
  63. clean();
  64. return result.endsWith(expected) && (
  65. result.startsWith(schema + '://xn--') ||
  66. result.startsWith(schema + '://' + domain)
  67. );
  68. }
  69. );
  70. // YOURLS API samples from: https://yourls.org/readme.html#API;apireturn
  71. jsc.property(
  72. 'extracts and updates URLs found in YOURLS API JSON response',
  73. common.jscSchemas(false),
  74. common.jscUrl(),
  75. common.jscUrl(false),
  76. function (schema, longUrl, shortUrl) {
  77. const [longUrlString, shortUrlString] = urlStrings(schema, longUrl, shortUrl),
  78. yourlsResponse = {
  79. url: {
  80. keyword: longUrl.address.join(''),
  81. url: longUrlString,
  82. title: "example title",
  83. date: "2014-10-24 16:01:39",
  84. ip: "127.0.0.1"
  85. },
  86. status: "success",
  87. message: longUrlString + " added to database",
  88. title: "example title",
  89. shorturl: shortUrlString,
  90. statusCode: 200
  91. },
  92. clean = jsdom();
  93. $('body').html('<div><div id="pastelink"></div></div>');
  94. $.PrivateBin.PasteStatus.init();
  95. $.PrivateBin.PasteStatus.createPasteNotification('', '');
  96. $.PrivateBin.PasteStatus.extractUrl(JSON.stringify(yourlsResponse, undefined, 4));
  97. const result = $('#pasteurl')[0].href;
  98. clean();
  99. return result === shortUrlString;
  100. }
  101. );
  102. jsc.property(
  103. 'extracts and updates URLs found in YOURLS API XML response',
  104. common.jscSchemas(false),
  105. common.jscUrl(),
  106. common.jscUrl(false),
  107. function (schema, longUrl, shortUrl) {
  108. const [longUrlString, shortUrlString] = urlStrings(schema, longUrl, shortUrl),
  109. yourlsResponse = '<result>\n' +
  110. ' <keyword>' + longUrl.address.join('') + '</keyword>\n' +
  111. ' <shorturl>' + shortUrlString + '</shorturl>\n' +
  112. ' <longurl>' + longUrlString + '</longurl>\n' +
  113. ' <message>success</message>\n' +
  114. ' <statusCode>200</statusCode>\n' +
  115. '</result>',
  116. clean = jsdom();
  117. $('body').html('<div><div id="pastelink"></div></div>');
  118. $.PrivateBin.PasteStatus.init();
  119. $.PrivateBin.PasteStatus.createPasteNotification('', '');
  120. $.PrivateBin.PasteStatus.extractUrl(yourlsResponse);
  121. const result = $('#pasteurl')[0].href;
  122. clean();
  123. return result === shortUrlString;
  124. }
  125. );
  126. jsc.property(
  127. 'extracts and updates URLs found in YOURLS proxy HTML response',
  128. common.jscSchemas(false),
  129. common.jscUrl(),
  130. common.jscUrl(false),
  131. function (schema, longUrl, shortUrl) {
  132. const [longUrlString, shortUrlString] = urlStrings(schema, longUrl, shortUrl),
  133. yourlsResponse = '<!DOCTYPE html>\n' +
  134. '<html lang="en">\n' +
  135. '\t<head>\n' +
  136. '\t\t<meta charset="utf-8" />\n' +
  137. '\t\t<meta http-equiv="Content-Security-Policy" content="default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\'; style-src \'self\'; font-src \'self\'; frame-ancestors \'none\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads">\n' +
  138. '\t\t<meta name="robots" content="noindex" />\n' +
  139. '\t\t<meta name="google" content="notranslate">\n' +
  140. '\t\t<title>PrivateBin</title>\n' +
  141. '\t</head>\n' +
  142. '\t<body>\n' +
  143. '\t\t<p>Your paste is <a id="pasteurl" href="' + shortUrlString + '">' + shortUrlString + '</a> <span id="copyhint">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span></p>\n' +
  144. '\t</body>\n' +
  145. '</html>',
  146. clean = jsdom();
  147. $('body').html('<div><div id="pastelink"></div></div>');
  148. $.PrivateBin.PasteStatus.init();
  149. $.PrivateBin.PasteStatus.createPasteNotification('', '');
  150. $.PrivateBin.PasteStatus.extractUrl(yourlsResponse);
  151. const result = $('#pasteurl')[0].href;
  152. clean();
  153. return result === shortUrlString;
  154. }
  155. );
  156. });
  157. describe('showRemainingTime', function () {
  158. this.timeout(30000);
  159. jsc.property(
  160. 'shows burn after reading message or remaining time v1',
  161. 'bool',
  162. 'nat',
  163. common.jscUrl(),
  164. function (burnafterreading, remainingTime, url) {
  165. let clean = jsdom('', {url: common.urlToString(url)}),
  166. result;
  167. $('body').html('<div id="remainingtime" class="hidden"></div>');
  168. $.PrivateBin.PasteStatus.init();
  169. $.PrivateBin.PasteStatus.showRemainingTime($.PrivateBin.Helper.PasteFactory({'meta': {
  170. 'burnafterreading': burnafterreading,
  171. 'remaining_time': remainingTime
  172. }}));
  173. if (burnafterreading) {
  174. result = $('#remainingtime').hasClass('foryoureyesonly') &&
  175. !$('#remainingtime').hasClass('hidden');
  176. } else if (remainingTime) {
  177. result =!$('#remainingtime').hasClass('foryoureyesonly') &&
  178. !$('#remainingtime').hasClass('hidden');
  179. } else {
  180. result = $('#remainingtime').hasClass('hidden') &&
  181. !$('#remainingtime').hasClass('foryoureyesonly');
  182. }
  183. clean();
  184. return result;
  185. }
  186. );
  187. jsc.property(
  188. 'shows burn after reading message or remaining time v2',
  189. 'bool',
  190. 'nat',
  191. common.jscUrl(),
  192. function (burnafterreading, remainingTime, url) {
  193. let clean = jsdom('', {url: common.urlToString(url)}),
  194. result;
  195. $('body').html('<div id="remainingtime" class="hidden"></div>');
  196. $.PrivateBin.PasteStatus.init();
  197. $.PrivateBin.PasteStatus.showRemainingTime($.PrivateBin.Helper.PasteFactory({
  198. 'adata': [null, null, null, burnafterreading],
  199. 'v': 2,
  200. 'meta': {
  201. 'time_to_live': remainingTime
  202. }
  203. }));
  204. if (burnafterreading) {
  205. result = $('#remainingtime').hasClass('foryoureyesonly') &&
  206. !$('#remainingtime').hasClass('hidden');
  207. } else if (remainingTime) {
  208. result =!$('#remainingtime').hasClass('foryoureyesonly') &&
  209. !$('#remainingtime').hasClass('hidden');
  210. } else {
  211. result = $('#remainingtime').hasClass('hidden') &&
  212. !$('#remainingtime').hasClass('foryoureyesonly');
  213. }
  214. clean();
  215. return result;
  216. }
  217. );
  218. });
  219. describe('hideMessages', function () {
  220. it(
  221. 'hides all messages',
  222. function() {
  223. $('body').html(
  224. '<div id="remainingtime"></div><div id="pastesuccess"></div>'
  225. );
  226. $.PrivateBin.PasteStatus.init();
  227. $.PrivateBin.PasteStatus.hideMessages();
  228. assert.ok(
  229. $('#remainingtime').hasClass('hidden') &&
  230. $('#pastesuccess').hasClass('hidden')
  231. );
  232. }
  233. );
  234. });
  235. });