PasteStatus.js 11 KB

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