TopNav.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  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('hideRawButton', function () {
  117. before(function () {
  118. cleanup();
  119. });
  120. it(
  121. 'hides the raw text button',
  122. function () {
  123. var results = [];
  124. $('body').html(
  125. '<nav><div id="navbar"><ul><li><button ' +
  126. 'id="rawtextbutton" type="button" class="btn ' +
  127. 'btn-warning navbar-btn"><span class="glyphicon ' +
  128. 'glyphicon-text-background" aria-hidden="true"></span> ' +
  129. 'Raw text</button></li></ul></div></nav>'
  130. );
  131. $.PrivateBin.TopNav.init();
  132. results.push(
  133. !$('#rawtextbutton').hasClass('hidden')
  134. );
  135. $.PrivateBin.TopNav.hideRawButton();
  136. results.push(
  137. $('#rawtextbutton').hasClass('hidden')
  138. );
  139. cleanup();
  140. assert.ok(results.every(element => element));
  141. }
  142. );
  143. });
  144. describe('hideFileSelector', function () {
  145. before(function () {
  146. cleanup();
  147. });
  148. it(
  149. 'hides the file attachment selection button',
  150. function () {
  151. var results = [];
  152. $('body').html(
  153. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  154. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  155. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  156. 'aria-expanded="false">Attach a file <span class="caret">' +
  157. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  158. '<div><input type="file" id="file" name="file" /></div>' +
  159. '</li><li id="customattachment" class="hidden"></li><li>' +
  160. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  161. '</li></ul></li></ul></div></nav>'
  162. );
  163. $.PrivateBin.TopNav.init();
  164. results.push(
  165. !$('#filewrap').hasClass('hidden')
  166. );
  167. $.PrivateBin.TopNav.hideFileSelector();
  168. results.push(
  169. $('#filewrap').hasClass('hidden')
  170. );
  171. cleanup();
  172. assert.ok(results.every(element => element));
  173. }
  174. );
  175. });
  176. describe('showCustomAttachment', function () {
  177. before(function () {
  178. cleanup();
  179. });
  180. it(
  181. 'display the custom file attachment',
  182. function () {
  183. var results = [];
  184. $('body').html(
  185. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  186. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  187. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  188. 'aria-expanded="false">Attach a file <span class="caret">' +
  189. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  190. '<div><input type="file" id="file" name="file" /></div>' +
  191. '</li><li id="customattachment" class="hidden"></li><li>' +
  192. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  193. '</li></ul></li></ul></div></nav>'
  194. );
  195. $.PrivateBin.TopNav.init();
  196. results.push(
  197. $('#customattachment').hasClass('hidden')
  198. );
  199. $.PrivateBin.TopNav.showCustomAttachment();
  200. results.push(
  201. !$('#customattachment').hasClass('hidden')
  202. );
  203. cleanup();
  204. assert.ok(results.every(element => element));
  205. }
  206. );
  207. });
  208. describe('collapseBar', function () {
  209. before(function () {
  210. cleanup();
  211. });
  212. it(
  213. 'collapses the navigation when displayed on a small screen',
  214. function () {
  215. var results = [];
  216. $('body').html(
  217. '<nav><div class="navbar-header"><button type="button" ' +
  218. 'class="navbar-toggle collapsed" data-toggle="collapse" ' +
  219. 'data-target="#navbar" aria-expanded="false" aria-controls' +
  220. '="navbar">Toggle navigation</button><a class="reloadlink ' +
  221. 'navbar-brand" href=""><img alt="PrivateBin" ' +
  222. 'src="img/icon.svg" width="38" /></a></div><div ' +
  223. 'id="navbar"><ul><li><button id="newbutton" type=' +
  224. '"button" class="hidden">New</button></li></ul></div></nav>'
  225. );
  226. $.PrivateBin.TopNav.init();
  227. results.push(
  228. $('.navbar-toggle').hasClass('collapsed') &&
  229. $('#navbar').attr('aria-expanded') != 'true'
  230. );
  231. $.PrivateBin.TopNav.collapseBar();
  232. results.push(
  233. $('.navbar-toggle').hasClass('collapsed') &&
  234. $('#navbar').attr('aria-expanded') != 'true'
  235. );
  236. $('.navbar-toggle').click();
  237. results.push(
  238. !$('.navbar-toggle').hasClass('collapsed') &&
  239. $('#navbar').attr('aria-expanded') == 'true'
  240. );
  241. $.PrivateBin.TopNav.collapseBar();
  242. results.push(
  243. $('.navbar-toggle').hasClass('collapsed') &&
  244. $('#navbar').attr('aria-expanded') == 'false'
  245. );
  246. cleanup();
  247. assert.ok(results.every(element => element));
  248. }
  249. );
  250. });
  251. describe('getExpiration', function () {
  252. before(function () {
  253. cleanup();
  254. });
  255. it(
  256. 'returns the currently selected expiration date',
  257. function () {
  258. $.PrivateBin.TopNav.init();
  259. assert.ok($.PrivateBin.TopNav.getExpiration() === null);
  260. }
  261. );
  262. });
  263. describe('getFileList', function () {
  264. before(function () {
  265. cleanup();
  266. });
  267. var File = window.File,
  268. FileList = window.FileList,
  269. path = require('path'),
  270. mime = require('mime-types');
  271. // mocking file input as per https://github.com/jsdom/jsdom/issues/1272
  272. function createFile(file_path) {
  273. var file = fs.statSync(file_path),
  274. lastModified = file.mtimeMs,
  275. size = file.size;
  276. return new File(
  277. [new fs.readFileSync(file_path)],
  278. path.basename(file_path),
  279. {
  280. lastModified,
  281. type: mime.lookup(file_path) || '',
  282. }
  283. )
  284. }
  285. function addFileList(input, file_paths) {
  286. if (typeof file_paths === 'string')
  287. file_paths = [file_paths]
  288. else if (!Array.isArray(file_paths)) {
  289. throw new Error('file_paths needs to be a file path string or an Array of file path strings')
  290. }
  291. const file_list = file_paths.map(fp => createFile(fp))
  292. file_list.__proto__ = Object.create(FileList.prototype)
  293. Object.defineProperty(input, 'files', {
  294. value: file_list,
  295. writeable: false,
  296. })
  297. return input
  298. }
  299. it(
  300. 'returns the selected files',
  301. function () {
  302. var results = [];
  303. $('body').html(
  304. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  305. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  306. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  307. 'aria-expanded="false">Attach a file <span class="caret">' +
  308. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  309. '<div><input type="file" id="file" name="file" /></div>' +
  310. '</li><li id="customattachment" class="hidden"></li><li>' +
  311. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  312. '</li></ul></li></ul></div></nav>'
  313. );
  314. $.PrivateBin.TopNav.init();
  315. results.push(
  316. $.PrivateBin.TopNav.getFileList() === null
  317. );
  318. addFileList($('#file')[0], [
  319. '../img/logo.svg',
  320. '../img/busy.gif'
  321. ]);
  322. var files = $.PrivateBin.TopNav.getFileList();
  323. results.push(
  324. files[0].name === 'logo.svg' &&
  325. files[1].name === 'busy.gif'
  326. );
  327. cleanup();
  328. assert.ok(results.every(element => element));
  329. }
  330. );
  331. });
  332. describe('getBurnAfterReading', function () {
  333. before(function () {
  334. cleanup();
  335. });
  336. it(
  337. 'returns if the burn-after-reading checkbox was ticked',
  338. function () {
  339. var results = [];
  340. $('body').html(
  341. '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
  342. 'class="hidden"><label><input type="checkbox" ' +
  343. 'id="burnafterreading" name="burnafterreading" /> ' +
  344. 'Burn after reading</label></li></ul></div></nav>'
  345. );
  346. $.PrivateBin.TopNav.init();
  347. results.push(
  348. !$.PrivateBin.TopNav.getBurnAfterReading()
  349. );
  350. $('#burnafterreading').attr('checked', 'checked');
  351. results.push(
  352. $.PrivateBin.TopNav.getBurnAfterReading()
  353. );
  354. $('#burnafterreading').removeAttr('checked');
  355. results.push(
  356. !$.PrivateBin.TopNav.getBurnAfterReading()
  357. );
  358. cleanup();
  359. assert.ok(results.every(element => element));
  360. }
  361. );
  362. });
  363. describe('getOpenDiscussion', function () {
  364. before(function () {
  365. cleanup();
  366. });
  367. it(
  368. 'returns if the open-discussion checkbox was ticked',
  369. function () {
  370. var results = [];
  371. $('body').html(
  372. '<nav><div id="navbar"><ul><li id="opendiscussionoption" ' +
  373. 'class="hidden"><label><input type="checkbox" ' +
  374. 'id="opendiscussion" name="opendiscussion" /> ' +
  375. 'Open discussion</label></li></ul></div></nav>'
  376. );
  377. $.PrivateBin.TopNav.init();
  378. results.push(
  379. !$.PrivateBin.TopNav.getOpenDiscussion()
  380. );
  381. $('#opendiscussion').attr('checked', 'checked');
  382. results.push(
  383. $.PrivateBin.TopNav.getOpenDiscussion()
  384. );
  385. $('#opendiscussion').removeAttr('checked');
  386. results.push(
  387. !$.PrivateBin.TopNav.getOpenDiscussion()
  388. );
  389. cleanup();
  390. assert.ok(results.every(element => element));
  391. }
  392. );
  393. });
  394. describe('getPassword', function () {
  395. before(function () {
  396. cleanup();
  397. });
  398. jsc.property(
  399. 'returns the contents of the password input',
  400. 'string',
  401. function (password) {
  402. password = password.replace(/\r+/g, '');
  403. var results = [];
  404. $('body').html(
  405. '<nav><div id="navbar"><ul><li><div id="password" ' +
  406. 'class="navbar-form hidden"><input type="password" ' +
  407. 'id="passwordinput" placeholder="Password (recommended)" ' +
  408. 'class="form-control" size="23" /></div></li></ul></div></nav>'
  409. );
  410. $.PrivateBin.TopNav.init();
  411. results.push(
  412. $.PrivateBin.TopNav.getPassword() === ''
  413. );
  414. $('#passwordinput').val(password);
  415. results.push(
  416. $.PrivateBin.TopNav.getPassword() === password
  417. );
  418. $('#passwordinput').val('');
  419. results.push(
  420. $.PrivateBin.TopNav.getPassword() === ''
  421. );
  422. cleanup();
  423. return results.every(element => element);
  424. }
  425. );
  426. });
  427. describe('getCustomAttachment', function () {
  428. before(function () {
  429. cleanup();
  430. });
  431. it(
  432. 'returns the custom attachment element',
  433. function () {
  434. var results = [];
  435. $('body').html(
  436. '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
  437. 'dropdown"><a href="#" class="dropdown-toggle" data-' +
  438. 'toggle="dropdown" role="button" aria-haspopup="true" ' +
  439. 'aria-expanded="false">Attach a file <span class="caret">' +
  440. '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
  441. '<div><input type="file" id="file" name="file" /></div>' +
  442. '</li><li id="customattachment" class="hidden"></li><li>' +
  443. '<a id="fileremovebutton" href="#">Remove attachment</a>' +
  444. '</li></ul></li></ul></div></nav>'
  445. );
  446. $.PrivateBin.TopNav.init();
  447. results.push(
  448. !$.PrivateBin.TopNav.getCustomAttachment().hasClass('test')
  449. );
  450. $('#customattachment').addClass('test');
  451. results.push(
  452. $.PrivateBin.TopNav.getCustomAttachment().hasClass('test')
  453. );
  454. cleanup();
  455. assert.ok(results.every(element => element));
  456. }
  457. );
  458. });
  459. });