TopNav.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  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. $('.navbar-toggle').trigger('click');
  320. results.push(
  321. !$('.navbar-toggle').hasClass('collapsed') &&
  322. $('#navbar').attr('aria-expanded') == 'true'
  323. );
  324. PrivateBin.TopNav.collapseBar();
  325. results.push(
  326. $('.navbar-toggle').hasClass('collapsed') &&
  327. $('#navbar').attr('aria-expanded') == 'false'
  328. );
  329. */
  330. const result = results.every(element => element);
  331. if (!result) {
  332. console.log(results);
  333. }
  334. assert.ok(result);
  335. }
  336. );
  337. });
  338. describe('resetInput', function () {
  339. before(function () {
  340. cleanup();
  341. });
  342. it(
  343. 'reset inputs to defaults (options off)',
  344. function () {
  345. let results = [];
  346. document.documentElement.innerHTML =
  347. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  348. 'class="hidden"><label><input type="checkbox" ' +
  349. 'id="burnafterreading" name="burnafterreading" /> ' +
  350. 'Burn after reading</label></li><li id="opendiscussionoption" ' +
  351. 'class="hidden"><label><input type="checkbox" ' +
  352. 'id="opendiscussion" name="opendiscussion" /> ' +
  353. 'Open discussion</label></li></ul></div></nav>';
  354. PrivateBin.TopNav.init();
  355. results.push(
  356. !PrivateBin.TopNav.getBurnAfterReading()
  357. );
  358. results.push(
  359. !PrivateBin.TopNav.getOpenDiscussion()
  360. );
  361. query('#burnafterreading').checked = true;
  362. query('#opendiscussion').checked = true;
  363. results.push(
  364. PrivateBin.TopNav.getBurnAfterReading()
  365. );
  366. results.push(
  367. PrivateBin.TopNav.getOpenDiscussion()
  368. );
  369. PrivateBin.TopNav.resetInput();
  370. results.push(
  371. !PrivateBin.TopNav.getBurnAfterReading()
  372. );
  373. results.push(
  374. !PrivateBin.TopNav.getOpenDiscussion()
  375. );
  376. cleanup();
  377. const result = results.every(element => element);
  378. if (!result) {
  379. console.log(results);
  380. }
  381. assert.ok(result);
  382. }
  383. );
  384. it(
  385. 'reset inputs to defaults (burnafterreading on)',
  386. function () {
  387. let results = [];
  388. document.documentElement.innerHTML =
  389. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  390. 'class="hidden"><label><input type="checkbox" ' +
  391. 'id="burnafterreading" name="burnafterreading" checked="checked" /> ' +
  392. 'Burn after reading</label></li><li id="opendiscussionoption" ' +
  393. 'class="hidden"><label><input type="checkbox" ' +
  394. 'id="opendiscussion" name="opendiscussion" checked="checked" /> ' +
  395. 'Open discussion</label></li></ul></div></nav>';
  396. PrivateBin.TopNav.init();
  397. results.push(
  398. PrivateBin.TopNav.getBurnAfterReading()
  399. );
  400. results.push(
  401. !PrivateBin.TopNav.getOpenDiscussion()
  402. );
  403. query('#burnafterreading').checked = false;
  404. query('#burnafterreading').removeAttribute('checked');
  405. results.push(
  406. !PrivateBin.TopNav.getBurnAfterReading()
  407. );
  408. results.push(
  409. !PrivateBin.TopNav.getOpenDiscussion()
  410. );
  411. PrivateBin.TopNav.resetInput();
  412. results.push(
  413. PrivateBin.TopNav.getBurnAfterReading()
  414. );
  415. results.push(
  416. !PrivateBin.TopNav.getOpenDiscussion()
  417. );
  418. cleanup();
  419. const result = results.every(element => element);
  420. if (!result) {
  421. console.log(results);
  422. }
  423. assert.ok(result);
  424. }
  425. );
  426. it(
  427. 'reset inputs to defaults (opendiscussion on)',
  428. function () {
  429. let results = [];
  430. document.documentElement.innerHTML =
  431. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  432. 'class="hidden"><label><input type="checkbox" ' +
  433. 'id="burnafterreading" name="burnafterreading" /> ' +
  434. 'Burn after reading</label></li><li id="opendiscussionoption" ' +
  435. 'class="hidden"><label><input type="checkbox" ' +
  436. 'id="opendiscussion" name="opendiscussion" checked="checked" /> ' +
  437. 'Open discussion</label></li></ul></div></nav>';
  438. PrivateBin.TopNav.init();
  439. results.push(
  440. !PrivateBin.TopNav.getBurnAfterReading()
  441. );
  442. results.push(
  443. PrivateBin.TopNav.getOpenDiscussion()
  444. );
  445. query('#opendiscussion').checked = false;
  446. query('#opendiscussion').removeAttribute('checked');
  447. query('#burnafterreading').checked = true;
  448. query('#burnafterreading').setAttribute('checked', 'checked');
  449. results.push(
  450. PrivateBin.TopNav.getBurnAfterReading()
  451. );
  452. results.push(
  453. !PrivateBin.TopNav.getOpenDiscussion()
  454. );
  455. PrivateBin.TopNav.resetInput();
  456. results.push(
  457. !PrivateBin.TopNav.getBurnAfterReading()
  458. );
  459. results.push(
  460. PrivateBin.TopNav.getOpenDiscussion()
  461. );
  462. cleanup();
  463. const result = results.every(element => element);
  464. if (!result) {
  465. console.log(results);
  466. }
  467. assert.ok(result);
  468. }
  469. );
  470. });
  471. describe('getExpiration', function () {
  472. before(function () {
  473. cleanup();
  474. });
  475. it(
  476. 'returns the currently selected expiration date',
  477. function () {
  478. document.documentElement.innerHTML =
  479. '<select id="pasteExpiration" name="pasteExpiration">' +
  480. '<option value="1day">1 day</option>' +
  481. '<option value="never">Never</option></select>';
  482. PrivateBin.TopNav.init();
  483. assert.strictEqual(PrivateBin.TopNav.getExpiration(), '1day');
  484. cleanup();
  485. }
  486. );
  487. });
  488. describe('getFileList', function () {
  489. before(function () {
  490. cleanup();
  491. });
  492. const File = window.File,
  493. FileList = window.FileList,
  494. path = require('path'), // eslint-disable-line global-require
  495. mime = require('mime-types'); // eslint-disable-line global-require
  496. // mocking file input as per https://github.com/jsdom/jsdom/issues/1272
  497. function createFile(file_path) {
  498. const lastModified = fs.statSync(file_path).mtimeMs;
  499. return new File(
  500. [new fs.readFileSync(file_path)],
  501. path.basename(file_path),
  502. {
  503. lastModified,
  504. type: mime.lookup(file_path) || ''
  505. }
  506. );
  507. }
  508. function addFileList(input, file_paths) {
  509. if (typeof file_paths === 'string') {
  510. file_paths = [file_paths];
  511. } else if (!Array.isArray(file_paths)) {
  512. throw new Error('file_paths needs to be a file path string or an Array of file path strings');
  513. }
  514. const file_list = file_paths.map(fp => createFile(fp));
  515. Object.setPrototypeOf(file_list, Object.create(FileList.prototype));
  516. Object.defineProperty(input, 'files', {
  517. value: file_list,
  518. writeable: false
  519. });
  520. return input;
  521. }
  522. it(
  523. 'returns the selected files',
  524. function () {
  525. let results = [];
  526. document.documentElement.innerHTML =
  527. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  528. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  529. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  530. 'aria-expanded="false">Attach a file <span class="caret">' +
  531. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  532. '<div><input type="file" id="file" name="file" /></div>' +
  533. '</li><li id="customattachment" class="hidden"></li><li>' +
  534. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  535. '</li></ul></li></ul></div></nav>';
  536. PrivateBin.TopNav.init();
  537. results.push(
  538. PrivateBin.TopNav.getFileList() === null
  539. );
  540. addFileList(query('#file'), [
  541. '../img/logo.svg',
  542. '../img/busy.gif'
  543. ]);
  544. const files = PrivateBin.TopNav.getFileList();
  545. results.push(
  546. files[0].name === 'logo.svg' &&
  547. files[1].name === 'busy.gif'
  548. );
  549. cleanup();
  550. const result = results.every(element => element);
  551. if (!result) {
  552. console.log(results);
  553. }
  554. assert.ok(result);
  555. }
  556. );
  557. });
  558. describe('getBurnAfterReading', function () {
  559. before(function () {
  560. cleanup();
  561. });
  562. it(
  563. 'returns if the burn-after-reading checkbox was ticked',
  564. function () {
  565. let results = [];
  566. document.documentElement.innerHTML =
  567. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  568. 'class="hidden"><label><input type="checkbox" ' +
  569. 'id="burnafterreading" name="burnafterreading" /> ' +
  570. 'Burn after reading</label></li></ul></div></nav>';
  571. PrivateBin.TopNav.init();
  572. results.push(
  573. !PrivateBin.TopNav.getBurnAfterReading()
  574. );
  575. query('#burnafterreading').checked = true;
  576. results.push(
  577. PrivateBin.TopNav.getBurnAfterReading()
  578. );
  579. query('#burnafterreading').checked = false;
  580. query('#burnafterreading').removeAttribute('checked');
  581. results.push(
  582. !PrivateBin.TopNav.getBurnAfterReading()
  583. );
  584. cleanup();
  585. const result = results.every(element => element);
  586. if (!result) {
  587. console.log(results);
  588. }
  589. assert.ok(result);
  590. }
  591. );
  592. });
  593. describe('getOpenDiscussion', function () {
  594. before(function () {
  595. cleanup();
  596. });
  597. it(
  598. 'returns if the open-discussion checkbox was ticked',
  599. function () {
  600. let results = [];
  601. document.documentElement.innerHTML =
  602. '<nav><div id="navbar"><ul><li id="opendiscussionoption" ' +
  603. 'class="hidden"><label><input type="checkbox" ' +
  604. 'id="opendiscussion" name="opendiscussion" /> ' +
  605. 'Open discussion</label></li></ul></div></nav>';
  606. PrivateBin.TopNav.init();
  607. results.push(
  608. !PrivateBin.TopNav.getOpenDiscussion()
  609. );
  610. query('#opendiscussion').checked = true;
  611. results.push(
  612. PrivateBin.TopNav.getOpenDiscussion()
  613. );
  614. query('#opendiscussion').checked = false;
  615. query('#opendiscussion').removeAttribute('checked');
  616. results.push(
  617. !PrivateBin.TopNav.getOpenDiscussion()
  618. );
  619. cleanup();
  620. const result = results.every(element => element);
  621. if (!result) {
  622. console.log(results);
  623. }
  624. assert.ok(result);
  625. }
  626. );
  627. });
  628. describe('getPassword', function () {
  629. before(function () {
  630. cleanup();
  631. });
  632. jsc.property(
  633. 'returns the contents of the password input',
  634. 'string',
  635. function (password) {
  636. password = password.replace(/\r+|\n+/g, '');
  637. let results = [];
  638. document.documentElement.innerHTML =
  639. '<nav><div id="navbar"><ul><li><div id="password" ' +
  640. 'class="navbar-form hidden"><input type="password" ' +
  641. 'id="passwordinput" placeholder="Password (recommended)" ' +
  642. 'class="form-control" size="23" /></div></li></ul></div></nav>';
  643. PrivateBin.TopNav.init();
  644. results.push(
  645. PrivateBin.TopNav.getPassword() === ''
  646. );
  647. query('#passwordinput').value = password;
  648. results.push(
  649. PrivateBin.TopNav.getPassword() === password
  650. );
  651. query('#passwordinput').value = '';
  652. results.push(
  653. PrivateBin.TopNav.getPassword() === ''
  654. );
  655. cleanup();
  656. const result = results.every(element => element);
  657. if (!result) {
  658. console.log(results);
  659. }
  660. return result;
  661. }
  662. );
  663. });
  664. describe('getCustomAttachment', function () {
  665. before(function () {
  666. cleanup();
  667. });
  668. it(
  669. 'returns the custom attachment element',
  670. function () {
  671. let results = [];
  672. document.documentElement.innerHTML =
  673. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  674. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  675. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  676. 'aria-expanded="false">Attach a file <span class="caret">' +
  677. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  678. '<div><input type="file" id="file" name="file" /></div>' +
  679. '</li><li id="customattachment" class="hidden"></li><li>' +
  680. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  681. '</li></ul></li></ul></div></nav>';
  682. PrivateBin.TopNav.init();
  683. results.push(
  684. !PrivateBin.TopNav.getCustomAttachment().classList.contains('test')
  685. );
  686. query('#customattachment').classList.add('test');
  687. results.push(
  688. PrivateBin.TopNav.getCustomAttachment().classList.contains('test')
  689. );
  690. cleanup();
  691. const result = results.every(element => element);
  692. if (!result) {
  693. console.log(results);
  694. }
  695. assert.ok(result);
  696. }
  697. );
  698. });
  699. describe('hideAllButtons', function () {
  700. before(function () {
  701. cleanup();
  702. });
  703. it(
  704. 'hides all buttons correctly',
  705. function () {
  706. // Insert any setup code needed for the hideAllButtons function
  707. // Example: Initialize the DOM elements required for testing
  708. document.body.innerHTML =
  709. '<nav class="navbar navbar-inverse navbar-static-top">' +
  710. '<div id="navbar" class="navbar-collapse collapse"><ul ' +
  711. 'class="nav navbar-nav"><li><button id="newbutton" ' +
  712. 'type="button" class="hidden btn btn-warning navbar-btn">' +
  713. '<span class="glyphicon glyphicon-file" aria-hidden="true">' +
  714. '</span> New</button><button id="clonebutton" type="button"' +
  715. ' class="hidden btn btn-warning navbar-btn">' +
  716. '<span class="glyphicon glyphicon-duplicate" ' +
  717. 'aria-hidden="true"></span> Clone</button><button ' +
  718. 'id="rawtextbutton" type="button" class="hidden btn ' +
  719. 'btn-warning navbar-btn"><span class="glyphicon ' +
  720. 'glyphicon-text-background" aria-hidden="true"></span> ' +
  721. 'Raw text</button><button id="qrcodelink" type="button" ' +
  722. 'data-toggle="modal" data-target="#qrcodemodal" ' +
  723. 'class="hidden btn btn-warning navbar-btn"><span ' +
  724. 'class="glyphicon glyphicon-qrcode" aria-hidden="true">' +
  725. '</span> QR code</button></li></ul></div></nav>';
  726. PrivateBin.TopNav.init();
  727. PrivateBin.TopNav.hideAllButtons();
  728. assert.ok(query('#newbutton').classList.contains('hidden'));
  729. assert.ok(query('#clonebutton').classList.contains('hidden'));
  730. assert.ok(query('#rawtextbutton').classList.contains('hidden'));
  731. assert.ok(query('#qrcodelink').classList.contains('hidden'));
  732. cleanup();
  733. }
  734. );
  735. });
  736. describe('rawText', function () {
  737. before(function () {
  738. cleanup();
  739. });
  740. // TODO triggers error messages in jsDOM since version 12, but passes
  741. it(
  742. 'displays raw text view correctly',
  743. function () {
  744. const clean = globalThis.cleanup('', {url: 'https://privatebin.net/?0123456789abcdef#1'});
  745. document.documentElement.innerHTML ='<button id="rawtextbutton"></button>';
  746. const sample = 'example';
  747. PrivateBin.PasteViewer.setText(sample);
  748. PrivateBin.Helper.reset();
  749. PrivateBin.TopNav.init();
  750. triggerClick(query('#rawtextbutton'));
  751. assert.strictEqual(document.querySelector('pre').textContent, sample);
  752. clean();
  753. }
  754. );
  755. });
  756. });