1
0

TopNav.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. 'use strict';
  2. require('../common');
  3. const fc = require('fast-check');
  4. function query(selector) {
  5. if (selector.startsWith('#')) {
  6. return document.getElementById(selector.slice(1));
  7. }
  8. return document.querySelector(selector);
  9. }
  10. describe('TopNav', function () {
  11. describe('showViewButtons & hideViewButtons', function () {
  12. before(function () {
  13. cleanup();
  14. });
  15. it(
  16. 'displays & hides navigation elements for viewing an existing document',
  17. function () {
  18. let results = [];
  19. document.documentElement.innerHTML =
  20. `<nav class="navbar navbar-inverse navbar-static-top">
  21. <div id="navbar" class="navbar-collapse collapse">
  22. <ul class="nav navbar-nav"><li><button id="newbutton" type="button" class="hidden btn btn-warning navbar-btn">
  23. <span class="glyphicon glyphicon-file" aria-hidden="true">
  24. </span> New</button><button id="clonebutton" type="button" class="hidden btn btn-warning navbar-btn">
  25. <span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> Clone</button>
  26. <button id="rawtextbutton" type="button" class="hidden btn btn-warning navbar-btn">
  27. <span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> Raw text</button>
  28. <button id="downloadtextbutton" type="button" class="hidden btn btn-default navbar-btn"></button>
  29. <button id="qrcodelink" type="button" data-toggle="modal" data-target="#qrcodemodal" class="hidden btn btn-warning navbar-btn"/>
  30. <span class="glyphicon glyphicon-qrcode" aria-hidden="true"></span> QR code</button></li></ul></div>
  31. </nav>`;
  32. PrivateBin.TopNav.init();
  33. results.push(
  34. query('#newbutton').classList.contains('hidden') &&
  35. query('#clonebutton').classList.contains('hidden') &&
  36. query('#rawtextbutton').classList.contains('hidden') &&
  37. query('#qrcodelink').classList.contains('hidden')
  38. );
  39. PrivateBin.TopNav.showViewButtons();
  40. results.push(
  41. !query('#newbutton').classList.contains('hidden') &&
  42. !query('#clonebutton').classList.contains('hidden') &&
  43. !query('#rawtextbutton').classList.contains('hidden') &&
  44. !query('#qrcodelink').classList.contains('hidden')
  45. );
  46. PrivateBin.TopNav.hideViewButtons();
  47. results.push(
  48. query('#newbutton').classList.contains('hidden') &&
  49. query('#clonebutton').classList.contains('hidden') &&
  50. query('#rawtextbutton').classList.contains('hidden') &&
  51. query('#qrcodelink').classList.contains('hidden')
  52. );
  53. cleanup();
  54. const result = results.every(element => element);
  55. if (!result) {
  56. console.log(results);
  57. }
  58. assert.ok(result);
  59. }
  60. );
  61. });
  62. describe('showCreateButtons & hideCreateButtons', function () {
  63. before(function () {
  64. cleanup();
  65. });
  66. it(
  67. 'displays & hides navigation elements for creating a document',
  68. function () { // eslint-disable-line complexity
  69. let results = [];
  70. document.documentElement.innerHTML =
  71. '<nav><div id="navbar"><ul><li><button id="newbutton" ' +
  72. 'type="button" class="hidden">New</button></li><li><a ' +
  73. 'id="expiration" href="#" class="hidden">Expiration</a>' +
  74. '</li><li><div id="burnafterreadingoption" class="hidden">' +
  75. 'Burn after reading</div></li><li><div id="opendiscussion' +
  76. 'option" class="hidden">Open discussion</div></li><li>' +
  77. '<div id="password" class="hidden">Password</div></li>' +
  78. '<li id="attach" class="hidden">Attach a file</li><li>' +
  79. '<a id="formatter" href="#" class="hidden">Format</a>' +
  80. '</li><li><button id="sendbutton" type="button" ' +
  81. 'class="hidden">Create</button></li></ul></div></nav>';
  82. PrivateBin.TopNav.init();
  83. results.push(
  84. query('#sendbutton').classList.contains('hidden') &&
  85. query('#expiration').classList.contains('hidden') &&
  86. query('#formatter').classList.contains('hidden') &&
  87. query('#burnafterreadingoption').classList.contains('hidden') &&
  88. query('#opendiscussionoption').classList.contains('hidden') &&
  89. query('#newbutton').classList.contains('hidden') &&
  90. query('#password').classList.contains('hidden') &&
  91. query('#attach').classList.contains('hidden')
  92. );
  93. PrivateBin.TopNav.showCreateButtons();
  94. results.push(
  95. !query('#sendbutton').classList.contains('hidden') &&
  96. !query('#expiration').classList.contains('hidden') &&
  97. !query('#formatter').classList.contains('hidden') &&
  98. !query('#burnafterreadingoption').classList.contains('hidden') &&
  99. !query('#opendiscussionoption').classList.contains('hidden') &&
  100. !query('#newbutton').classList.contains('hidden') &&
  101. !query('#password').classList.contains('hidden') &&
  102. !query('#attach').classList.contains('hidden')
  103. );
  104. PrivateBin.TopNav.hideCreateButtons();
  105. results.push(
  106. query('#sendbutton').classList.contains('hidden') &&
  107. query('#expiration').classList.contains('hidden') &&
  108. query('#formatter').classList.contains('hidden') &&
  109. query('#burnafterreadingoption').classList.contains('hidden') &&
  110. query('#opendiscussionoption').classList.contains('hidden') &&
  111. query('#newbutton').classList.contains('hidden') &&
  112. query('#password').classList.contains('hidden') &&
  113. query('#attach').classList.contains('hidden')
  114. );
  115. cleanup();
  116. const result = results.every(element => element);
  117. if (!result) {
  118. console.log(results);
  119. }
  120. assert.ok(result);
  121. }
  122. );
  123. });
  124. describe('showNewPasteButton', function () {
  125. before(function () {
  126. cleanup();
  127. });
  128. it(
  129. 'displays the button for creating a document',
  130. function () {
  131. let results = [];
  132. document.documentElement.innerHTML =
  133. '<nav><div id="navbar"><ul><li><button id="newbutton" type=' +
  134. '"button" class="hidden">New</button></li></ul></div></nav>';
  135. PrivateBin.TopNav.init();
  136. results.push(
  137. query('#newbutton').classList.contains('hidden')
  138. );
  139. PrivateBin.TopNav.showNewPasteButton();
  140. results.push(
  141. !query('#newbutton').classList.contains('hidden')
  142. );
  143. cleanup();
  144. const result = results.every(element => element);
  145. if (!result) {
  146. console.log(results);
  147. }
  148. assert.ok(result);
  149. }
  150. );
  151. });
  152. describe('hideCloneButton', function () {
  153. before(function () {
  154. cleanup();
  155. });
  156. it(
  157. 'hides the button for cloning a document',
  158. function () {
  159. let results = [];
  160. document.documentElement.innerHTML =
  161. '<nav><div id="navbar"><ul><li><button id="clonebutton" ' +
  162. 'type="button" class="btn btn-warning navbar-btn">' +
  163. '<span class="glyphicon glyphicon-duplicate" aria-hidden=' +
  164. '"true"></span> Clone</button></li></ul></div></nav>';
  165. PrivateBin.TopNav.init();
  166. results.push(
  167. !query('#clonebutton').classList.contains('hidden')
  168. );
  169. PrivateBin.TopNav.hideCloneButton();
  170. results.push(
  171. query('#clonebutton').classList.contains('hidden')
  172. );
  173. cleanup();
  174. const result = results.every(element => element);
  175. if (!result) {
  176. console.log(results);
  177. }
  178. assert.ok(result);
  179. }
  180. );
  181. });
  182. describe('hideRawButton', function () {
  183. before(function () {
  184. cleanup();
  185. });
  186. it(
  187. 'hides the raw text button',
  188. function () {
  189. let results = [];
  190. document.documentElement.innerHTML =
  191. '<nav><div id="navbar"><ul><li><button ' +
  192. 'id="rawtextbutton" type="button" class="btn ' +
  193. 'btn-warning navbar-btn"><span class="glyphicon ' +
  194. 'glyphicon-text-background" aria-hidden="true"></span> ' +
  195. 'Raw text</button></li></ul></div></nav>';
  196. PrivateBin.TopNav.init();
  197. results.push(
  198. !query('#rawtextbutton').classList.contains('hidden')
  199. );
  200. PrivateBin.TopNav.hideRawButton();
  201. results.push(
  202. query('#rawtextbutton').classList.contains('hidden')
  203. );
  204. cleanup();
  205. const result = results.every(element => element);
  206. if (!result) {
  207. console.log(results);
  208. }
  209. assert.ok(result);
  210. }
  211. );
  212. });
  213. describe('hideFileSelector', function () {
  214. before(function () {
  215. cleanup();
  216. });
  217. it(
  218. 'hides the file attachment selection button',
  219. function () {
  220. let results = [];
  221. document.documentElement.innerHTML =
  222. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  223. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  224. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  225. 'aria-expanded="false">Attach a file <span class="caret">' +
  226. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  227. '<div><input type="file" id="file" name="file" /></div>' +
  228. '</li><li id="customattachment" class="hidden"></li><li>' +
  229. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  230. '</li></ul></li></ul></div></nav>';
  231. PrivateBin.TopNav.init();
  232. results.push(
  233. !query('#filewrap').classList.contains('hidden')
  234. );
  235. PrivateBin.TopNav.hideFileSelector();
  236. results.push(
  237. query('#filewrap').classList.contains('hidden')
  238. );
  239. cleanup();
  240. const result = results.every(element => element);
  241. if (!result) {
  242. console.log(results);
  243. }
  244. assert.ok(result);
  245. }
  246. );
  247. });
  248. describe('showCustomAttachment', function () {
  249. before(function () {
  250. cleanup();
  251. });
  252. it(
  253. 'display the custom file attachment',
  254. function () {
  255. let results = [];
  256. document.documentElement.innerHTML =
  257. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  258. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  259. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  260. 'aria-expanded="false">Attach a file <span class="caret">' +
  261. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  262. '<div><input type="file" id="file" name="file" /></div>' +
  263. '</li><li id="customattachment" class="hidden"></li><li>' +
  264. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  265. '</li></ul></li></ul></div></nav>';
  266. PrivateBin.TopNav.init();
  267. results.push(
  268. query('#customattachment').classList.contains('hidden')
  269. );
  270. PrivateBin.TopNav.showCustomAttachment();
  271. results.push(
  272. !query('#customattachment').classList.contains('hidden')
  273. );
  274. cleanup();
  275. const result = results.every(element => element);
  276. if (!result) {
  277. console.log(results);
  278. }
  279. assert.ok(result);
  280. }
  281. );
  282. });
  283. describe('collapseBar', function () {
  284. before(function () {
  285. cleanup();
  286. });
  287. it(
  288. 'collapses the navigation when displayed on a small screen',
  289. function () {
  290. let results = [];
  291. document.documentElement.innerHTML =
  292. '<nav><div class="navbar-header"><button type="button" ' +
  293. 'class="navbar-toggle collapsed" data-toggle="collapse" ' +
  294. 'data-target="#navbar" aria-expanded="false" aria-controls' +
  295. '="navbar">Toggle navigation</button><a class="reloadlink ' +
  296. 'navbar-brand" href=""><img alt="PrivateBin" ' +
  297. 'src="img/icon.svg" width="38" /></a></div><div ' +
  298. 'id="navbar"><ul><li><button id="newbutton" type=' +
  299. '"button" class="hidden">New</button></li></ul></div></nav>';
  300. PrivateBin.TopNav.init();
  301. results.push(
  302. query('.navbar-toggle').classList.contains('collapsed') &&
  303. query('#navbar').getAttribute('aria-expanded') !== 'true'
  304. );
  305. PrivateBin.TopNav.collapseBar();
  306. results.push(
  307. query('.navbar-toggle').classList.contains('collapsed') &&
  308. query('#navbar').getAttribute('aria-expanded') !== 'true'
  309. );
  310. /*
  311. with the upgrade for bootstrap-3.3.7.js to bootstrap-3.4.1.js
  312. the mobile interface detection changed to check if the
  313. ontouchstart event exists, which broke this section of the test
  314. const toggleBtn = document.querySelector('.navbar-toggle');
  315. toggleBtn.dispatchEvent(new MouseEvent('click'));
  316. results.push(
  317. !toggleBtn.classList.contains('collapsed') &&
  318. document.getElementById('navbar').getAttribute('aria-expanded') == 'true'
  319. );
  320. PrivateBin.TopNav.collapseBar();
  321. results.push(
  322. document.querySelector('.navbar-toggle').classList.contains('collapsed') &&
  323. document.getElementById('navbar').getAttribute('aria-expanded') == 'false'
  324. );
  325. */
  326. const result = results.every(element => element);
  327. if (!result) {
  328. console.log(results);
  329. }
  330. assert.ok(result);
  331. }
  332. );
  333. });
  334. describe('resetInput', function () {
  335. before(function () {
  336. cleanup();
  337. });
  338. it(
  339. 'reset inputs to defaults (options off)',
  340. function () {
  341. let results = [];
  342. document.documentElement.innerHTML =
  343. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  344. 'class="hidden"><label><input type="checkbox" ' +
  345. 'id="burnafterreading" name="burnafterreading" /> ' +
  346. 'Burn after reading</label></li><li id="opendiscussionoption" ' +
  347. 'class="hidden"><label><input type="checkbox" ' +
  348. 'id="opendiscussion" name="opendiscussion" /> ' +
  349. 'Open discussion</label></li></ul></div></nav>';
  350. PrivateBin.TopNav.init();
  351. results.push(
  352. !PrivateBin.TopNav.getBurnAfterReading()
  353. );
  354. results.push(
  355. !PrivateBin.TopNav.getOpenDiscussion()
  356. );
  357. query('#burnafterreading').checked = true;
  358. query('#opendiscussion').checked = true;
  359. results.push(
  360. PrivateBin.TopNav.getBurnAfterReading()
  361. );
  362. results.push(
  363. PrivateBin.TopNav.getOpenDiscussion()
  364. );
  365. PrivateBin.TopNav.resetInput();
  366. results.push(
  367. !PrivateBin.TopNav.getBurnAfterReading()
  368. );
  369. results.push(
  370. !PrivateBin.TopNav.getOpenDiscussion()
  371. );
  372. cleanup();
  373. const result = results.every(element => element);
  374. if (!result) {
  375. console.log(results);
  376. }
  377. assert.ok(result);
  378. }
  379. );
  380. it(
  381. 'reset inputs to defaults (burnafterreading on)',
  382. function () {
  383. let results = [];
  384. document.documentElement.innerHTML =
  385. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  386. 'class="hidden"><label><input type="checkbox" ' +
  387. 'id="burnafterreading" name="burnafterreading" checked="checked" /> ' +
  388. 'Burn after reading</label></li><li id="opendiscussionoption" ' +
  389. 'class="hidden"><label><input type="checkbox" ' +
  390. 'id="opendiscussion" name="opendiscussion" checked="checked" /> ' +
  391. 'Open discussion</label></li></ul></div></nav>';
  392. PrivateBin.TopNav.init();
  393. results.push(
  394. PrivateBin.TopNav.getBurnAfterReading()
  395. );
  396. results.push(
  397. !PrivateBin.TopNav.getOpenDiscussion()
  398. );
  399. query('#burnafterreading').checked = false;
  400. query('#burnafterreading').removeAttribute('checked');
  401. results.push(
  402. !PrivateBin.TopNav.getBurnAfterReading()
  403. );
  404. results.push(
  405. !PrivateBin.TopNav.getOpenDiscussion()
  406. );
  407. PrivateBin.TopNav.resetInput();
  408. results.push(
  409. PrivateBin.TopNav.getBurnAfterReading()
  410. );
  411. results.push(
  412. !PrivateBin.TopNav.getOpenDiscussion()
  413. );
  414. cleanup();
  415. const result = results.every(element => element);
  416. if (!result) {
  417. console.log(results);
  418. }
  419. assert.ok(result);
  420. }
  421. );
  422. it(
  423. 'reset inputs to defaults (opendiscussion on)',
  424. function () {
  425. let results = [];
  426. document.documentElement.innerHTML =
  427. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  428. 'class="hidden"><label><input type="checkbox" ' +
  429. 'id="burnafterreading" name="burnafterreading" /> ' +
  430. 'Burn after reading</label></li><li id="opendiscussionoption" ' +
  431. 'class="hidden"><label><input type="checkbox" ' +
  432. 'id="opendiscussion" name="opendiscussion" checked="checked" /> ' +
  433. 'Open discussion</label></li></ul></div></nav>';
  434. PrivateBin.TopNav.init();
  435. results.push(
  436. !PrivateBin.TopNav.getBurnAfterReading()
  437. );
  438. results.push(
  439. PrivateBin.TopNav.getOpenDiscussion()
  440. );
  441. query('#opendiscussion').checked = false;
  442. query('#opendiscussion').removeAttribute('checked');
  443. query('#burnafterreading').checked = true;
  444. query('#burnafterreading').setAttribute('checked', 'checked');
  445. results.push(
  446. PrivateBin.TopNav.getBurnAfterReading()
  447. );
  448. results.push(
  449. !PrivateBin.TopNav.getOpenDiscussion()
  450. );
  451. PrivateBin.TopNav.resetInput();
  452. results.push(
  453. !PrivateBin.TopNav.getBurnAfterReading()
  454. );
  455. results.push(
  456. PrivateBin.TopNav.getOpenDiscussion()
  457. );
  458. cleanup();
  459. const result = results.every(element => element);
  460. if (!result) {
  461. console.log(results);
  462. }
  463. assert.ok(result);
  464. }
  465. );
  466. });
  467. describe('getExpiration', function () {
  468. before(function () {
  469. cleanup();
  470. });
  471. it(
  472. 'returns the currently selected expiration date',
  473. function () {
  474. document.documentElement.innerHTML =
  475. '<select id="pasteExpiration" name="pasteExpiration">' +
  476. '<option value="1day">1 day</option>' +
  477. '<option value="never">Never</option></select>';
  478. PrivateBin.TopNav.init();
  479. assert.strictEqual(PrivateBin.TopNav.getExpiration(), '1day');
  480. cleanup();
  481. }
  482. );
  483. });
  484. describe('getFileList', function () {
  485. before(function () {
  486. cleanup();
  487. });
  488. const File = window.File,
  489. FileList = window.FileList,
  490. path = require('path'), // eslint-disable-line global-require
  491. mime = require('mime-types'); // eslint-disable-line global-require
  492. // mocking file input as per https://github.com/jsdom/jsdom/issues/1272
  493. function createFile(file_path) {
  494. const lastModified = fs.statSync(file_path).mtimeMs;
  495. return new File(
  496. [new fs.readFileSync(file_path)],
  497. path.basename(file_path),
  498. {
  499. lastModified,
  500. type: mime.lookup(file_path) || ''
  501. }
  502. );
  503. }
  504. function addFileList(input, file_paths) {
  505. if (typeof file_paths === 'string') {
  506. file_paths = [file_paths];
  507. } else if (!Array.isArray(file_paths)) {
  508. throw new Error('file_paths needs to be a file path string or an Array of file path strings');
  509. }
  510. const file_list = file_paths.map(fp => createFile(fp));
  511. Object.setPrototypeOf(file_list, Object.create(FileList.prototype));
  512. Object.defineProperty(input, 'files', {
  513. value: file_list,
  514. writeable: false
  515. });
  516. return input;
  517. }
  518. it(
  519. 'returns the selected files',
  520. function () {
  521. let results = [];
  522. document.documentElement.innerHTML =
  523. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  524. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  525. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  526. 'aria-expanded="false">Attach a file <span class="caret">' +
  527. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  528. '<div><input type="file" id="file" name="file" /></div>' +
  529. '</li><li id="customattachment" class="hidden"></li><li>' +
  530. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  531. '</li></ul></li></ul></div></nav>';
  532. PrivateBin.TopNav.init();
  533. results.push(
  534. PrivateBin.TopNav.getFileList() === null
  535. );
  536. addFileList(query('#file'), [
  537. '../img/logo.svg',
  538. '../img/busy.gif'
  539. ]);
  540. const files = PrivateBin.TopNav.getFileList();
  541. results.push(
  542. files[0].name === 'logo.svg' &&
  543. files[1].name === 'busy.gif'
  544. );
  545. cleanup();
  546. const result = results.every(element => element);
  547. if (!result) {
  548. console.log(results);
  549. }
  550. assert.ok(result);
  551. }
  552. );
  553. });
  554. describe('getBurnAfterReading', function () {
  555. before(function () {
  556. cleanup();
  557. });
  558. it(
  559. 'returns if the burn-after-reading checkbox was ticked',
  560. function () {
  561. let results = [];
  562. document.documentElement.innerHTML =
  563. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  564. 'class="hidden"><label><input type="checkbox" ' +
  565. 'id="burnafterreading" name="burnafterreading" /> ' +
  566. 'Burn after reading</label></li></ul></div></nav>';
  567. PrivateBin.TopNav.init();
  568. results.push(
  569. !PrivateBin.TopNav.getBurnAfterReading()
  570. );
  571. query('#burnafterreading').checked = true;
  572. results.push(
  573. PrivateBin.TopNav.getBurnAfterReading()
  574. );
  575. query('#burnafterreading').checked = false;
  576. query('#burnafterreading').removeAttribute('checked');
  577. results.push(
  578. !PrivateBin.TopNav.getBurnAfterReading()
  579. );
  580. cleanup();
  581. const result = results.every(element => element);
  582. if (!result) {
  583. console.log(results);
  584. }
  585. assert.ok(result);
  586. }
  587. );
  588. });
  589. describe('getOpenDiscussion', function () {
  590. before(function () {
  591. cleanup();
  592. });
  593. it(
  594. 'returns if the open-discussion checkbox was ticked',
  595. function () {
  596. let results = [];
  597. document.documentElement.innerHTML =
  598. '<nav><div id="navbar"><ul><li id="opendiscussionoption" ' +
  599. 'class="hidden"><label><input type="checkbox" ' +
  600. 'id="opendiscussion" name="opendiscussion" /> ' +
  601. 'Open discussion</label></li></ul></div></nav>';
  602. PrivateBin.TopNav.init();
  603. results.push(
  604. !PrivateBin.TopNav.getOpenDiscussion()
  605. );
  606. query('#opendiscussion').checked = true;
  607. results.push(
  608. PrivateBin.TopNav.getOpenDiscussion()
  609. );
  610. query('#opendiscussion').checked = false;
  611. query('#opendiscussion').removeAttribute('checked');
  612. results.push(
  613. !PrivateBin.TopNav.getOpenDiscussion()
  614. );
  615. cleanup();
  616. const result = results.every(element => element);
  617. if (!result) {
  618. console.log(results);
  619. }
  620. assert.ok(result);
  621. }
  622. );
  623. });
  624. describe('getPassword', function () {
  625. before(function () {
  626. globalThis.cleanup();
  627. });
  628. it('returns the contents of the password input', () => {
  629. fc.assert(fc.property(
  630. fc.string(),
  631. function (password) {
  632. password = password.replace(/\r+|\n+/g, '');
  633. let results = [];
  634. document.documentElement.innerHTML =
  635. '<nav><div id="navbar"><ul><li><div id="password" ' +
  636. 'class="navbar-form hidden"><input type="password" ' +
  637. 'id="passwordinput" placeholder="Password (recommended)" ' +
  638. 'class="form-control" size="23" /></div></li></ul></div></nav>';
  639. PrivateBin.TopNav.init();
  640. results.push(
  641. PrivateBin.TopNav.getPassword() === ''
  642. );
  643. query('#passwordinput').value = password;
  644. results.push(
  645. PrivateBin.TopNav.getPassword() === password
  646. );
  647. query('#passwordinput').value = '';
  648. results.push(
  649. PrivateBin.TopNav.getPassword() === ''
  650. );
  651. globalThis.cleanup();
  652. const result = results.every(element => element);
  653. if (!result) {
  654. console.log(results);
  655. }
  656. return result;
  657. }
  658. ));
  659. });
  660. });
  661. describe('getCustomAttachment', function () {
  662. before(function () {
  663. cleanup();
  664. });
  665. it(
  666. 'returns the custom attachment element',
  667. function () {
  668. let results = [];
  669. document.documentElement.innerHTML =
  670. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  671. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  672. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  673. 'aria-expanded="false">Attach a file <span class="caret">' +
  674. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  675. '<div><input type="file" id="file" name="file" /></div>' +
  676. '</li><li id="customattachment" class="hidden"></li><li>' +
  677. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  678. '</li></ul></li></ul></div></nav>';
  679. PrivateBin.TopNav.init();
  680. results.push(
  681. !PrivateBin.TopNav.getCustomAttachment().classList.contains('test')
  682. );
  683. query('#customattachment').classList.add('test');
  684. results.push(
  685. PrivateBin.TopNav.getCustomAttachment().classList.contains('test')
  686. );
  687. cleanup();
  688. const result = results.every(element => element);
  689. if (!result) {
  690. console.log(results);
  691. }
  692. assert.ok(result);
  693. }
  694. );
  695. });
  696. describe('hideAllButtons', function () {
  697. before(function () {
  698. cleanup();
  699. });
  700. it(
  701. 'hides all buttons correctly',
  702. function () {
  703. // Insert any setup code needed for the hideAllButtons function
  704. // Example: Initialize the DOM elements required for testing
  705. document.body.innerHTML =
  706. '<nav class="navbar navbar-inverse navbar-static-top">' +
  707. '<div id="navbar" class="navbar-collapse collapse"><ul ' +
  708. 'class="nav navbar-nav"><li><button id="newbutton" ' +
  709. 'type="button" class="hidden btn btn-warning navbar-btn">' +
  710. '<span class="glyphicon glyphicon-file" aria-hidden="true">' +
  711. '</span> New</button><button id="clonebutton" type="button"' +
  712. ' class="hidden btn btn-warning navbar-btn">' +
  713. '<span class="glyphicon glyphicon-duplicate" ' +
  714. 'aria-hidden="true"></span> Clone</button><button ' +
  715. 'id="rawtextbutton" type="button" class="hidden btn ' +
  716. 'btn-warning navbar-btn"><span class="glyphicon ' +
  717. 'glyphicon-text-background" aria-hidden="true"></span> ' +
  718. 'Raw text</button><button id="qrcodelink" type="button" ' +
  719. 'data-toggle="modal" data-target="#qrcodemodal" ' +
  720. 'class="hidden btn btn-warning navbar-btn"><span ' +
  721. 'class="glyphicon glyphicon-qrcode" aria-hidden="true">' +
  722. '</span> QR code</button></li></ul></div></nav>';
  723. PrivateBin.TopNav.init();
  724. PrivateBin.TopNav.hideAllButtons();
  725. assert.ok(query('#newbutton').classList.contains('hidden'));
  726. assert.ok(query('#clonebutton').classList.contains('hidden'));
  727. assert.ok(query('#rawtextbutton').classList.contains('hidden'));
  728. assert.ok(query('#qrcodelink').classList.contains('hidden'));
  729. cleanup();
  730. }
  731. );
  732. });
  733. describe('rawText', function () {
  734. before(function () {
  735. cleanup();
  736. });
  737. // TODO triggers error messages in jsDOM since version 12, but passes
  738. it(
  739. 'displays raw text view correctly',
  740. function () {
  741. const clean = globalThis.cleanup('', {url: 'https://privatebin.net/?0123456789abcdef#1'});
  742. document.documentElement.innerHTML = `
  743. <li id="loadingindicator" class="hidden"></li>
  744. <button id="rawtextbutton"></button>`;
  745. const sample = 'example';
  746. PrivateBin.Alert.init(); // required because of locading indiator being used
  747. PrivateBin.TopNav.init();
  748. PrivateBin.PasteViewer.setText(sample);
  749. PrivateBin.Helper.reset();
  750. query('#rawtextbutton').click();
  751. assert.strictEqual(document.querySelector('pre').textContent, sample);
  752. clean();
  753. }
  754. );
  755. });
  756. });