TopNav.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. 'use strict';
  2. var common = require('../common');
  3. describe('TopNav', function () {
  4. describe('showViewButtons & hideViewButtons', function () {
  5. before(function () {
  6. cleanup();
  7. });
  8. it(
  9. 'displays & hides navigation elements for viewing an existing paste',
  10. function () {
  11. var results = [];
  12. $('body').html(
  13. '<nav class="navbar navbar-inverse navbar-static-top">' +
  14. '<div id="navbar" class="navbar-collapse collapse"><ul ' +
  15. 'class="nav navbar-nav"><li><button id="newbutton" ' +
  16. 'type="button" class="hidden btn btn-warning navbar-btn">' +
  17. '<span class="glyphicon glyphicon-file" aria-hidden="true">' +
  18. '</span> New</button><button id="clonebutton" type="button"' +
  19. ' class="hidden btn btn-warning navbar-btn">' +
  20. '<span class="glyphicon glyphicon-duplicate" ' +
  21. 'aria-hidden="true"></span> Clone</button><button ' +
  22. 'id="rawtextbutton" type="button" class="hidden btn ' +
  23. 'btn-warning navbar-btn"><span class="glyphicon ' +
  24. 'glyphicon-text-background" aria-hidden="true"></span> ' +
  25. 'Raw text</button><button id="qrcodelink" type="button" ' +
  26. 'data-toggle="modal" data-target="#qrcodemodal" ' +
  27. 'class="hidden btn btn-warning navbar-btn"><span ' +
  28. 'class="glyphicon glyphicon-qrcode" aria-hidden="true">' +
  29. '</span> QR code</button></li></ul></div></nav>'
  30. );
  31. $.PrivateBin.TopNav.init();
  32. results.push(
  33. $('#newbutton').hasClass('hidden') &&
  34. $('#clonebutton').hasClass('hidden') &&
  35. $('#rawtextbutton').hasClass('hidden') &&
  36. $('#qrcodelink').hasClass('hidden')
  37. );
  38. $.PrivateBin.TopNav.showViewButtons();
  39. results.push(
  40. !$('#newbutton').hasClass('hidden') &&
  41. !$('#clonebutton').hasClass('hidden') &&
  42. !$('#rawtextbutton').hasClass('hidden') &&
  43. !$('#qrcodelink').hasClass('hidden')
  44. );
  45. $.PrivateBin.TopNav.hideViewButtons();
  46. results.push(
  47. $('#newbutton').hasClass('hidden') &&
  48. $('#clonebutton').hasClass('hidden') &&
  49. $('#rawtextbutton').hasClass('hidden') &&
  50. $('#qrcodelink').hasClass('hidden')
  51. );
  52. cleanup();
  53. assert.ok(results.every(element => element));
  54. }
  55. );
  56. });
  57. describe('showCreateButtons & hideCreateButtons', function () {
  58. before(function () {
  59. cleanup();
  60. });
  61. it(
  62. 'displays & hides navigation elements for creating a paste',
  63. function () {
  64. var results = [];
  65. $('body').html(
  66. '<nav><div id="navbar"><ul><li><button id="newbutton" ' +
  67. 'type="button" class="hidden">New</button></li><li><a ' +
  68. 'id="expiration" href="#" class="hidden">Expiration</a>' +
  69. '</li><li><div id="burnafterreadingoption" class="hidden">' +
  70. 'Burn after reading</div></li><li><div id="opendiscussion' +
  71. 'option" class="hidden">Open discussion</div></li><li>' +
  72. '<div id="password" class="hidden">Password</div></li>' +
  73. '<li id="attach" class="hidden">Attach a file</li><li>' +
  74. '<a id="formatter" href="#" class="hidden">Format</a>' +
  75. '</li><li><button id="sendbutton" type="button" ' +
  76. 'class="hidden">Send</button></li></ul></div></nav>'
  77. );
  78. $.PrivateBin.TopNav.init();
  79. results.push(
  80. $('#sendbutton').hasClass('hidden') &&
  81. $('#expiration').hasClass('hidden') &&
  82. $('#formatter').hasClass('hidden') &&
  83. $('#burnafterreadingoption').hasClass('hidden') &&
  84. $('#opendiscussionoption').hasClass('hidden') &&
  85. $('#newbutton').hasClass('hidden') &&
  86. $('#password').hasClass('hidden') &&
  87. $('#attach').hasClass('hidden')
  88. );
  89. $.PrivateBin.TopNav.showCreateButtons();
  90. results.push(
  91. !$('#sendbutton').hasClass('hidden') &&
  92. !$('#expiration').hasClass('hidden') &&
  93. !$('#formatter').hasClass('hidden') &&
  94. !$('#burnafterreadingoption').hasClass('hidden') &&
  95. !$('#opendiscussionoption').hasClass('hidden') &&
  96. !$('#newbutton').hasClass('hidden') &&
  97. !$('#password').hasClass('hidden') &&
  98. !$('#attach').hasClass('hidden')
  99. );
  100. $.PrivateBin.TopNav.hideCreateButtons();
  101. results.push(
  102. $('#sendbutton').hasClass('hidden') &&
  103. $('#expiration').hasClass('hidden') &&
  104. $('#formatter').hasClass('hidden') &&
  105. $('#burnafterreadingoption').hasClass('hidden') &&
  106. $('#opendiscussionoption').hasClass('hidden') &&
  107. $('#newbutton').hasClass('hidden') &&
  108. $('#password').hasClass('hidden') &&
  109. $('#attach').hasClass('hidden')
  110. );
  111. cleanup();
  112. assert.ok(results.every(element => element));
  113. }
  114. );
  115. });
  116. describe('showNewPasteButton', function () {
  117. before(function () {
  118. cleanup();
  119. });
  120. it(
  121. 'displays the button for creating a paste',
  122. function () {
  123. var results = [];
  124. $('body').html(
  125. '<nav><div id="navbar"><ul><li><button id="newbutton" type=' +
  126. '"button" class="hidden">New</button></li></ul></div></nav>'
  127. );
  128. $.PrivateBin.TopNav.init();
  129. results.push(
  130. $('#newbutton').hasClass('hidden')
  131. );
  132. $.PrivateBin.TopNav.showNewPasteButton();
  133. results.push(
  134. !$('#newbutton').hasClass('hidden')
  135. );
  136. cleanup();
  137. assert.ok(results.every(element => element));
  138. }
  139. );
  140. });
  141. describe('hideCloneButton', function () {
  142. before(function () {
  143. cleanup();
  144. });
  145. it(
  146. 'hides the button for cloning a paste',
  147. function () {
  148. var results = [];
  149. $('body').html(
  150. '<nav><div id="navbar"><ul><li><button id="clonebutton" ' +
  151. 'type="button" class="btn btn-warning navbar-btn">' +
  152. '<span class="glyphicon glyphicon-duplicate" aria-hidden=' +
  153. '"true"></span> Clone</button></li></ul></div></nav>'
  154. );
  155. $.PrivateBin.TopNav.init();
  156. results.push(
  157. !$('#clonebutton').hasClass('hidden')
  158. );
  159. $.PrivateBin.TopNav.hideCloneButton();
  160. results.push(
  161. $('#clonebutton').hasClass('hidden')
  162. );
  163. cleanup();
  164. assert.ok(results.every(element => element));
  165. }
  166. );
  167. });
  168. describe('hideRawButton', function () {
  169. before(function () {
  170. cleanup();
  171. });
  172. it(
  173. 'hides the raw text button',
  174. function () {
  175. var results = [];
  176. $('body').html(
  177. '<nav><div id="navbar"><ul><li><button ' +
  178. 'id="rawtextbutton" type="button" class="btn ' +
  179. 'btn-warning navbar-btn"><span class="glyphicon ' +
  180. 'glyphicon-text-background" aria-hidden="true"></span> ' +
  181. 'Raw text</button></li></ul></div></nav>'
  182. );
  183. $.PrivateBin.TopNav.init();
  184. results.push(
  185. !$('#rawtextbutton').hasClass('hidden')
  186. );
  187. $.PrivateBin.TopNav.hideRawButton();
  188. results.push(
  189. $('#rawtextbutton').hasClass('hidden')
  190. );
  191. cleanup();
  192. assert.ok(results.every(element => element));
  193. }
  194. );
  195. });
  196. describe('hideFileSelector', function () {
  197. before(function () {
  198. cleanup();
  199. });
  200. it(
  201. 'hides the file attachment selection button',
  202. function () {
  203. var results = [];
  204. $('body').html(
  205. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  206. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  207. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  208. 'aria-expanded="false">Attach a file <span class="caret">' +
  209. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  210. '<div><input type="file" id="file" name="file" /></div>' +
  211. '</li><li id="customattachment" class="hidden"></li><li>' +
  212. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  213. '</li></ul></li></ul></div></nav>'
  214. );
  215. $.PrivateBin.TopNav.init();
  216. results.push(
  217. !$('#filewrap').hasClass('hidden')
  218. );
  219. $.PrivateBin.TopNav.hideFileSelector();
  220. results.push(
  221. $('#filewrap').hasClass('hidden')
  222. );
  223. cleanup();
  224. assert.ok(results.every(element => element));
  225. }
  226. );
  227. });
  228. describe('showCustomAttachment', function () {
  229. before(function () {
  230. cleanup();
  231. });
  232. it(
  233. 'display the custom file attachment',
  234. function () {
  235. var results = [];
  236. $('body').html(
  237. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  238. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  239. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  240. 'aria-expanded="false">Attach a file <span class="caret">' +
  241. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  242. '<div><input type="file" id="file" name="file" /></div>' +
  243. '</li><li id="customattachment" class="hidden"></li><li>' +
  244. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  245. '</li></ul></li></ul></div></nav>'
  246. );
  247. $.PrivateBin.TopNav.init();
  248. results.push(
  249. $('#customattachment').hasClass('hidden')
  250. );
  251. $.PrivateBin.TopNav.showCustomAttachment();
  252. results.push(
  253. !$('#customattachment').hasClass('hidden')
  254. );
  255. cleanup();
  256. assert.ok(results.every(element => element));
  257. }
  258. );
  259. });
  260. describe('collapseBar', function () {
  261. before(function () {
  262. cleanup();
  263. });
  264. it(
  265. 'collapses the navigation when displayed on a small screen',
  266. function () {
  267. var results = [];
  268. $('body').html(
  269. '<nav><div class="navbar-header"><button type="button" ' +
  270. 'class="navbar-toggle collapsed" data-toggle="collapse" ' +
  271. 'data-target="#navbar" aria-expanded="false" aria-controls' +
  272. '="navbar">Toggle navigation</button><a class="reloadlink ' +
  273. 'navbar-brand" href=""><img alt="PrivateBin" ' +
  274. 'src="img/icon.svg" width="38" /></a></div><div ' +
  275. 'id="navbar"><ul><li><button id="newbutton" type=' +
  276. '"button" class="hidden">New</button></li></ul></div></nav>'
  277. );
  278. $.PrivateBin.TopNav.init();
  279. results.push(
  280. $('.navbar-toggle').hasClass('collapsed') &&
  281. $('#navbar').attr('aria-expanded') != 'true'
  282. );
  283. $.PrivateBin.TopNav.collapseBar();
  284. results.push(
  285. $('.navbar-toggle').hasClass('collapsed') &&
  286. $('#navbar').attr('aria-expanded') != 'true'
  287. );
  288. $('.navbar-toggle').click();
  289. results.push(
  290. !$('.navbar-toggle').hasClass('collapsed') &&
  291. $('#navbar').attr('aria-expanded') == 'true'
  292. );
  293. $.PrivateBin.TopNav.collapseBar();
  294. results.push(
  295. $('.navbar-toggle').hasClass('collapsed') &&
  296. $('#navbar').attr('aria-expanded') == 'false'
  297. );
  298. cleanup();
  299. assert.ok(results.every(element => element));
  300. }
  301. );
  302. });
  303. describe('resetInput', function () {
  304. before(function () {
  305. cleanup();
  306. });
  307. it(
  308. 'reset inputs to defaults (options off)',
  309. function () {
  310. var results = [];
  311. $('body').html(
  312. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  313. 'class="hidden"><label><input type="checkbox" ' +
  314. 'id="burnafterreading" name="burnafterreading" /> ' +
  315. 'Burn after reading</label></li><li id="opendiscussionoption" ' +
  316. 'class="hidden"><label><input type="checkbox" ' +
  317. 'id="opendiscussion" name="opendiscussion" /> ' +
  318. 'Open discussion</label></li></ul></div></nav>'
  319. );
  320. $.PrivateBin.TopNav.init();
  321. results.push(
  322. !$.PrivateBin.TopNav.getBurnAfterReading()
  323. );
  324. results.push(
  325. !$.PrivateBin.TopNav.getOpenDiscussion()
  326. );
  327. $('#burnafterreading').attr('checked', 'checked');
  328. $('#opendiscussion').attr('checked', 'checked');
  329. results.push(
  330. $.PrivateBin.TopNav.getBurnAfterReading()
  331. );
  332. results.push(
  333. $.PrivateBin.TopNav.getOpenDiscussion()
  334. );
  335. $.PrivateBin.TopNav.resetInput();
  336. results.push(
  337. !$.PrivateBin.TopNav.getBurnAfterReading()
  338. );
  339. results.push(
  340. !$.PrivateBin.TopNav.getOpenDiscussion()
  341. );
  342. cleanup();
  343. assert.ok(results.every(element => element));
  344. }
  345. );
  346. it(
  347. 'reset inputs to defaults (options on)',
  348. function () {
  349. var results = [];
  350. $('body').html(
  351. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  352. 'class="hidden"><label><input type="checkbox" ' +
  353. 'id="burnafterreading" name="burnafterreading" checked="checked" /> ' +
  354. 'Burn after reading</label></li><li id="opendiscussionoption" ' +
  355. 'class="hidden"><label><input type="checkbox" ' +
  356. 'id="opendiscussion" name="opendiscussion" checked="checked" /> ' +
  357. 'Open discussion</label></li></ul></div></nav>'
  358. );
  359. $.PrivateBin.TopNav.init();
  360. results.push(
  361. $.PrivateBin.TopNav.getBurnAfterReading()
  362. );
  363. results.push(
  364. $.PrivateBin.TopNav.getOpenDiscussion()
  365. );
  366. $('#burnafterreading').removeAttr('checked');
  367. $('#opendiscussion').removeAttr('checked');
  368. results.push(
  369. !$.PrivateBin.TopNav.getBurnAfterReading()
  370. );
  371. results.push(
  372. !$.PrivateBin.TopNav.getOpenDiscussion()
  373. );
  374. $.PrivateBin.TopNav.resetInput();
  375. results.push(
  376. $.PrivateBin.TopNav.getBurnAfterReading()
  377. );
  378. results.push(
  379. $.PrivateBin.TopNav.getOpenDiscussion()
  380. );
  381. cleanup();
  382. assert.ok(results.every(element => element));
  383. }
  384. );
  385. });
  386. describe('getExpiration', function () {
  387. before(function () {
  388. cleanup();
  389. });
  390. it(
  391. 'returns the currently selected expiration date',
  392. function () {
  393. $.PrivateBin.TopNav.init();
  394. assert.ok($.PrivateBin.TopNav.getExpiration() === null);
  395. }
  396. );
  397. });
  398. describe('getFileList', function () {
  399. before(function () {
  400. cleanup();
  401. });
  402. var File = window.File,
  403. FileList = window.FileList,
  404. path = require('path'),
  405. mime = require('mime-types');
  406. // mocking file input as per https://github.com/jsdom/jsdom/issues/1272
  407. function createFile(file_path) {
  408. var file = fs.statSync(file_path),
  409. lastModified = file.mtimeMs,
  410. size = file.size;
  411. return new File(
  412. [new fs.readFileSync(file_path)],
  413. path.basename(file_path),
  414. {
  415. lastModified,
  416. type: mime.lookup(file_path) || '',
  417. }
  418. )
  419. }
  420. function addFileList(input, file_paths) {
  421. if (typeof file_paths === 'string')
  422. file_paths = [file_paths]
  423. else if (!Array.isArray(file_paths)) {
  424. throw new Error('file_paths needs to be a file path string or an Array of file path strings')
  425. }
  426. const file_list = file_paths.map(fp => createFile(fp))
  427. file_list.__proto__ = Object.create(FileList.prototype)
  428. Object.defineProperty(input, 'files', {
  429. value: file_list,
  430. writeable: false,
  431. })
  432. return input
  433. }
  434. it(
  435. 'returns the selected files',
  436. function () {
  437. var results = [];
  438. $('body').html(
  439. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  440. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  441. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  442. 'aria-expanded="false">Attach a file <span class="caret">' +
  443. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  444. '<div><input type="file" id="file" name="file" /></div>' +
  445. '</li><li id="customattachment" class="hidden"></li><li>' +
  446. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  447. '</li></ul></li></ul></div></nav>'
  448. );
  449. $.PrivateBin.TopNav.init();
  450. results.push(
  451. $.PrivateBin.TopNav.getFileList() === null
  452. );
  453. addFileList($('#file')[0], [
  454. '../img/logo.svg',
  455. '../img/busy.gif'
  456. ]);
  457. var files = $.PrivateBin.TopNav.getFileList();
  458. results.push(
  459. files[0].name === 'logo.svg' &&
  460. files[1].name === 'busy.gif'
  461. );
  462. cleanup();
  463. assert.ok(results.every(element => element));
  464. }
  465. );
  466. });
  467. describe('getBurnAfterReading', function () {
  468. before(function () {
  469. cleanup();
  470. });
  471. it(
  472. 'returns if the burn-after-reading checkbox was ticked',
  473. function () {
  474. var results = [];
  475. $('body').html(
  476. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  477. 'class="hidden"><label><input type="checkbox" ' +
  478. 'id="burnafterreading" name="burnafterreading" /> ' +
  479. 'Burn after reading</label></li></ul></div></nav>'
  480. );
  481. $.PrivateBin.TopNav.init();
  482. results.push(
  483. !$.PrivateBin.TopNav.getBurnAfterReading()
  484. );
  485. $('#burnafterreading').attr('checked', 'checked');
  486. results.push(
  487. $.PrivateBin.TopNav.getBurnAfterReading()
  488. );
  489. $('#burnafterreading').removeAttr('checked');
  490. results.push(
  491. !$.PrivateBin.TopNav.getBurnAfterReading()
  492. );
  493. cleanup();
  494. assert.ok(results.every(element => element));
  495. }
  496. );
  497. });
  498. describe('getOpenDiscussion', function () {
  499. before(function () {
  500. cleanup();
  501. });
  502. it(
  503. 'returns if the open-discussion checkbox was ticked',
  504. function () {
  505. var results = [];
  506. $('body').html(
  507. '<nav><div id="navbar"><ul><li id="opendiscussionoption" ' +
  508. 'class="hidden"><label><input type="checkbox" ' +
  509. 'id="opendiscussion" name="opendiscussion" /> ' +
  510. 'Open discussion</label></li></ul></div></nav>'
  511. );
  512. $.PrivateBin.TopNav.init();
  513. results.push(
  514. !$.PrivateBin.TopNav.getOpenDiscussion()
  515. );
  516. $('#opendiscussion').attr('checked', 'checked');
  517. results.push(
  518. $.PrivateBin.TopNav.getOpenDiscussion()
  519. );
  520. $('#opendiscussion').removeAttr('checked');
  521. results.push(
  522. !$.PrivateBin.TopNav.getOpenDiscussion()
  523. );
  524. cleanup();
  525. assert.ok(results.every(element => element));
  526. }
  527. );
  528. });
  529. describe('getPassword', function () {
  530. before(function () {
  531. cleanup();
  532. });
  533. jsc.property(
  534. 'returns the contents of the password input',
  535. 'string',
  536. function (password) {
  537. password = password.replace(/\r+/g, '');
  538. var results = [];
  539. $('body').html(
  540. '<nav><div id="navbar"><ul><li><div id="password" ' +
  541. 'class="navbar-form hidden"><input type="password" ' +
  542. 'id="passwordinput" placeholder="Password (recommended)" ' +
  543. 'class="form-control" size="23" /></div></li></ul></div></nav>'
  544. );
  545. $.PrivateBin.TopNav.init();
  546. results.push(
  547. $.PrivateBin.TopNav.getPassword() === ''
  548. );
  549. $('#passwordinput').val(password);
  550. results.push(
  551. $.PrivateBin.TopNav.getPassword() === password
  552. );
  553. $('#passwordinput').val('');
  554. results.push(
  555. $.PrivateBin.TopNav.getPassword() === ''
  556. );
  557. cleanup();
  558. return results.every(element => element);
  559. }
  560. );
  561. });
  562. describe('getCustomAttachment', function () {
  563. before(function () {
  564. cleanup();
  565. });
  566. it(
  567. 'returns the custom attachment element',
  568. function () {
  569. var results = [];
  570. $('body').html(
  571. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  572. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  573. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  574. 'aria-expanded="false">Attach a file <span class="caret">' +
  575. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  576. '<div><input type="file" id="file" name="file" /></div>' +
  577. '</li><li id="customattachment" class="hidden"></li><li>' +
  578. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  579. '</li></ul></li></ul></div></nav>'
  580. );
  581. $.PrivateBin.TopNav.init();
  582. results.push(
  583. !$.PrivateBin.TopNav.getCustomAttachment().hasClass('test')
  584. );
  585. $('#customattachment').addClass('test');
  586. results.push(
  587. $.PrivateBin.TopNav.getCustomAttachment().hasClass('test')
  588. );
  589. cleanup();
  590. assert.ok(results.every(element => element));
  591. }
  592. );
  593. });
  594. });