PasteStatus.js 11 KB

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