TopNav.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  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('getExpiration', function () {
  304. before(function () {
  305. cleanup();
  306. });
  307. it(
  308. 'returns the currently selected expiration date',
  309. function () {
  310. $.PrivateBin.TopNav.init();
  311. assert.ok($.PrivateBin.TopNav.getExpiration() === '1week');
  312. }
  313. );
  314. });
  315. describe('getFileList', function () {
  316. before(function () {
  317. cleanup();
  318. });
  319. var File = window.File,
  320. FileList = window.FileList,
  321. path = require('path'),
  322. mime = require('mime-types');
  323. // mocking file input as per https://github.com/jsdom/jsdom/issues/1272
  324. function createFile(file_path) {
  325. var file = fs.statSync(file_path),
  326. lastModified = file.mtimeMs,
  327. size = file.size;
  328. return new File(
  329. [new fs.readFileSync(file_path)],
  330. path.basename(file_path),
  331. {
  332. lastModified,
  333. type: mime.lookup(file_path) || '',
  334. }
  335. )
  336. }
  337. function addFileList(input, file_paths) {
  338. if (typeof file_paths === 'string')
  339. file_paths = [file_paths]
  340. else if (!Array.isArray(file_paths)) {
  341. throw new Error('file_paths needs to be a file path string or an Array of file path strings')
  342. }
  343. const file_list = file_paths.map(fp => createFile(fp))
  344. file_list.__proto__ = Object.create(FileList.prototype)
  345. Object.defineProperty(input, 'files', {
  346. value: file_list,
  347. writeable: false,
  348. })
  349. return input
  350. }
  351. it(
  352. 'returns the selected files',
  353. function () {
  354. var results = [];
  355. $('body').html(
  356. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  357. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  358. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  359. 'aria-expanded="false">Attach a file <span class="caret">' +
  360. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  361. '<div><input type="file" id="file" name="file" /></div>' +
  362. '</li><li id="customattachment" class="hidden"></li><li>' +
  363. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  364. '</li></ul></li></ul></div></nav>'
  365. );
  366. $.PrivateBin.TopNav.init();
  367. results.push(
  368. $.PrivateBin.TopNav.getFileList() === null
  369. );
  370. addFileList($('#file')[0], [
  371. '../img/logo.svg',
  372. '../img/busy.gif'
  373. ]);
  374. var files = $.PrivateBin.TopNav.getFileList();
  375. results.push(
  376. files[0].name === 'logo.svg' &&
  377. files[1].name === 'busy.gif'
  378. );
  379. cleanup();
  380. assert.ok(results.every(element => element));
  381. }
  382. );
  383. });
  384. describe('getBurnAfterReading', function () {
  385. before(function () {
  386. cleanup();
  387. });
  388. it(
  389. 'returns if the burn-after-reading checkbox was ticked',
  390. function () {
  391. var results = [];
  392. $('body').html(
  393. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  394. 'class="hidden"><label><input type="checkbox" ' +
  395. 'id="burnafterreading" name="burnafterreading" /> ' +
  396. 'Burn after reading</label></li></ul></div></nav>'
  397. );
  398. $.PrivateBin.TopNav.init();
  399. results.push(
  400. !$.PrivateBin.TopNav.getBurnAfterReading()
  401. );
  402. $('#burnafterreading').attr('checked', 'checked');
  403. results.push(
  404. $.PrivateBin.TopNav.getBurnAfterReading()
  405. );
  406. $('#burnafterreading').removeAttr('checked');
  407. results.push(
  408. !$.PrivateBin.TopNav.getBurnAfterReading()
  409. );
  410. cleanup();
  411. assert.ok(results.every(element => element));
  412. }
  413. );
  414. });
  415. describe('getOpenDiscussion', function () {
  416. before(function () {
  417. cleanup();
  418. });
  419. it(
  420. 'returns if the open-discussion checkbox was ticked',
  421. function () {
  422. var results = [];
  423. $('body').html(
  424. '<nav><div id="navbar"><ul><li id="opendiscussionoption" ' +
  425. 'class="hidden"><label><input type="checkbox" ' +
  426. 'id="opendiscussion" name="opendiscussion" /> ' +
  427. 'Open discussion</label></li></ul></div></nav>'
  428. );
  429. $.PrivateBin.TopNav.init();
  430. results.push(
  431. !$.PrivateBin.TopNav.getOpenDiscussion()
  432. );
  433. $('#opendiscussion').attr('checked', 'checked');
  434. results.push(
  435. $.PrivateBin.TopNav.getOpenDiscussion()
  436. );
  437. $('#opendiscussion').removeAttr('checked');
  438. results.push(
  439. !$.PrivateBin.TopNav.getOpenDiscussion()
  440. );
  441. cleanup();
  442. assert.ok(results.every(element => element));
  443. }
  444. );
  445. });
  446. describe('getPassword', function () {
  447. before(function () {
  448. cleanup();
  449. });
  450. jsc.property(
  451. 'returns the contents of the password input',
  452. 'string',
  453. function (password) {
  454. password = password.replace(/\r+/g, '');
  455. var results = [];
  456. $('body').html(
  457. '<nav><div id="navbar"><ul><li><div id="password" ' +
  458. 'class="navbar-form hidden"><input type="password" ' +
  459. 'id="passwordinput" placeholder="Password (recommended)" ' +
  460. 'class="form-control" size="23" /></div></li></ul></div></nav>'
  461. );
  462. $.PrivateBin.TopNav.init();
  463. results.push(
  464. $.PrivateBin.TopNav.getPassword() === ''
  465. );
  466. $('#passwordinput').val(password);
  467. results.push(
  468. $.PrivateBin.TopNav.getPassword() === password
  469. );
  470. $('#passwordinput').val('');
  471. results.push(
  472. $.PrivateBin.TopNav.getPassword() === ''
  473. );
  474. cleanup();
  475. return results.every(element => element);
  476. }
  477. );
  478. });
  479. describe('getCustomAttachment', function () {
  480. before(function () {
  481. cleanup();
  482. });
  483. it(
  484. 'returns the custom attachment element',
  485. function () {
  486. var results = [];
  487. $('body').html(
  488. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  489. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  490. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  491. 'aria-expanded="false">Attach a file <span class="caret">' +
  492. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  493. '<div><input type="file" id="file" name="file" /></div>' +
  494. '</li><li id="customattachment" class="hidden"></li><li>' +
  495. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  496. '</li></ul></li></ul></div></nav>'
  497. );
  498. $.PrivateBin.TopNav.init();
  499. results.push(
  500. !$.PrivateBin.TopNav.getCustomAttachment().hasClass('test')
  501. );
  502. $('#customattachment').addClass('test');
  503. results.push(
  504. $.PrivateBin.TopNav.getCustomAttachment().hasClass('test')
  505. );
  506. cleanup();
  507. assert.ok(results.every(element => element));
  508. }
  509. );
  510. });
  511. });