| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011 |
- 'use strict';
- require('../common');
- const fc = require('fast-check');
- function query(selector) {
- if (selector.startsWith('#')) {
- return document.getElementById(selector.slice(1));
- }
- return document.querySelector(selector);
- }
- describe('TopNav', function () {
- describe('showViewButtons & hideViewButtons', function () {
- before(function () {
- cleanup();
- });
- it(
- 'displays & hides navigation elements for viewing an existing document',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- `<nav class="navbar navbar-inverse navbar-static-top">
- <div id="navbar" class="navbar-collapse collapse">
- <ul class="nav navbar-nav"><li><button id="newbutton" type="button" class="hidden btn btn-warning navbar-btn">
- <span class="glyphicon glyphicon-file" aria-hidden="true">
- </span> New</button><button id="clonebutton" type="button" class="hidden btn btn-warning navbar-btn">
- <span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> Clone</button>
- <button id="rawtextbutton" type="button" class="hidden btn btn-warning navbar-btn">
- <span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> Raw text</button>
- <button id="downloadtextbutton" type="button" class="hidden btn btn-default navbar-btn"></button>
- <button id="qrcodelink" type="button" data-toggle="modal" data-target="#qrcodemodal" class="hidden btn btn-warning navbar-btn"/>
- <span class="glyphicon glyphicon-qrcode" aria-hidden="true"></span> QR code</button></li></ul></div>
- </nav>`;
- PrivateBin.TopNav.init();
- results.push(
- query('#newbutton').classList.contains('hidden') &&
- query('#clonebutton').classList.contains('hidden') &&
- query('#rawtextbutton').classList.contains('hidden') &&
- query('#qrcodelink').classList.contains('hidden')
- );
- PrivateBin.TopNav.showViewButtons();
- results.push(
- !query('#newbutton').classList.contains('hidden') &&
- !query('#clonebutton').classList.contains('hidden') &&
- !query('#rawtextbutton').classList.contains('hidden') &&
- !query('#qrcodelink').classList.contains('hidden')
- );
- PrivateBin.TopNav.hideViewButtons();
- results.push(
- query('#newbutton').classList.contains('hidden') &&
- query('#clonebutton').classList.contains('hidden') &&
- query('#rawtextbutton').classList.contains('hidden') &&
- query('#qrcodelink').classList.contains('hidden')
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('showCreateButtons & hideCreateButtons', function () {
- before(function () {
- cleanup();
- });
- it(
- 'displays & hides navigation elements for creating a document',
- function () { // eslint-disable-line complexity
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li><button id="newbutton" ' +
- 'type="button" class="hidden">New</button></li><li><a ' +
- 'id="expiration" href="#" class="hidden">Expiration</a>' +
- '</li><li><div id="burnafterreadingoption" class="hidden">' +
- 'Burn after reading</div></li><li><div id="opendiscussion' +
- 'option" class="hidden">Open discussion</div></li><li>' +
- '<div id="password" class="hidden">Password</div></li>' +
- '<li id="attach" class="hidden">Attach a file</li><li>' +
- '<a id="formatter" href="#" class="hidden">Format</a>' +
- '</li><li><button id="sendbutton" type="button" ' +
- 'class="hidden">Create</button></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- query('#sendbutton').classList.contains('hidden') &&
- query('#expiration').classList.contains('hidden') &&
- query('#formatter').classList.contains('hidden') &&
- query('#burnafterreadingoption').classList.contains('hidden') &&
- query('#opendiscussionoption').classList.contains('hidden') &&
- query('#newbutton').classList.contains('hidden') &&
- query('#password').classList.contains('hidden') &&
- query('#attach').classList.contains('hidden')
- );
- PrivateBin.TopNav.showCreateButtons();
- results.push(
- !query('#sendbutton').classList.contains('hidden') &&
- !query('#expiration').classList.contains('hidden') &&
- !query('#formatter').classList.contains('hidden') &&
- !query('#burnafterreadingoption').classList.contains('hidden') &&
- !query('#opendiscussionoption').classList.contains('hidden') &&
- !query('#newbutton').classList.contains('hidden') &&
- !query('#password').classList.contains('hidden') &&
- !query('#attach').classList.contains('hidden')
- );
- PrivateBin.TopNav.hideCreateButtons();
- results.push(
- query('#sendbutton').classList.contains('hidden') &&
- query('#expiration').classList.contains('hidden') &&
- query('#formatter').classList.contains('hidden') &&
- query('#burnafterreadingoption').classList.contains('hidden') &&
- query('#opendiscussionoption').classList.contains('hidden') &&
- query('#newbutton').classList.contains('hidden') &&
- query('#password').classList.contains('hidden') &&
- query('#attach').classList.contains('hidden')
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- it(
- 'tolerates missing optional elements (discussion & password disabled)',
- function () {
- // with discussion = false and password = false in the
- // configuration, the template omits these elements entirely
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li><button id="newbutton" ' +
- 'type="button" class="hidden">New</button></li><li><a ' +
- 'id="expiration" href="#" class="hidden">Expiration</a>' +
- '</li><li><div id="burnafterreadingoption" class="hidden">' +
- 'Burn after reading</div></li><li>' +
- '<a id="formatter" href="#" class="hidden">Format</a>' +
- '</li><li><button id="sendbutton" type="button" ' +
- 'class="hidden">Create</button></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- assert.doesNotThrow(() => PrivateBin.TopNav.showCreateButtons());
- assert.ok(!query('#sendbutton').classList.contains('hidden'));
- assert.ok(!query('#burnafterreadingoption').classList.contains('hidden'));
- assert.doesNotThrow(() => PrivateBin.TopNav.hideCreateButtons());
- assert.ok(query('#sendbutton').classList.contains('hidden'));
- assert.ok(query('#burnafterreadingoption').classList.contains('hidden'));
- cleanup();
- }
- );
- });
- describe('send shortcut', function () {
- let sendCount;
- // builds the create-document navbar and stubs the actual send, so no
- // server interaction happens
- function setUpCreateMode() {
- cleanup();
- sendCount = 0;
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li><button id="newbutton" ' +
- 'type="button" class="hidden">New</button></li><li><a ' +
- 'id="expiration" href="#" class="hidden">Expiration</a>' +
- '</li><li><div id="burnafterreadingoption" class="hidden">' +
- 'Burn after reading</div></li><li><div id="opendiscussion' +
- 'option" class="hidden">Open discussion</div></li><li>' +
- '<div id="password" class="hidden">Password</div></li>' +
- '<li id="attach" class="hidden">Attach a file</li><li>' +
- '<a id="formatter" href="#" class="hidden">Format</a>' +
- '</li><li><button id="sendbutton" type="button" ' +
- 'class="hidden">Create</button></li></ul></div></nav>';
- PrivateBin.PasteEncrypter.sendPaste = function () {
- sendCount++;
- };
- PrivateBin.TopNav.init();
- PrivateBin.TopNav.showCreateButtons();
- }
- // dispatches a keydown on the document, returns whether the default was prevented
- function pressKey(options) {
- const event = new window.KeyboardEvent('keydown', Object.assign(
- {bubbles: true, cancelable: true}, options
- ));
- document.dispatchEvent(event);
- return event.defaultPrevented;
- }
- afterEach(function () {
- cleanup();
- });
- it('sends the document on Ctrl+S and suppresses the browser save dialog', function () {
- setUpCreateMode();
- const prevented = pressKey({key: 's', code: 'KeyS', ctrlKey: true});
- assert.strictEqual(sendCount, 1);
- assert.ok(prevented);
- });
- it('sends the document on Cmd+S (macOS)', function () {
- setUpCreateMode();
- const prevented = pressKey({key: 's', code: 'KeyS', metaKey: true});
- assert.strictEqual(sendCount, 1);
- assert.ok(prevented);
- });
- it('sends on the physical S key of non-Latin keyboard layouts', function () {
- setUpCreateMode();
- // on a Russian layout the S key produces "ы"
- pressKey({key: 'ы', code: 'KeyS', ctrlKey: true});
- assert.strictEqual(sendCount, 1);
- });
- it('leaves Ctrl+S to the browser when viewing a document', function () {
- setUpCreateMode();
- PrivateBin.TopNav.hideCreateButtons();
- const prevented = pressKey({key: 's', code: 'KeyS', ctrlKey: true});
- assert.strictEqual(sendCount, 0);
- assert.ok(!prevented);
- });
- it('ignores S without Ctrl/Cmd, with AltGr (Ctrl+Alt), with Shift, or other keys', function () {
- setUpCreateMode();
- const prevented = [
- pressKey({key: 's', code: 'KeyS'}),
- pressKey({key: 's', code: 'KeyS', ctrlKey: true, altKey: true}),
- pressKey({key: 'S', code: 'KeyS', ctrlKey: true, shiftKey: true}),
- pressKey({key: 'd', code: 'KeyD', ctrlKey: true})
- ];
- assert.strictEqual(sendCount, 0);
- assert.deepStrictEqual(prevented, [false, false, false, false]);
- });
- });
- describe('showNewPasteButton', function () {
- before(function () {
- cleanup();
- });
- it(
- 'displays the button for creating a document',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li><button id="newbutton" type=' +
- '"button" class="hidden">New</button></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- query('#newbutton').classList.contains('hidden')
- );
- PrivateBin.TopNav.showNewPasteButton();
- results.push(
- !query('#newbutton').classList.contains('hidden')
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('hideCloneButton', function () {
- before(function () {
- cleanup();
- });
- it(
- 'hides the button for cloning a document',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li><button id="clonebutton" ' +
- 'type="button" class="btn btn-warning navbar-btn">' +
- '<span class="glyphicon glyphicon-duplicate" aria-hidden=' +
- '"true"></span> Clone</button></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- !query('#clonebutton').classList.contains('hidden')
- );
- PrivateBin.TopNav.hideCloneButton();
- results.push(
- query('#clonebutton').classList.contains('hidden')
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('hideRawButton', function () {
- before(function () {
- cleanup();
- });
- it(
- 'hides the raw text button',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li><button ' +
- 'id="rawtextbutton" type="button" class="btn ' +
- 'btn-warning navbar-btn"><span class="glyphicon ' +
- 'glyphicon-text-background" aria-hidden="true"></span> ' +
- 'Raw text</button></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- !query('#rawtextbutton').classList.contains('hidden')
- );
- PrivateBin.TopNav.hideRawButton();
- results.push(
- query('#rawtextbutton').classList.contains('hidden')
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('hideFileSelector', function () {
- before(function () {
- cleanup();
- });
- it(
- 'hides the file attachment selection button',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
- 'dropdown"><a href="#" class="dropdown-toggle" data-' +
- 'toggle="dropdown" role="button" aria-haspopup="true" ' +
- 'aria-expanded="false">Attach a file <span class="caret">' +
- '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
- '<div><input type="file" id="file" name="file" /></div>' +
- '</li><li id="customattachment" class="hidden"></li><li>' +
- '<a id="fileremovebutton" href="#">Remove attachment</a>' +
- '</li></ul></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- !query('#filewrap').classList.contains('hidden')
- );
- PrivateBin.TopNav.hideFileSelector();
- results.push(
- query('#filewrap').classList.contains('hidden')
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('showCustomAttachment', function () {
- before(function () {
- cleanup();
- });
- it(
- 'display the custom file attachment',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
- 'dropdown"><a href="#" class="dropdown-toggle" data-' +
- 'toggle="dropdown" role="button" aria-haspopup="true" ' +
- 'aria-expanded="false">Attach a file <span class="caret">' +
- '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
- '<div><input type="file" id="file" name="file" /></div>' +
- '</li><li id="customattachment" class="hidden"></li><li>' +
- '<a id="fileremovebutton" href="#">Remove attachment</a>' +
- '</li></ul></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- query('#customattachment').classList.contains('hidden')
- );
- PrivateBin.TopNav.showCustomAttachment();
- results.push(
- !query('#customattachment').classList.contains('hidden')
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('collapseBar', function () {
- before(function () {
- cleanup();
- });
- it(
- 'collapses the navigation when displayed on a small screen',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div class="navbar-header"><button type="button" ' +
- 'class="navbar-toggle collapsed" data-toggle="collapse" ' +
- 'data-target="#navbar" aria-expanded="false" aria-controls' +
- '="navbar">Toggle navigation</button><a class="reloadlink ' +
- 'navbar-brand" href=""><img alt="PrivateBin" ' +
- 'src="img/icon.svg" width="38" /></a></div><div ' +
- 'id="navbar"><ul><li><button id="newbutton" type=' +
- '"button" class="hidden">New</button></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- query('.navbar-toggle').classList.contains('collapsed') &&
- query('#navbar').getAttribute('aria-expanded') !== 'true'
- );
- PrivateBin.TopNav.collapseBar();
- results.push(
- query('.navbar-toggle').classList.contains('collapsed') &&
- query('#navbar').getAttribute('aria-expanded') !== 'true'
- );
- /*
- with the upgrade for bootstrap-3.3.7.js to bootstrap-3.4.1.js
- the mobile interface detection changed to check if the
- ontouchstart event exists, which broke this section of the test
- const toggleBtn = document.querySelector('.navbar-toggle');
- toggleBtn.dispatchEvent(new MouseEvent('click'));
- results.push(
- !toggleBtn.classList.contains('collapsed') &&
- document.getElementById('navbar').getAttribute('aria-expanded') == 'true'
- );
- PrivateBin.TopNav.collapseBar();
- results.push(
- document.querySelector('.navbar-toggle').classList.contains('collapsed') &&
- document.getElementById('navbar').getAttribute('aria-expanded') == 'false'
- );
- */
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('resetInput', function () {
- before(function () {
- cleanup();
- });
- it(
- 'reset inputs to defaults (options off)',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
- 'class="hidden"><label><input type="checkbox" ' +
- 'id="burnafterreading" name="burnafterreading" /> ' +
- 'Burn after reading</label></li><li id="opendiscussionoption" ' +
- 'class="hidden"><label><input type="checkbox" ' +
- 'id="opendiscussion" name="opendiscussion" /> ' +
- 'Open discussion</label></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- !PrivateBin.TopNav.getBurnAfterReading()
- );
- results.push(
- !PrivateBin.TopNav.getOpenDiscussion()
- );
- query('#burnafterreading').checked = true;
- query('#opendiscussion').checked = true;
- results.push(
- PrivateBin.TopNav.getBurnAfterReading()
- );
- results.push(
- PrivateBin.TopNav.getOpenDiscussion()
- );
- PrivateBin.TopNav.resetInput();
- results.push(
- !PrivateBin.TopNav.getBurnAfterReading()
- );
- results.push(
- !PrivateBin.TopNav.getOpenDiscussion()
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- it(
- 'reset inputs to defaults (burnafterreading on)',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
- 'class="hidden"><label><input type="checkbox" ' +
- 'id="burnafterreading" name="burnafterreading" checked="checked" /> ' +
- 'Burn after reading</label></li><li id="opendiscussionoption" ' +
- 'class="hidden"><label><input type="checkbox" ' +
- 'id="opendiscussion" name="opendiscussion" checked="checked" /> ' +
- 'Open discussion</label></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- PrivateBin.TopNav.getBurnAfterReading()
- );
- results.push(
- !PrivateBin.TopNav.getOpenDiscussion()
- );
- query('#burnafterreading').checked = false;
- query('#burnafterreading').removeAttribute('checked');
- results.push(
- !PrivateBin.TopNav.getBurnAfterReading()
- );
- results.push(
- !PrivateBin.TopNav.getOpenDiscussion()
- );
- PrivateBin.TopNav.resetInput();
- results.push(
- PrivateBin.TopNav.getBurnAfterReading()
- );
- results.push(
- !PrivateBin.TopNav.getOpenDiscussion()
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- it(
- 'reset inputs to defaults (opendiscussion on)',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
- 'class="hidden"><label><input type="checkbox" ' +
- 'id="burnafterreading" name="burnafterreading" /> ' +
- 'Burn after reading</label></li><li id="opendiscussionoption" ' +
- 'class="hidden"><label><input type="checkbox" ' +
- 'id="opendiscussion" name="opendiscussion" checked="checked" /> ' +
- 'Open discussion</label></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- !PrivateBin.TopNav.getBurnAfterReading()
- );
- results.push(
- PrivateBin.TopNav.getOpenDiscussion()
- );
- query('#opendiscussion').checked = false;
- query('#opendiscussion').removeAttribute('checked');
- query('#burnafterreading').checked = true;
- query('#burnafterreading').setAttribute('checked', 'checked');
- results.push(
- PrivateBin.TopNav.getBurnAfterReading()
- );
- results.push(
- !PrivateBin.TopNav.getOpenDiscussion()
- );
- PrivateBin.TopNav.resetInput();
- results.push(
- !PrivateBin.TopNav.getBurnAfterReading()
- );
- results.push(
- PrivateBin.TopNav.getOpenDiscussion()
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- it(
- 'tolerates a missing discussion option (discussion disabled)',
- function () {
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
- 'class="buttondisabled"><label><input type="checkbox" ' +
- 'id="burnafterreading" name="burnafterreading" /> ' +
- 'Burn after reading</label></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- assert.doesNotThrow(() => PrivateBin.TopNav.resetInput());
- assert.ok(!query('#burnafterreadingoption').classList.contains('buttondisabled'));
- cleanup();
- }
- );
- });
- describe('getExpiration', function () {
- before(function () {
- cleanup();
- });
- it(
- 'returns the currently selected expiration date',
- function () {
- document.documentElement.innerHTML =
- '<select id="pasteExpiration" name="pasteExpiration">' +
- '<option value="1day">1 day</option>' +
- '<option value="never">Never</option></select>';
- PrivateBin.TopNav.init();
- assert.strictEqual(PrivateBin.TopNav.getExpiration(), '1day');
- cleanup();
- }
- );
- });
- describe('getFileList', function () {
- before(function () {
- cleanup();
- });
- const File = window.File,
- FileList = window.FileList,
- path = require('path'), // eslint-disable-line global-require
- mime = require('mime-types'); // eslint-disable-line global-require
- // mocking file input as per https://github.com/jsdom/jsdom/issues/1272
- function createFile(file_path) {
- const lastModified = fs.statSync(file_path).mtimeMs;
- return new File(
- [new fs.readFileSync(file_path)],
- path.basename(file_path),
- {
- lastModified,
- type: mime.lookup(file_path) || ''
- }
- );
- }
- function addFileList(input, file_paths) {
- if (typeof file_paths === 'string') {
- file_paths = [file_paths];
- } else if (!Array.isArray(file_paths)) {
- throw new Error('file_paths needs to be a file path string or an Array of file path strings');
- }
- const file_list = file_paths.map(fp => createFile(fp));
- Object.setPrototypeOf(file_list, Object.create(FileList.prototype));
- Object.defineProperty(input, 'files', {
- value: file_list,
- writeable: false
- });
- return input;
- }
- it(
- 'returns the selected files',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
- 'dropdown"><a href="#" class="dropdown-toggle" data-' +
- 'toggle="dropdown" role="button" aria-haspopup="true" ' +
- 'aria-expanded="false">Attach a file <span class="caret">' +
- '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
- '<div><input type="file" id="file" name="file" /></div>' +
- '</li><li id="customattachment" class="hidden"></li><li>' +
- '<a id="fileremovebutton" href="#">Remove attachment</a>' +
- '</li></ul></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- PrivateBin.TopNav.getFileList() === null
- );
- addFileList(query('#file'), [
- '../img/logo.svg',
- '../img/busy.gif'
- ]);
- const files = PrivateBin.TopNav.getFileList();
- results.push(
- files[0].name === 'logo.svg' &&
- files[1].name === 'busy.gif'
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('getBurnAfterReading', function () {
- before(function () {
- cleanup();
- });
- it(
- 'returns if the burn-after-reading checkbox was ticked',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
- 'class="hidden"><label><input type="checkbox" ' +
- 'id="burnafterreading" name="burnafterreading" /> ' +
- 'Burn after reading</label></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- !PrivateBin.TopNav.getBurnAfterReading()
- );
- query('#burnafterreading').checked = true;
- results.push(
- PrivateBin.TopNav.getBurnAfterReading()
- );
- query('#burnafterreading').checked = false;
- query('#burnafterreading').removeAttribute('checked');
- results.push(
- !PrivateBin.TopNav.getBurnAfterReading()
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('getOpenDiscussion', function () {
- before(function () {
- cleanup();
- });
- it(
- 'returns if the open-discussion checkbox was ticked',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="opendiscussionoption" ' +
- 'class="hidden"><label><input type="checkbox" ' +
- 'id="opendiscussion" name="opendiscussion" /> ' +
- 'Open discussion</label></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- !PrivateBin.TopNav.getOpenDiscussion()
- );
- query('#opendiscussion').checked = true;
- results.push(
- PrivateBin.TopNav.getOpenDiscussion()
- );
- query('#opendiscussion').checked = false;
- query('#opendiscussion').removeAttribute('checked');
- results.push(
- !PrivateBin.TopNav.getOpenDiscussion()
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('getPassword', function () {
- before(function () {
- globalThis.cleanup();
- });
- it('returns the contents of the password input', () => {
- fc.assert(fc.property(
- fc.string(),
- function (password) {
- password = password.replace(/\r+|\n+/g, '');
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li><div id="password" ' +
- 'class="navbar-form hidden"><input type="password" ' +
- 'id="passwordinput" placeholder="Password (recommended)" ' +
- 'class="form-control" size="23" /></div></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- PrivateBin.TopNav.getPassword() === ''
- );
- query('#passwordinput').value = password;
- results.push(
- PrivateBin.TopNav.getPassword() === password
- );
- query('#passwordinput').value = '';
- results.push(
- PrivateBin.TopNav.getPassword() === ''
- );
- globalThis.cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- return result;
- }
- ));
- });
- });
- describe('getCustomAttachment', function () {
- before(function () {
- cleanup();
- });
- it(
- 'returns the custom attachment element',
- function () {
- let results = [];
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
- 'dropdown"><a href="#" class="dropdown-toggle" data-' +
- 'toggle="dropdown" role="button" aria-haspopup="true" ' +
- 'aria-expanded="false">Attach a file <span class="caret">' +
- '</span></a><ul class="dropdown-menu"><li id="filewrap">' +
- '<div><input type="file" id="file" name="file" /></div>' +
- '</li><li id="customattachment" class="hidden"></li><li>' +
- '<a id="fileremovebutton" href="#">Remove attachment</a>' +
- '</li></ul></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- results.push(
- !PrivateBin.TopNav.getCustomAttachment().classList.contains('test')
- );
- query('#customattachment').classList.add('test');
- results.push(
- PrivateBin.TopNav.getCustomAttachment().classList.contains('test')
- );
- cleanup();
- const result = results.every(element => element);
- if (!result) {
- console.log(results);
- }
- assert.ok(result);
- }
- );
- });
- describe('hideAllButtons', function () {
- before(function () {
- cleanup();
- });
- it(
- 'hides all buttons correctly',
- function () {
- // Insert any setup code needed for the hideAllButtons function
- // Example: Initialize the DOM elements required for testing
- document.body.innerHTML =
- '<nav class="navbar navbar-inverse navbar-static-top">' +
- '<div id="navbar" class="navbar-collapse collapse"><ul ' +
- 'class="nav navbar-nav"><li><button id="newbutton" ' +
- 'type="button" class="hidden btn btn-warning navbar-btn">' +
- '<span class="glyphicon glyphicon-file" aria-hidden="true">' +
- '</span> New</button><button id="clonebutton" type="button"' +
- ' class="hidden btn btn-warning navbar-btn">' +
- '<span class="glyphicon glyphicon-duplicate" ' +
- 'aria-hidden="true"></span> Clone</button><button ' +
- 'id="rawtextbutton" type="button" class="hidden btn ' +
- 'btn-warning navbar-btn"><span class="glyphicon ' +
- 'glyphicon-text-background" aria-hidden="true"></span> ' +
- 'Raw text</button><button id="qrcodelink" type="button" ' +
- 'data-toggle="modal" data-target="#qrcodemodal" ' +
- 'class="hidden btn btn-warning navbar-btn"><span ' +
- 'class="glyphicon glyphicon-qrcode" aria-hidden="true">' +
- '</span> QR code</button></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- PrivateBin.TopNav.hideAllButtons();
- assert.ok(query('#newbutton').classList.contains('hidden'));
- assert.ok(query('#clonebutton').classList.contains('hidden'));
- assert.ok(query('#rawtextbutton').classList.contains('hidden'));
- assert.ok(query('#qrcodelink').classList.contains('hidden'));
- cleanup();
- }
- );
- });
- describe('showRetryButton & hideRetryButton', function () {
- afterEach(function () {
- delete global.bootstrap;
- cleanup();
- });
- it(
- 'shows and hides the Bootstrap 5 retry button with its list item and runs the callback once',
- function () {
- cleanup();
- global.bootstrap = {};
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul class="navbar-nav">' +
- '<li class="nav-item hidden"><button id="retrybutton" ' +
- 'type="button" class="hidden">Retry</button></li>' +
- '<li><button id="newbutton" type="button">New</button>' +
- '</li></ul></div></nav>';
- PrivateBin.TopNav.init();
- let calls = 0;
- PrivateBin.TopNav.setRetryCallback(function () {
- calls++;
- });
- const retryItem = query('#retrybutton').parentElement;
- assert.ok(query('#retrybutton').classList.contains('hidden'));
- assert.ok(retryItem.classList.contains('hidden'));
- PrivateBin.TopNav.showRetryButton();
- assert.ok(!query('#retrybutton').classList.contains('hidden'));
- assert.ok(!retryItem.classList.contains('hidden'));
- query('#retrybutton').click();
- assert.strictEqual(calls, 1);
- PrivateBin.TopNav.hideRetryButton();
- assert.ok(query('#retrybutton').classList.contains('hidden'));
- assert.ok(retryItem.classList.contains('hidden'));
- PrivateBin.TopNav.showRetryButton();
- PrivateBin.TopNav.hideRetryButton();
- assert.ok(query('#retrybutton').classList.contains('hidden'));
- assert.ok(retryItem.classList.contains('hidden'));
- assert.ok(!query('#newbutton').classList.contains('hidden'));
- assert.strictEqual(calls, 1);
- }
- );
- it(
- 'toggles only the retry button on legacy Bootstrap 3 and page templates',
- function () {
- cleanup();
- delete global.bootstrap;
- document.documentElement.innerHTML =
- '<nav><div id="navbar"><ul class="nav navbar-nav"><li>' +
- '<button id="retrybutton" type="button" class="hidden">' +
- 'Retry</button><button id="newbutton" type="button">' +
- 'New</button></li></ul></div></nav>';
- PrivateBin.TopNav.init();
- let calls = 0;
- PrivateBin.TopNav.setRetryCallback(function () {
- calls++;
- });
- const retryItem = query('#retrybutton').parentElement;
- assert.ok(query('#retrybutton').classList.contains('hidden'));
- assert.ok(!retryItem.classList.contains('hidden'));
- PrivateBin.TopNav.showRetryButton();
- assert.ok(!query('#retrybutton').classList.contains('hidden'));
- assert.ok(!retryItem.classList.contains('hidden'));
- assert.ok(!query('#newbutton').classList.contains('hidden'));
- query('#retrybutton').click();
- assert.strictEqual(calls, 1);
- PrivateBin.TopNav.hideRetryButton();
- assert.ok(query('#retrybutton').classList.contains('hidden'));
- assert.ok(!retryItem.classList.contains('hidden'));
- assert.ok(!query('#newbutton').classList.contains('hidden'));
- PrivateBin.TopNav.showRetryButton();
- PrivateBin.TopNav.hideRetryButton();
- assert.ok(query('#retrybutton').classList.contains('hidden'));
- assert.strictEqual(calls, 1);
- }
- );
- });
- describe('rawText', function () {
- before(function () {
- cleanup();
- });
- // TODO triggers error messages in jsDOM since version 12, but passes
- it(
- 'displays raw text view correctly',
- function () {
- const clean = globalThis.cleanup('', {url: 'https://privatebin.net/?0123456789abcdef#1'});
- document.documentElement.innerHTML = `
- <li id="loadingindicator" class="hidden"></li>
- <button id="rawtextbutton"></button>`;
- const sample = 'example';
- PrivateBin.Alert.init(); // required because of locading indiator being used
- PrivateBin.TopNav.init();
- PrivateBin.PasteViewer.setText(sample);
- PrivateBin.Helper.reset();
- query('#rawtextbutton').click();
- assert.strictEqual(document.querySelector('pre').textContent, sample);
- clean();
- }
- );
- });
- });
|