TopNav.js 34 KB

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