From b8d07a42eb211b4bfad6f578c6aa6c8bc51573e9 Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Mon, 23 Nov 2020 13:21:51 -0500 Subject: [PATCH] lint: Run `eslint --fix` on `bin/` and `tests/` --- bin/checkAllPads.js | 55 +- bin/checkPad.js | 53 +- bin/checkPadDeltas.js | 113 +- bin/convert.js | 464 ++++---- bin/createUserSession.js | 8 +- bin/deleteAllGroupSessions.js | 70 +- bin/deletePad.js | 54 +- bin/doc/generate.js | 46 +- bin/doc/html.js | 63 +- bin/doc/json.js | 165 ++- bin/extractPadData.js | 40 +- bin/importSqlFile.js | 99 +- bin/migrateDirtyDBtoRealDB.js | 45 +- bin/plugins/checkPlugin.js | 386 ++++--- bin/rebuildPad.js | 142 +-- bin/repairPad.js | 39 +- tests/backend/common.js | 6 +- tests/backend/fuzzImportTest.js | 59 +- tests/backend/specs/api/api.js | 46 +- tests/backend/specs/api/characterEncoding.js | 100 +- tests/backend/specs/api/chat.js | 112 +- tests/backend/specs/api/importexport.js | 149 ++- .../backend/specs/api/importexportGetPost.js | 122 ++- tests/backend/specs/api/instance.js | 30 +- tests/backend/specs/api/pad.js | 989 +++++++++--------- tests/backend/specs/api/sessionsAndGroups.js | 113 +- tests/backend/specs/api/tidy.js | 40 +- tests/backend/specs/caching_middleware.js | 127 +-- tests/backend/specs/contentcollector.js | 195 ++-- tests/backend/specs/hooks.js | 168 ++- tests/backend/specs/promises.js | 22 +- tests/backend/specs/socketio.js | 82 +- tests/backend/specs/specialpages.js | 12 +- tests/backend/specs/webaccess.js | 282 ++--- tests/container/loadSettings.js | 16 +- tests/container/specs/api/pad.js | 44 +- tests/frontend/helper.js | 193 ++-- tests/frontend/helper/methods.js | 158 ++- tests/frontend/helper/ui.js | 79 +- tests/frontend/runner.js | 184 ++-- tests/frontend/specs/alphabet.js | 23 +- .../frontend/specs/authorship_of_editions.js | 90 +- tests/frontend/specs/bold.js | 58 +- tests/frontend/specs/caret.js | 59 +- tests/frontend/specs/change_user_color.js | 95 +- tests/frontend/specs/change_user_name.js | 63 +- tests/frontend/specs/chat.js | 67 +- tests/frontend/specs/chat_load_messages.js | 98 +- .../frontend/specs/clear_authorship_colors.js | 113 +- tests/frontend/specs/delete.js | 32 +- tests/frontend/specs/drag_and_drop.js | 128 +-- tests/frontend/specs/embed_value.js | 140 ++- tests/frontend/specs/enter.js | 32 +- tests/frontend/specs/font_type.js | 32 +- tests/frontend/specs/helper.js | 316 +++--- tests/frontend/specs/importexport.js | 339 +++--- tests/frontend/specs/importindents.js | 146 ++- tests/frontend/specs/indentation.js | 165 ++- tests/frontend/specs/italic.js | 59 +- tests/frontend/specs/language.js | 168 ++- ...ultiple_authors_clear_authorship_colors.js | 38 +- tests/frontend/specs/ordered_list.js | 182 ++-- tests/frontend/specs/pad_modal.js | 100 +- tests/frontend/specs/redo.js | 53 +- tests/frontend/specs/responsiveness.js | 69 +- .../specs/select_formatting_buttons.js | 142 ++- tests/frontend/specs/strikethrough.js | 32 +- tests/frontend/specs/timeslider.js | 49 +- tests/frontend/specs/timeslider_follow.js | 90 +- tests/frontend/specs/timeslider_labels.js | 36 +- .../specs/timeslider_numeric_padID.js | 16 +- tests/frontend/specs/timeslider_revisions.js | 179 ++-- tests/frontend/specs/undo.js | 53 +- tests/frontend/specs/unordered_list.js | 165 ++- tests/frontend/specs/urls_become_clickable.js | 61 +- tests/frontend/specs/xxauto_reconnect.js | 50 +- tests/frontend/travis/remote_runner.js | 179 ++-- tests/ratelimit/send_changesets.js | 31 +- 78 files changed, 4319 insertions(+), 4599 deletions(-) diff --git a/bin/checkAllPads.js b/bin/checkAllPads.js index 0d4e8bb8d..f90e57aef 100644 --- a/bin/checkAllPads.js +++ b/bin/checkAllPads.js @@ -3,88 +3,85 @@ */ if (process.argv.length != 2) { - console.error("Use: node bin/checkAllPads.js"); + console.error('Use: node bin/checkAllPads.js'); process.exit(1); } // load and initialize NPM -let npm = require('../src/node_modules/npm'); -npm.load({}, async function() { - +const npm = require('../src/node_modules/npm'); +npm.load({}, async () => { try { // initialize the database - let settings = require('../src/node/utils/Settings'); - let db = require('../src/node/db/DB'); + const settings = require('../src/node/utils/Settings'); + const db = require('../src/node/db/DB'); await db.init(); // load modules - let Changeset = require('../src/static/js/Changeset'); - let padManager = require('../src/node/db/PadManager'); + const Changeset = require('../src/static/js/Changeset'); + const padManager = require('../src/node/db/PadManager'); // get all pads - let res = await padManager.listAllPads(); + const res = await padManager.listAllPads(); - for (let padId of res.padIDs) { - - let pad = await padManager.getPad(padId); + for (const padId of res.padIDs) { + const pad = await padManager.getPad(padId); // check if the pad has a pool if (pad.pool === undefined) { - console.error("[" + pad.id + "] Missing attribute pool"); + console.error(`[${pad.id}] Missing attribute pool`); continue; } // create an array with key kevisions // key revisions always save the full pad atext - let head = pad.getHeadRevisionNumber(); - let keyRevisions = []; + const head = pad.getHeadRevisionNumber(); + const keyRevisions = []; for (let rev = 0; rev < head; rev += 100) { keyRevisions.push(rev); } // run through all key revisions - for (let keyRev of keyRevisions) { - + for (const keyRev of keyRevisions) { // create an array of revisions we need till the next keyRevision or the End - var revisionsNeeded = []; - for (let rev = keyRev ; rev <= keyRev + 100 && rev <= head; rev++) { + const revisionsNeeded = []; + for (let rev = keyRev; rev <= keyRev + 100 && rev <= head; rev++) { revisionsNeeded.push(rev); } // this array will hold all revision changesets - var revisions = []; + const revisions = []; // run through all needed revisions and get them from the database - for (let revNum of revisionsNeeded) { - let revision = await db.get("pad:" + pad.id + ":revs:" + revNum); - revisions[revNum] = revision; + for (const revNum of revisionsNeeded) { + const revision = await db.get(`pad:${pad.id}:revs:${revNum}`); + revisions[revNum] = revision; } // check if the revision exists if (revisions[keyRev] == null) { - console.error("[" + pad.id + "] Missing revision " + keyRev); + console.error(`[${pad.id}] Missing revision ${keyRev}`); continue; } // check if there is a atext in the keyRevisions if (revisions[keyRev].meta === undefined || revisions[keyRev].meta.atext === undefined) { - console.error("[" + pad.id + "] Missing atext in revision " + keyRev); + console.error(`[${pad.id}] Missing atext in revision ${keyRev}`); continue; } - let apool = pad.pool; + const apool = pad.pool; let atext = revisions[keyRev].meta.atext; for (let rev = keyRev + 1; rev <= keyRev + 100 && rev <= head; rev++) { try { - let cs = revisions[rev].changeset; + const cs = revisions[rev].changeset; atext = Changeset.applyToAText(cs, atext, apool); } catch (e) { - console.error("[" + pad.id + "] Bad changeset at revision " + i + " - " + e.message); + console.error(`[${pad.id}] Bad changeset at revision ${i} - ${e.message}`); } } } - console.log("finished"); + console.log('finished'); process.exit(0); } } catch (err) { diff --git a/bin/checkPad.js b/bin/checkPad.js index c6a3a1971..323840e72 100644 --- a/bin/checkPad.js +++ b/bin/checkPad.js @@ -3,7 +3,7 @@ */ if (process.argv.length != 3) { - console.error("Use: node bin/checkPad.js $PADID"); + console.error('Use: node bin/checkPad.js $PADID'); process.exit(1); } @@ -11,83 +11,80 @@ if (process.argv.length != 3) { const padId = process.argv[2]; // load and initialize NPM; -let npm = require('../src/node_modules/npm'); -npm.load({}, async function() { - +const npm = require('../src/node_modules/npm'); +npm.load({}, async () => { try { // initialize database - let settings = require('../src/node/utils/Settings'); - let db = require('../src/node/db/DB'); + const settings = require('../src/node/utils/Settings'); + const db = require('../src/node/db/DB'); await db.init(); // load modules - let Changeset = require('ep_etherpad-lite/static/js/Changeset'); - let padManager = require('../src/node/db/PadManager'); + const Changeset = require('ep_etherpad-lite/static/js/Changeset'); + const padManager = require('../src/node/db/PadManager'); - let exists = await padManager.doesPadExists(padId); + const exists = await padManager.doesPadExists(padId); if (!exists) { - console.error("Pad does not exist"); + console.error('Pad does not exist'); process.exit(1); } // get the pad - let pad = await padManager.getPad(padId); + const pad = await padManager.getPad(padId); // create an array with key revisions // key revisions always save the full pad atext - let head = pad.getHeadRevisionNumber(); - let keyRevisions = []; + const head = pad.getHeadRevisionNumber(); + const keyRevisions = []; for (let rev = 0; rev < head; rev += 100) { keyRevisions.push(rev); } // run through all key revisions - for (let keyRev of keyRevisions) { - + for (const keyRev of keyRevisions) { // create an array of revisions we need till the next keyRevision or the End - let revisionsNeeded = []; + const revisionsNeeded = []; for (let rev = keyRev; rev <= keyRev + 100 && rev <= head; rev++) { revisionsNeeded.push(rev); } // this array will hold all revision changesets - var revisions = []; + const revisions = []; // run through all needed revisions and get them from the database - for (let revNum of revisionsNeeded) { - let revision = await db.get("pad:" + padId + ":revs:" + revNum); + for (const revNum of revisionsNeeded) { + const revision = await db.get(`pad:${padId}:revs:${revNum}`); revisions[revNum] = revision; } // check if the pad has a pool - if (pad.pool === undefined ) { - console.error("Attribute pool is missing"); + if (pad.pool === undefined) { + console.error('Attribute pool is missing'); process.exit(1); } // check if there is an atext in the keyRevisions if (revisions[keyRev] === undefined || revisions[keyRev].meta === undefined || revisions[keyRev].meta.atext === undefined) { - console.error("No atext in key revision " + keyRev); + console.error(`No atext in key revision ${keyRev}`); continue; } - let apool = pad.pool; + const apool = pad.pool; let atext = revisions[keyRev].meta.atext; for (let rev = keyRev + 1; rev <= keyRev + 100 && rev <= head; rev++) { try { // console.log("check revision " + rev); - let cs = revisions[rev].changeset; + const cs = revisions[rev].changeset; atext = Changeset.applyToAText(cs, atext, apool); - } catch(e) { - console.error("Bad changeset at revision " + rev + " - " + e.message); + } catch (e) { + console.error(`Bad changeset at revision ${rev} - ${e.message}`); continue; } } - console.log("finished"); + console.log('finished'); process.exit(0); } - } catch (e) { console.trace(e); process.exit(1); diff --git a/bin/checkPadDeltas.js b/bin/checkPadDeltas.js index 80ae4e3a9..1e45f7148 100644 --- a/bin/checkPadDeltas.js +++ b/bin/checkPadDeltas.js @@ -3,7 +3,7 @@ */ if (process.argv.length != 3) { - console.error("Use: node bin/checkPadDeltas.js $PADID"); + console.error('Use: node bin/checkPadDeltas.js $PADID'); process.exit(1); } @@ -11,108 +11,101 @@ if (process.argv.length != 3) { const padId = process.argv[2]; // load and initialize NPM; -var expect = require('expect.js') -var diff = require('diff') -var async = require('async') +const expect = require('expect.js'); +const diff = require('diff'); +var async = require('async'); -let npm = require('../src/node_modules/npm'); -var async = require("ep_etherpad-lite/node_modules/async"); -var Changeset = require("ep_etherpad-lite/static/js/Changeset"); - -npm.load({}, async function() { +const npm = require('../src/node_modules/npm'); +var async = require('ep_etherpad-lite/node_modules/async'); +const Changeset = require('ep_etherpad-lite/static/js/Changeset'); +npm.load({}, async () => { try { // initialize database - let settings = require('../src/node/utils/Settings'); - let db = require('../src/node/db/DB'); + const settings = require('../src/node/utils/Settings'); + const db = require('../src/node/db/DB'); await db.init(); // load modules - let Changeset = require('ep_etherpad-lite/static/js/Changeset'); - let padManager = require('../src/node/db/PadManager'); + const Changeset = require('ep_etherpad-lite/static/js/Changeset'); + const padManager = require('../src/node/db/PadManager'); - let exists = await padManager.doesPadExists(padId); + const exists = await padManager.doesPadExists(padId); if (!exists) { - console.error("Pad does not exist"); + console.error('Pad does not exist'); process.exit(1); } // get the pad - let pad = await padManager.getPad(padId); + const pad = await padManager.getPad(padId); - //create an array with key revisions - //key revisions always save the full pad atext - var head = pad.getHeadRevisionNumber(); - var keyRevisions = []; - for(var i=0;i { + // console.log('Fetching', revNum) + db.db.get(`pad:${padId}:revs:${revNum}`, (err, revision) => { + if (err) return callback(err); - //check if there is a atext in the keyRevisions - if(~keyRevisions.indexOf(revNum) && (revision === undefined || revision.meta === undefined || revision.meta.atext === undefined)) { - console.error("No atext in key revision " + revNum); + // check if there is a atext in the keyRevisions + if (~keyRevisions.indexOf(revNum) && (revision === undefined || revision.meta === undefined || revision.meta.atext === undefined)) { + console.error(`No atext in key revision ${revNum}`); callback(); return; } try { - //console.log("check revision ", revNum); - var cs = revision.changeset; + // console.log("check revision ", revNum); + const cs = revision.changeset; atext = Changeset.applyToAText(cs, atext, pad.pool); - } - catch(e) { - console.error("Bad changeset at revision " + revNum + " - " + e.message); + } catch (e) { + console.error(`Bad changeset at revision ${revNum} - ${e.message}`); callback(); return; } - if(~keyRevisions.indexOf(revNum)) { + if (~keyRevisions.indexOf(revNum)) { try { - expect(revision.meta.atext.text).to.eql(atext.text) - expect(revision.meta.atext.attribs).to.eql(atext.attribs) - }catch(e) { - console.error("Atext in key revision "+revNum+" doesn't match computed one.") - console.log(diff.diffChars(atext.text, revision.meta.atext.text).map(function(op) {if(!op.added && !op.removed) op.value = op.value.length; return op})) - //console.error(e) - //console.log('KeyRev. :', revision.meta.atext) - //console.log('Computed:', atext) - callback() - return + expect(revision.meta.atext.text).to.eql(atext.text); + expect(revision.meta.atext.attribs).to.eql(atext.attribs); + } catch (e) { + console.error(`Atext in key revision ${revNum} doesn't match computed one.`); + console.log(diff.diffChars(atext.text, revision.meta.atext.text).map((op) => { if (!op.added && !op.removed) op.value = op.value.length; return op; })); + // console.error(e) + // console.log('KeyRev. :', revision.meta.atext) + // console.log('Computed:', atext) + callback(); + return; } } - setImmediate(callback) + setImmediate(callback); }); - }, function(er) { - if(pad.atext.text == atext.text) console.log('ok') - else { - console.error('Pad AText doesn\'t match computed one! (Computed ',atext.text.length, ', db', pad.atext.text.length,')') - console.log(diff.diffChars(atext.text, pad.atext.text).map(function(op) {if(!op.added && !op.removed) op.value = op.value.length; return op})) + }, (er) => { + if (pad.atext.text == atext.text) { console.log('ok'); } else { + console.error('Pad AText doesn\'t match computed one! (Computed ', atext.text.length, ', db', pad.atext.text.length, ')'); + console.log(diff.diffChars(atext.text, pad.atext.text).map((op) => { if (!op.added && !op.removed) op.value = op.value.length; return op; })); } - callback(er) + callback(er); }); process.exit(0); - } catch (e) { console.trace(e); process.exit(1); } - }); diff --git a/bin/convert.js b/bin/convert.js index 8caea752f..47f8b2d27 100644 --- a/bin/convert.js +++ b/bin/convert.js @@ -1,120 +1,116 @@ -var startTime = Date.now(); -var fs = require("fs"); -var ueberDB = require("../src/node_modules/ueberdb2"); -var mysql = require("../src/node_modules/ueberdb2/node_modules/mysql"); -var async = require("../src/node_modules/async"); -var Changeset = require("ep_etherpad-lite/static/js/Changeset"); -var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString; -var AttributePool = require("ep_etherpad-lite/static/js/AttributePool"); +const startTime = Date.now(); +const fs = require('fs'); +const ueberDB = require('../src/node_modules/ueberdb2'); +const mysql = require('../src/node_modules/ueberdb2/node_modules/mysql'); +const async = require('../src/node_modules/async'); +const Changeset = require('ep_etherpad-lite/static/js/Changeset'); +const randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString; +const AttributePool = require('ep_etherpad-lite/static/js/AttributePool'); -var settingsFile = process.argv[2]; -var sqlOutputFile = process.argv[3]; +const settingsFile = process.argv[2]; +const sqlOutputFile = process.argv[3]; -//stop if the settings file is not set -if(!settingsFile || !sqlOutputFile) -{ - console.error("Use: node convert.js $SETTINGSFILE $SQLOUTPUT"); +// stop if the settings file is not set +if (!settingsFile || !sqlOutputFile) { + console.error('Use: node convert.js $SETTINGSFILE $SQLOUTPUT'); process.exit(1); } -log("read settings file..."); -//read the settings file and parse the json -var settings = JSON.parse(fs.readFileSync(settingsFile, "utf8")); -log("done"); +log('read settings file...'); +// read the settings file and parse the json +const settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8')); +log('done'); -log("open output file..."); -var sqlOutput = fs.openSync(sqlOutputFile, "w"); -var sql = "SET CHARACTER SET UTF8;\n" + - "CREATE TABLE IF NOT EXISTS `store` ( \n" + - "`key` VARCHAR( 100 ) NOT NULL , \n" + - "`value` LONGTEXT NOT NULL , \n" + - "PRIMARY KEY ( `key` ) \n" + - ") ENGINE = INNODB;\n" + - "START TRANSACTION;\n\n"; +log('open output file...'); +const sqlOutput = fs.openSync(sqlOutputFile, 'w'); +const sql = 'SET CHARACTER SET UTF8;\n' + + 'CREATE TABLE IF NOT EXISTS `store` ( \n' + + '`key` VARCHAR( 100 ) NOT NULL , \n' + + '`value` LONGTEXT NOT NULL , \n' + + 'PRIMARY KEY ( `key` ) \n' + + ') ENGINE = INNODB;\n' + + 'START TRANSACTION;\n\n'; fs.writeSync(sqlOutput, sql); -log("done"); +log('done'); -var etherpadDB = mysql.createConnection({ - host : settings.etherpadDB.host, - user : settings.etherpadDB.user, - password : settings.etherpadDB.password, - database : settings.etherpadDB.database, - port : settings.etherpadDB.port +const etherpadDB = mysql.createConnection({ + host: settings.etherpadDB.host, + user: settings.etherpadDB.user, + password: settings.etherpadDB.password, + database: settings.etherpadDB.database, + port: settings.etherpadDB.port, }); -//get the timestamp once -var timestamp = Date.now(); +// get the timestamp once +const timestamp = Date.now(); -var padIDs; +let padIDs; async.series([ - //get all padids out of the database... - function(callback) { - log("get all padIds out of the database..."); + // get all padids out of the database... + function (callback) { + log('get all padIds out of the database...'); - etherpadDB.query("SELECT ID FROM PAD_META", [], function(err, _padIDs) { + etherpadDB.query('SELECT ID FROM PAD_META', [], (err, _padIDs) => { padIDs = _padIDs; callback(err); }); }, - function(callback) { - log("done"); + function (callback) { + log('done'); - //create a queue with a concurrency 100 - var queue = async.queue(function (padId, callback) { - convertPad(padId, function(err) { + // create a queue with a concurrency 100 + const queue = async.queue((padId, callback) => { + convertPad(padId, (err) => { incrementPadStats(); callback(err); }); }, 100); - //set the step callback as the queue callback + // set the step callback as the queue callback queue.drain = callback; - //add the padids to the worker queue - for(var i=0,length=padIDs.length;i { + if (err) throw err; - //write the groups - var sql = ""; - for(var proID in proID2groupID) - { - var groupID = proID2groupID[proID]; - var subdomain = proID2subdomain[proID]; + // write the groups + let sql = ''; + for (const proID in proID2groupID) { + const groupID = proID2groupID[proID]; + const subdomain = proID2subdomain[proID]; - sql+="REPLACE INTO store VALUES (" + etherpadDB.escape("group:" + groupID) + ", " + etherpadDB.escape(JSON.stringify(groups[groupID]))+ ");\n"; - sql+="REPLACE INTO store VALUES (" + etherpadDB.escape("mapper2group:subdomain:" + subdomain) + ", " + etherpadDB.escape(groupID)+ ");\n"; + sql += `REPLACE INTO store VALUES (${etherpadDB.escape(`group:${groupID}`)}, ${etherpadDB.escape(JSON.stringify(groups[groupID]))});\n`; + sql += `REPLACE INTO store VALUES (${etherpadDB.escape(`mapper2group:subdomain:${subdomain}`)}, ${etherpadDB.escape(groupID)});\n`; } - //close transaction - sql+="COMMIT;"; + // close transaction + sql += 'COMMIT;'; - //end the sql file - fs.writeSync(sqlOutput, sql, undefined, "utf-8"); + // end the sql file + fs.writeSync(sqlOutput, sql, undefined, 'utf-8'); fs.closeSync(sqlOutput); - log("finished."); + log('finished.'); process.exit(0); }); function log(str) { - console.log((Date.now() - startTime)/1000 + "\t" + str); + console.log(`${(Date.now() - startTime) / 1000}\t${str}`); } -var padsDone = 0; +let padsDone = 0; function incrementPadStats() { padsDone++; - if(padsDone%100 == 0) - { - var averageTime = Math.round(padsDone/((Date.now() - startTime)/1000)); - log(padsDone + "/" + padIDs.length + "\t" + averageTime + " pad/s") + if (padsDone % 100 == 0) { + const averageTime = Math.round(padsDone / ((Date.now() - startTime) / 1000)); + log(`${padsDone}/${padIDs.length}\t${averageTime} pad/s`); } } @@ -123,275 +119,245 @@ var proID2subdomain = {}; var groups = {}; function convertPad(padId, callback) { - var changesets = []; - var changesetsMeta = []; - var chatMessages = []; - var authors = []; - var apool; - var subdomain; - var padmeta; + const changesets = []; + const changesetsMeta = []; + const chatMessages = []; + const authors = []; + let apool; + let subdomain; + let padmeta; async.series([ - //get all needed db values - function(callback) { + // get all needed db values + function (callback) { async.parallel([ - //get the pad revisions - function(callback) { - var sql = "SELECT * FROM `PAD_CHAT_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_CHAT_META` WHERE ID=?)"; + // get the pad revisions + function (callback) { + const sql = 'SELECT * FROM `PAD_CHAT_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_CHAT_META` WHERE ID=?)'; - etherpadDB.query(sql, [padId], function(err, results) { - if(!err) - { - try - { - //parse the pages - for(var i=0,length=results.length;i { + if (!err) { + try { + // parse the pages + for (let i = 0, length = results.length; i < length; i++) { parsePage(chatMessages, results[i].PAGESTART, results[i].OFFSETS, results[i].DATA, true); } - }catch(e) {err = e} + } catch (e) { err = e; } } callback(err); }); }, - //get the chat entries - function(callback) { - var sql = "SELECT * FROM `PAD_REVS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVS_META` WHERE ID=?)"; + // get the chat entries + function (callback) { + const sql = 'SELECT * FROM `PAD_REVS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVS_META` WHERE ID=?)'; - etherpadDB.query(sql, [padId], function(err, results) { - if(!err) - { - try - { - //parse the pages - for(var i=0,length=results.length;i { + if (!err) { + try { + // parse the pages + for (let i = 0, length = results.length; i < length; i++) { parsePage(changesets, results[i].PAGESTART, results[i].OFFSETS, results[i].DATA, false); } - }catch(e) {err = e} + } catch (e) { err = e; } } callback(err); }); }, - //get the pad revisions meta data - function(callback) { - var sql = "SELECT * FROM `PAD_REVMETA_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVMETA_META` WHERE ID=?)"; + // get the pad revisions meta data + function (callback) { + const sql = 'SELECT * FROM `PAD_REVMETA_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVMETA_META` WHERE ID=?)'; - etherpadDB.query(sql, [padId], function(err, results) { - if(!err) - { - try - { - //parse the pages - for(var i=0,length=results.length;i { + if (!err) { + try { + // parse the pages + for (let i = 0, length = results.length; i < length; i++) { parsePage(changesetsMeta, results[i].PAGESTART, results[i].OFFSETS, results[i].DATA, true); } - }catch(e) {err = e} + } catch (e) { err = e; } } callback(err); }); }, - //get the attribute pool of this pad - function(callback) { - var sql = "SELECT `JSON` FROM `PAD_APOOL` WHERE `ID` = ?"; + // get the attribute pool of this pad + function (callback) { + const sql = 'SELECT `JSON` FROM `PAD_APOOL` WHERE `ID` = ?'; - etherpadDB.query(sql, [padId], function(err, results) { - if(!err) - { - try - { - apool=JSON.parse(results[0].JSON).x; - }catch(e) {err = e} + etherpadDB.query(sql, [padId], (err, results) => { + if (!err) { + try { + apool = JSON.parse(results[0].JSON).x; + } catch (e) { err = e; } } callback(err); }); }, - //get the authors informations - function(callback) { - var sql = "SELECT * FROM `PAD_AUTHORS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_AUTHORS_META` WHERE ID=?)"; + // get the authors informations + function (callback) { + const sql = 'SELECT * FROM `PAD_AUTHORS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_AUTHORS_META` WHERE ID=?)'; - etherpadDB.query(sql, [padId], function(err, results) { - if(!err) - { - try - { - //parse the pages - for(var i=0, length=results.length;i { + if (!err) { + try { + // parse the pages + for (let i = 0, length = results.length; i < length; i++) { parsePage(authors, results[i].PAGESTART, results[i].OFFSETS, results[i].DATA, true); } - }catch(e) {err = e} + } catch (e) { err = e; } } callback(err); }); }, - //get the pad information - function(callback) { - var sql = "SELECT JSON FROM `PAD_META` WHERE ID=?"; + // get the pad information + function (callback) { + const sql = 'SELECT JSON FROM `PAD_META` WHERE ID=?'; - etherpadDB.query(sql, [padId], function(err, results) { - if(!err) - { - try - { + etherpadDB.query(sql, [padId], (err, results) => { + if (!err) { + try { padmeta = JSON.parse(results[0].JSON).x; - }catch(e) {err = e} + } catch (e) { err = e; } } callback(err); }); }, - //get the subdomain - function(callback) { - //skip if this is no proPad - if(padId.indexOf("$") == -1) - { + // get the subdomain + function (callback) { + // skip if this is no proPad + if (padId.indexOf('$') == -1) { callback(); return; } - //get the proID out of this padID - var proID = padId.split("$")[0]; + // get the proID out of this padID + const proID = padId.split('$')[0]; - var sql = "SELECT subDomain FROM pro_domains WHERE ID = ?"; + const sql = 'SELECT subDomain FROM pro_domains WHERE ID = ?'; - etherpadDB.query(sql, [proID], function(err, results) { - if(!err) - { + etherpadDB.query(sql, [proID], (err, results) => { + if (!err) { subdomain = results[0].subDomain; } callback(err); }); - } + }, ], callback); }, - function(callback) { - //saves all values that should be written to the database - var values = {}; + function (callback) { + // saves all values that should be written to the database + const values = {}; - //this is a pro pad, let's convert it to a group pad - if(padId.indexOf("$") != -1) - { - var padIdParts = padId.split("$"); - var proID = padIdParts[0]; - var padName = padIdParts[1]; + // this is a pro pad, let's convert it to a group pad + if (padId.indexOf('$') != -1) { + const padIdParts = padId.split('$'); + const proID = padIdParts[0]; + const padName = padIdParts[1]; - var groupID + let groupID; - //this proID is not converted so far, do it - if(proID2groupID[proID] == null) - { - groupID = "g." + randomString(16); + // this proID is not converted so far, do it + if (proID2groupID[proID] == null) { + groupID = `g.${randomString(16)}`; - //create the mappers for this new group + // create the mappers for this new group proID2groupID[proID] = groupID; proID2subdomain[proID] = subdomain; groups[groupID] = {pads: {}}; } - //use the generated groupID; + // use the generated groupID; groupID = proID2groupID[proID]; - //rename the pad - padId = groupID + "$" + padName; + // rename the pad + padId = `${groupID}$${padName}`; - //set the value for this pad in the group + // set the value for this pad in the group groups[groupID].pads[padId] = 1; } - try - { - var newAuthorIDs = {}; - var oldName2newName = {}; + try { + const newAuthorIDs = {}; + const oldName2newName = {}; - //replace the authors with generated authors + // replace the authors with generated authors // we need to do that cause where the original etherpad saves pad local authors, the new (lite) etherpad uses them global - for(var i in apool.numToAttrib) - { + for (var i in apool.numToAttrib) { var key = apool.numToAttrib[i][0]; - var value = apool.numToAttrib[i][1]; + const value = apool.numToAttrib[i][1]; - //skip non authors and anonymous authors - if(key != "author" || value == "") - continue; + // skip non authors and anonymous authors + if (key != 'author' || value == '') continue; - //generate new author values - var authorID = "a." + randomString(16); - var authorColorID = authors[i].colorId || Math.floor(Math.random()*(exports.getColorPalette().length)); - var authorName = authors[i].name || null; + // generate new author values + const authorID = `a.${randomString(16)}`; + const authorColorID = authors[i].colorId || Math.floor(Math.random() * (exports.getColorPalette().length)); + const authorName = authors[i].name || null; - //overwrite the authorID of the attribute pool + // overwrite the authorID of the attribute pool apool.numToAttrib[i][1] = authorID; - //write the author to the database - values["globalAuthor:" + authorID] = {"colorId" : authorColorID, "name": authorName, "timestamp": timestamp}; + // write the author to the database + values[`globalAuthor:${authorID}`] = {colorId: authorColorID, name: authorName, timestamp}; - //save in mappers + // save in mappers newAuthorIDs[i] = authorID; oldName2newName[value] = authorID; } - //save all revisions - for(var i=0;i __dirname + '/../' + f; +const m = (f) => `${__dirname}/../${f}`; const fs = require('fs'); const path = require('path'); @@ -12,10 +12,10 @@ const settings = require(m('src/node/utils/Settings')); const supertest = require(m('src/node_modules/supertest')); (async () => { - const api = supertest('http://'+settings.ip+':'+settings.port); + const api = supertest(`http://${settings.ip}:${settings.port}`); const filePath = path.join(__dirname, '../APIKEY.txt'); - const apikey = fs.readFileSync(filePath, {encoding: 'utf-8'}); + const apikey = fs.readFileSync(filePath, {encoding: 'utf-8'}); let res; @@ -43,5 +43,5 @@ const supertest = require(m('src/node_modules/supertest')); res = await api.post(uri('createSession', {apikey, groupID, authorID, validUntil})); if (res.body.code === 1) throw new Error(`Error creating session: ${res.body}`); console.log('Session made: ====> create a cookie named sessionID and set the value to', - res.body.data.sessionID); + res.body.data.sessionID); })(); diff --git a/bin/deleteAllGroupSessions.js b/bin/deleteAllGroupSessions.js index cda4a3a59..ee0058ffa 100644 --- a/bin/deleteAllGroupSessions.js +++ b/bin/deleteAllGroupSessions.js @@ -4,48 +4,48 @@ */ const request = require('../src/node_modules/request'); -const settings = require(__dirname+'/../tests/container/loadSettings').loadSettings(); -const supertest = require(__dirname+'/../src/node_modules/supertest'); -const api = supertest('http://'+settings.ip+":"+settings.port); +const settings = require(`${__dirname}/../tests/container/loadSettings`).loadSettings(); +const supertest = require(`${__dirname}/../src/node_modules/supertest`); +const api = supertest(`http://${settings.ip}:${settings.port}`); const path = require('path'); const fs = require('fs'); // get the API Key -var filePath = path.join(__dirname, '../APIKEY.txt'); -var apikey = fs.readFileSync(filePath, {encoding: 'utf-8'}); +const filePath = path.join(__dirname, '../APIKEY.txt'); +const apikey = fs.readFileSync(filePath, {encoding: 'utf-8'}); // Set apiVersion to base value, we change this later. -var apiVersion = 1; -var guids; +let apiVersion = 1; +let guids; // Update the apiVersion api.get('/api/') -.expect(function(res){ - apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); - return; -}) -.then(function(){ - let guri = '/api/'+apiVersion+'/listAllGroups?apikey='+apikey; - api.get(guri) - .then(function(res){ - guids = res.body.data.groupIDs; - guids.forEach(function(groupID){ - let luri = '/api/'+apiVersion+'/listSessionsOfGroup?apikey='+apikey + "&groupID="+groupID; - api.get(luri) - .then(function(res){ - if(res.body.data){ - Object.keys(res.body.data).forEach(function(sessionID){ - if(sessionID){ - console.log("Deleting", sessionID); - let duri = '/api/'+apiVersion+'/deleteSession?apikey='+apikey + "&sessionID="+sessionID; - api.post(duri); // deletes - } - }) - }else{ - // no session in this group. - } - }) + .expect((res) => { + apiVersion = res.body.currentVersion; + if (!res.body.currentVersion) throw new Error('No version set in API'); + return; }) - }) -}) + .then(() => { + const guri = `/api/${apiVersion}/listAllGroups?apikey=${apikey}`; + api.get(guri) + .then((res) => { + guids = res.body.data.groupIDs; + guids.forEach((groupID) => { + const luri = `/api/${apiVersion}/listSessionsOfGroup?apikey=${apikey}&groupID=${groupID}`; + api.get(luri) + .then((res) => { + if (res.body.data) { + Object.keys(res.body.data).forEach((sessionID) => { + if (sessionID) { + console.log('Deleting', sessionID); + const duri = `/api/${apiVersion}/deleteSession?apikey=${apikey}&sessionID=${sessionID}`; + api.post(duri); // deletes + } + }); + } else { + // no session in this group. + } + }); + }); + }); + }); diff --git a/bin/deletePad.js b/bin/deletePad.js index 2ce82f8a4..e145d63a0 100644 --- a/bin/deletePad.js +++ b/bin/deletePad.js @@ -4,47 +4,45 @@ */ const request = require('../src/node_modules/request'); -const settings = require(__dirname+'/../tests/container/loadSettings').loadSettings(); -const supertest = require(__dirname+'/../src/node_modules/supertest'); -const api = supertest('http://'+settings.ip+":"+settings.port); +const settings = require(`${__dirname}/../tests/container/loadSettings`).loadSettings(); +const supertest = require(`${__dirname}/../src/node_modules/supertest`); +const api = supertest(`http://${settings.ip}:${settings.port}`); const path = require('path'); const fs = require('fs'); if (process.argv.length != 3) { - console.error("Use: node deletePad.js $PADID"); + console.error('Use: node deletePad.js $PADID'); process.exit(1); } // get the padID -let padId = process.argv[2]; +const padId = process.argv[2]; // get the API Key -var filePath = path.join(__dirname, '../APIKEY.txt'); -var apikey = fs.readFileSync(filePath, {encoding: 'utf-8'}); +const filePath = path.join(__dirname, '../APIKEY.txt'); +const apikey = fs.readFileSync(filePath, {encoding: 'utf-8'}); // Set apiVersion to base value, we change this later. -var apiVersion = 1; +let apiVersion = 1; // Update the apiVersion api.get('/api/') - .expect(function(res){ - apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); - return; - }) - .end(function(err, res){ - + .expect((res) => { + apiVersion = res.body.currentVersion; + if (!res.body.currentVersion) throw new Error('No version set in API'); + return; + }) + .end((err, res) => { // Now we know the latest API version, let's delete pad - var uri = '/api/'+apiVersion+'/deletePad?apikey='+apikey+'&padID='+padId; - api.post(uri) - .expect(function(res){ - if (res.body.code === 1){ - console.error("Error deleting pad", res.body); - }else{ - console.log("Deleted pad", res.body); - } - return; - }) - .end(function(){}) - }); + const uri = `/api/${apiVersion}/deletePad?apikey=${apikey}&padID=${padId}`; + api.post(uri) + .expect((res) => { + if (res.body.code === 1) { + console.error('Error deleting pad', res.body); + } else { + console.log('Deleted pad', res.body); + } + return; + }) + .end(() => {}); + }); // end - diff --git a/bin/doc/generate.js b/bin/doc/generate.js index b3a2c2ace..803f5017e 100644 --- a/bin/doc/generate.js +++ b/bin/doc/generate.js @@ -20,19 +20,19 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -var marked = require('marked'); -var fs = require('fs'); -var path = require('path'); +const marked = require('marked'); +const fs = require('fs'); +const path = require('path'); // parse the args. // Don't use nopt or whatever for this. It's simple enough. -var args = process.argv.slice(2); -var format = 'json'; -var template = null; -var inputFile = null; +const args = process.argv.slice(2); +let format = 'json'; +let template = null; +let inputFile = null; -args.forEach(function (arg) { +args.forEach((arg) => { if (!arg.match(/^\-\-/)) { inputFile = arg; } else if (arg.match(/^\-\-format=/)) { @@ -40,7 +40,7 @@ args.forEach(function (arg) { } else if (arg.match(/^\-\-template=/)) { template = arg.replace(/^\-\-template=/, ''); } -}) +}); if (!inputFile) { @@ -49,25 +49,25 @@ if (!inputFile) { console.error('Input file = %s', inputFile); -fs.readFile(inputFile, 'utf8', function(er, input) { +fs.readFile(inputFile, 'utf8', (er, input) => { if (er) throw er; // process the input for @include lines processIncludes(inputFile, input, next); }); -var includeExpr = /^@include\s+([A-Za-z0-9-_\/]+)(?:\.)?([a-zA-Z]*)$/gmi; -var includeData = {}; +const includeExpr = /^@include\s+([A-Za-z0-9-_\/]+)(?:\.)?([a-zA-Z]*)$/gmi; +const includeData = {}; function processIncludes(inputFile, input, cb) { - var includes = input.match(includeExpr); + const includes = input.match(includeExpr); if (includes === null) return cb(null, input); - var errState = null; + let errState = null; console.error(includes); - var incCount = includes.length; + let incCount = includes.length; if (incCount === 0) cb(null, input); - includes.forEach(function(include) { - var fname = include.replace(/^@include\s+/, ''); + includes.forEach((include) => { + let fname = include.replace(/^@include\s+/, ''); if (!fname.match(/\.md$/)) fname += '.md'; if (includeData.hasOwnProperty(fname)) { @@ -78,11 +78,11 @@ function processIncludes(inputFile, input, cb) { } } - var fullFname = path.resolve(path.dirname(inputFile), fname); - fs.readFile(fullFname, 'utf8', function(er, inc) { + const fullFname = path.resolve(path.dirname(inputFile), fname); + fs.readFile(fullFname, 'utf8', (er, inc) => { if (errState) return; if (er) return cb(errState = er); - processIncludes(fullFname, inc, function(er, inc) { + processIncludes(fullFname, inc, (er, inc) => { if (errState) return; if (er) return cb(errState = er); incCount--; @@ -101,20 +101,20 @@ function next(er, input) { if (er) throw er; switch (format) { case 'json': - require('./json.js')(input, inputFile, function(er, obj) { + require('./json.js')(input, inputFile, (er, obj) => { console.log(JSON.stringify(obj, null, 2)); if (er) throw er; }); break; case 'html': - require('./html.js')(input, inputFile, template, function(er, html) { + require('./html.js')(input, inputFile, template, (er, html) => { if (er) throw er; console.log(html); }); break; default: - throw new Error('Invalid format: ' + format); + throw new Error(`Invalid format: ${format}`); } } diff --git a/bin/doc/html.js b/bin/doc/html.js index 700ab18cc..26cf3f185 100644 --- a/bin/doc/html.js +++ b/bin/doc/html.js @@ -19,15 +19,15 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -var fs = require('fs'); -var marked = require('marked'); -var path = require('path'); +const fs = require('fs'); +const marked = require('marked'); +const path = require('path'); module.exports = toHTML; function toHTML(input, filename, template, cb) { - var lexed = marked.lexer(input); - fs.readFile(template, 'utf8', function(er, template) { + const lexed = marked.lexer(input); + fs.readFile(template, 'utf8', (er, template) => { if (er) return cb(er); render(lexed, filename, template, cb); }); @@ -35,7 +35,7 @@ function toHTML(input, filename, template, cb) { function render(lexed, filename, template, cb) { // get the section - var section = getSection(lexed); + const section = getSection(lexed); filename = path.basename(filename, '.md'); @@ -43,7 +43,7 @@ function render(lexed, filename, template, cb) { // generate the table of contents. // this mutates the lexed contents in-place. - buildToc(lexed, filename, function(er, toc) { + buildToc(lexed, filename, (er, toc) => { if (er) return cb(er); template = template.replace(/__FILENAME__/g, filename); @@ -63,11 +63,11 @@ function render(lexed, filename, template, cb) { // just update the list item text in-place. // lists that come right after a heading are what we're after. function parseLists(input) { - var state = null; - var depth = 0; - var output = []; + let state = null; + let depth = 0; + const output = []; output.links = input.links; - input.forEach(function(tok) { + input.forEach((tok) => { if (state === null) { if (tok.type === 'heading') { state = 'AFTERHEADING'; @@ -79,7 +79,7 @@ function parseLists(input) { if (tok.type === 'list_start') { state = 'LIST'; if (depth === 0) { - output.push({ type:'html', text: '
' }); + output.push({type: 'html', text: '
'}); } depth++; output.push(tok); @@ -99,7 +99,7 @@ function parseLists(input) { depth--; if (depth === 0) { state = null; - output.push({ type:'html', text: '
' }); + output.push({type: 'html', text: '
'}); } output.push(tok); return; @@ -117,16 +117,16 @@ function parseLists(input) { function parseListItem(text) { text = text.replace(/\{([^\}]+)\}/, '$1'); - //XXX maybe put more stuff here? + // XXX maybe put more stuff here? return text; } // section is just the first heading function getSection(lexed) { - var section = ''; - for (var i = 0, l = lexed.length; i < l; i++) { - var tok = lexed[i]; + const section = ''; + for (let i = 0, l = lexed.length; i < l; i++) { + const tok = lexed[i]; if (tok.type === 'heading') return tok.text; } return ''; @@ -134,40 +134,39 @@ function getSection(lexed) { function buildToc(lexed, filename, cb) { - var indent = 0; - var toc = []; - var depth = 0; - lexed.forEach(function(tok) { + const indent = 0; + let toc = []; + let depth = 0; + lexed.forEach((tok) => { if (tok.type !== 'heading') return; if (tok.depth - depth > 1) { - return cb(new Error('Inappropriate heading level\n' + - JSON.stringify(tok))); + return cb(new Error(`Inappropriate heading level\n${ + JSON.stringify(tok)}`)); } depth = tok.depth; - var id = getId(filename + '_' + tok.text.trim()); - toc.push(new Array((depth - 1) * 2 + 1).join(' ') + - '* ' + - tok.text + ''); - tok.text += '#'; + const id = getId(`${filename}_${tok.text.trim()}`); + toc.push(`${new Array((depth - 1) * 2 + 1).join(' ') + }* ${ + tok.text}`); + tok.text += `#`; }); toc = marked.parse(toc.join('\n')); cb(null, toc); } -var idCounters = {}; +const idCounters = {}; function getId(text) { text = text.toLowerCase(); text = text.replace(/[^a-z0-9]+/g, '_'); text = text.replace(/^_+|_+$/, ''); text = text.replace(/^([^a-z])/, '_$1'); if (idCounters.hasOwnProperty(text)) { - text += '_' + (++idCounters[text]); + text += `_${++idCounters[text]}`; } else { idCounters[text] = 0; } return text; } - diff --git a/bin/doc/json.js b/bin/doc/json.js index a404675b5..3ce62a301 100644 --- a/bin/doc/json.js +++ b/bin/doc/json.js @@ -24,24 +24,24 @@ module.exports = doJSON; // Take the lexed input, and return a JSON-encoded object // A module looks like this: https://gist.github.com/1777387 -var marked = require('marked'); +const marked = require('marked'); function doJSON(input, filename, cb) { - var root = {source: filename}; - var stack = [root]; - var depth = 0; - var current = root; - var state = null; - var lexed = marked.lexer(input); - lexed.forEach(function (tok) { - var type = tok.type; - var text = tok.text; + const root = {source: filename}; + const stack = [root]; + let depth = 0; + let current = root; + let state = null; + const lexed = marked.lexer(input); + lexed.forEach((tok) => { + const type = tok.type; + let text = tok.text; // // This is for cases where the markdown semantic structure is lacking. if (type === 'paragraph' || type === 'html') { - var metaExpr = /\n*/g; - text = text.replace(metaExpr, function(_0, k, v) { + const metaExpr = /\n*/g; + text = text.replace(metaExpr, (_0, k, v) => { current[k.trim()] = v.trim(); return ''; }); @@ -52,8 +52,8 @@ function doJSON(input, filename, cb) { if (type === 'heading' && !text.trim().match(/^example/i)) { if (tok.depth - depth > 1) { - return cb(new Error('Inappropriate heading level\n'+ - JSON.stringify(tok))); + return cb(new Error(`Inappropriate heading level\n${ + JSON.stringify(tok)}`)); } // Sometimes we have two headings with a single @@ -61,7 +61,7 @@ function doJSON(input, filename, cb) { if (current && state === 'AFTERHEADING' && depth === tok.depth) { - var clone = current; + const clone = current; current = newSection(tok); current.clone = clone; // don't keep it around on the stack. @@ -75,7 +75,7 @@ function doJSON(input, filename, cb) { // root is always considered the level=0 section, // and the lowest heading is 1, so this should always // result in having a valid parent node. - var d = tok.depth; + let d = tok.depth; while (d <= depth) { finishSection(stack.pop(), stack[stack.length - 1]); d++; @@ -98,7 +98,7 @@ function doJSON(input, filename, cb) { // // If one of these isn't found, then anything that comes between // here and the next heading should be parsed as the desc. - var stability + let stability; if (state === 'AFTERHEADING') { if (type === 'code' && (stability = text.match(/^Stability: ([0-5])(?:\s*-\s*)?(.*)$/))) { @@ -138,7 +138,6 @@ function doJSON(input, filename, cb) { current.desc = current.desc || []; current.desc.push(tok); - }); // finish any sections left open @@ -146,7 +145,7 @@ function doJSON(input, filename, cb) { finishSection(current, stack[stack.length - 1]); } - return cb(null, root) + return cb(null, root); } @@ -193,14 +192,14 @@ function doJSON(input, filename, cb) { // default: 'false' } ] } ] function processList(section) { - var list = section.list; - var values = []; - var current; - var stack = []; + const list = section.list; + const values = []; + let current; + const stack = []; // for now, *just* build the hierarchical list - list.forEach(function(tok) { - var type = tok.type; + list.forEach((tok) => { + const type = tok.type; if (type === 'space') return; if (type === 'list_item_start') { if (!current) { @@ -217,26 +216,26 @@ function processList(section) { return; } else if (type === 'list_item_end') { if (!current) { - throw new Error('invalid list - end without current item\n' + - JSON.stringify(tok) + '\n' + - JSON.stringify(list)); + throw new Error(`invalid list - end without current item\n${ + JSON.stringify(tok)}\n${ + JSON.stringify(list)}`); } current = stack.pop(); } else if (type === 'text') { if (!current) { - throw new Error('invalid list - text without current item\n' + - JSON.stringify(tok) + '\n' + - JSON.stringify(list)); + throw new Error(`invalid list - text without current item\n${ + JSON.stringify(tok)}\n${ + JSON.stringify(list)}`); } current.textRaw = current.textRaw || ''; - current.textRaw += tok.text + ' '; + current.textRaw += `${tok.text} `; } }); // shove the name in there for properties, since they are always // just going to be the value etc. if (section.type === 'property' && values[0]) { - values[0].textRaw = '`' + section.name + '` ' + values[0].textRaw; + values[0].textRaw = `\`${section.name}\` ${values[0].textRaw}`; } // now pull the actual values out of the text bits. @@ -252,9 +251,9 @@ function processList(section) { // each item is an argument, unless the name is 'return', // in which case it's the return value. section.signatures = section.signatures || []; - var sig = {} + var sig = {}; section.signatures.push(sig); - sig.params = values.filter(function(v) { + sig.params = values.filter((v) => { if (v.name === 'return') { sig.return = v; return false; @@ -271,7 +270,7 @@ function processList(section) { delete value.name; section.typeof = value.type; delete value.type; - Object.keys(value).forEach(function(k) { + Object.keys(value).forEach((k) => { section[k] = value[k]; }); break; @@ -289,36 +288,36 @@ function processList(section) { // textRaw = "someobject.someMethod(a, [b=100], [c])" function parseSignature(text, sig) { - var params = text.match(paramExpr); + let params = text.match(paramExpr); if (!params) return; params = params[1]; // the ] is irrelevant. [ indicates optionalness. params = params.replace(/\]/g, ''); - params = params.split(/,/) - params.forEach(function(p, i, _) { + params = params.split(/,/); + params.forEach((p, i, _) => { p = p.trim(); if (!p) return; - var param = sig.params[i]; - var optional = false; - var def; + let param = sig.params[i]; + let optional = false; + let def; // [foo] -> optional if (p.charAt(0) === '[') { optional = true; p = p.substr(1); } - var eq = p.indexOf('='); + const eq = p.indexOf('='); if (eq !== -1) { def = p.substr(eq + 1); p = p.substr(0, eq); } if (!param) { - param = sig.params[i] = { name: p }; + param = sig.params[i] = {name: p}; } // at this point, the name should match. if (p !== param.name) { console.error('Warning: invalid param "%s"', p); - console.error(' > ' + JSON.stringify(param)); - console.error(' > ' + text); + console.error(` > ${JSON.stringify(param)}`); + console.error(` > ${text}`); } if (optional) param.optional = true; if (def !== undefined) param.default = def; @@ -332,18 +331,18 @@ function parseListItem(item) { // the goal here is to find the name, type, default, and optional. // anything left over is 'desc' - var text = item.textRaw.trim(); + let text = item.textRaw.trim(); // text = text.replace(/^(Argument|Param)s?\s*:?\s*/i, ''); text = text.replace(/^, /, '').trim(); - var retExpr = /^returns?\s*:?\s*/i; - var ret = text.match(retExpr); + const retExpr = /^returns?\s*:?\s*/i; + const ret = text.match(retExpr); if (ret) { item.name = 'return'; text = text.replace(retExpr, ''); } else { - var nameExpr = /^['`"]?([^'`": \{]+)['`"]?\s*:?\s*/; - var name = text.match(nameExpr); + const nameExpr = /^['`"]?([^'`": \{]+)['`"]?\s*:?\s*/; + const name = text.match(nameExpr); if (name) { item.name = name[1]; text = text.replace(nameExpr, ''); @@ -351,24 +350,24 @@ function parseListItem(item) { } text = text.trim(); - var defaultExpr = /\(default\s*[:=]?\s*['"`]?([^, '"`]*)['"`]?\)/i; - var def = text.match(defaultExpr); + const defaultExpr = /\(default\s*[:=]?\s*['"`]?([^, '"`]*)['"`]?\)/i; + const def = text.match(defaultExpr); if (def) { item.default = def[1]; text = text.replace(defaultExpr, ''); } text = text.trim(); - var typeExpr = /^\{([^\}]+)\}/; - var type = text.match(typeExpr); + const typeExpr = /^\{([^\}]+)\}/; + const type = text.match(typeExpr); if (type) { item.type = type[1]; text = text.replace(typeExpr, ''); } text = text.trim(); - var optExpr = /^Optional\.|(?:, )?Optional$/; - var optional = text.match(optExpr); + const optExpr = /^Optional\.|(?:, )?Optional$/; + const optional = text.match(optExpr); if (optional) { item.optional = true; text = text.replace(optExpr, ''); @@ -382,9 +381,9 @@ function parseListItem(item) { function finishSection(section, parent) { if (!section || !parent) { - throw new Error('Invalid finishSection call\n'+ - JSON.stringify(section) + '\n' + - JSON.stringify(parent)); + throw new Error(`Invalid finishSection call\n${ + JSON.stringify(section)}\n${ + JSON.stringify(parent)}`); } if (!section.type) { @@ -394,7 +393,7 @@ function finishSection(section, parent) { } section.displayName = section.name; section.name = section.name.toLowerCase() - .trim().replace(/\s+/g, '_'); + .trim().replace(/\s+/g, '_'); } if (section.desc && Array.isArray(section.desc)) { @@ -411,10 +410,10 @@ function finishSection(section, parent) { // Merge them into the parent. if (section.type === 'class' && section.ctors) { section.signatures = section.signatures || []; - var sigs = section.signatures; - section.ctors.forEach(function(ctor) { + const sigs = section.signatures; + section.ctors.forEach((ctor) => { ctor.signatures = ctor.signatures || [{}]; - ctor.signatures.forEach(function(sig) { + ctor.signatures.forEach((sig) => { sig.desc = ctor.desc; }); sigs.push.apply(sigs, ctor.signatures); @@ -425,7 +424,7 @@ function finishSection(section, parent) { // properties are a bit special. // their "type" is the type of object, not "property" if (section.properties) { - section.properties.forEach(function (p) { + section.properties.forEach((p) => { if (p.typeof) p.type = p.typeof; else delete p.type; delete p.typeof; @@ -434,27 +433,27 @@ function finishSection(section, parent) { // handle clones if (section.clone) { - var clone = section.clone; + const clone = section.clone; delete section.clone; delete clone.clone; deepCopy(section, clone); finishSection(clone, parent); } - var plur; + let plur; if (section.type.slice(-1) === 's') { - plur = section.type + 'es'; + plur = `${section.type}es`; } else if (section.type.slice(-1) === 'y') { plur = section.type.replace(/y$/, 'ies'); } else { - plur = section.type + 's'; + plur = `${section.type}s`; } // if the parent's type is 'misc', then it's just a random // collection of stuff, like the "globals" section. // Make the children top-level items. if (section.type === 'misc') { - Object.keys(section).forEach(function(k) { + Object.keys(section).forEach((k) => { switch (k) { case 'textRaw': case 'name': @@ -486,9 +485,7 @@ function finishSection(section, parent) { // Not a general purpose deep copy. // But sufficient for these basic things. function deepCopy(src, dest) { - Object.keys(src).filter(function(k) { - return !dest.hasOwnProperty(k); - }).forEach(function(k) { + Object.keys(src).filter((k) => !dest.hasOwnProperty(k)).forEach((k) => { dest[k] = deepCopy_(src[k]); }); } @@ -497,14 +494,14 @@ function deepCopy_(src) { if (!src) return src; if (Array.isArray(src)) { var c = new Array(src.length); - src.forEach(function(v, i) { + src.forEach((v, i) => { c[i] = deepCopy_(v); }); return c; } if (typeof src === 'object') { var c = {}; - Object.keys(src).forEach(function(k) { + Object.keys(src).forEach((k) => { c[k] = deepCopy_(src[k]); }); return c; @@ -514,21 +511,21 @@ function deepCopy_(src) { // these parse out the contents of an H# tag -var eventExpr = /^Event(?::|\s)+['"]?([^"']+).*$/i; -var classExpr = /^Class:\s*([^ ]+).*?$/i; -var propExpr = /^(?:property:?\s*)?[^\.]+\.([^ \.\(\)]+)\s*?$/i; -var braceExpr = /^(?:property:?\s*)?[^\.\[]+(\[[^\]]+\])\s*?$/i; -var classMethExpr = +const eventExpr = /^Event(?::|\s)+['"]?([^"']+).*$/i; +const classExpr = /^Class:\s*([^ ]+).*?$/i; +const propExpr = /^(?:property:?\s*)?[^\.]+\.([^ \.\(\)]+)\s*?$/i; +const braceExpr = /^(?:property:?\s*)?[^\.\[]+(\[[^\]]+\])\s*?$/i; +const classMethExpr = /^class\s*method\s*:?[^\.]+\.([^ \.\(\)]+)\([^\)]*\)\s*?$/i; -var methExpr = +const methExpr = /^(?:method:?\s*)?(?:[^\.]+\.)?([^ \.\(\)]+)\([^\)]*\)\s*?$/i; -var newExpr = /^new ([A-Z][a-z]+)\([^\)]*\)\s*?$/; +const newExpr = /^new ([A-Z][a-z]+)\([^\)]*\)\s*?$/; var paramExpr = /\((.*)\);?$/; function newSection(tok) { - var section = {}; + const section = {}; // infer the type from the text. - var text = section.textRaw = tok.text; + const text = section.textRaw = tok.text; if (text.match(eventExpr)) { section.type = 'event'; section.name = text.replace(eventExpr, '$1'); diff --git a/bin/extractPadData.js b/bin/extractPadData.js index cce297f71..a811076ef 100644 --- a/bin/extractPadData.js +++ b/bin/extractPadData.js @@ -5,60 +5,60 @@ */ if (process.argv.length != 3) { - console.error("Use: node extractPadData.js $PADID"); + console.error('Use: node extractPadData.js $PADID'); process.exit(1); } // get the padID -let padId = process.argv[2]; +const padId = process.argv[2]; -let npm = require('../src/node_modules/npm'); +const npm = require('../src/node_modules/npm'); -npm.load({}, async function(er) { +npm.load({}, async (er) => { if (er) { - console.error("Could not load NPM: " + er) + console.error(`Could not load NPM: ${er}`); process.exit(1); } try { // initialize database - let settings = require('../src/node/utils/Settings'); - let db = require('../src/node/db/DB'); + const settings = require('../src/node/utils/Settings'); + const db = require('../src/node/db/DB'); await db.init(); // load extra modules - let dirtyDB = require('../src/node_modules/dirty'); - let padManager = require('../src/node/db/PadManager'); - let util = require('util'); + const dirtyDB = require('../src/node_modules/dirty'); + const padManager = require('../src/node/db/PadManager'); + const util = require('util'); // initialize output database - let dirty = dirtyDB(padId + '.db'); + const dirty = dirtyDB(`${padId}.db`); // Promise wrapped get and set function - let wrapped = db.db.db.wrappedDB; - let get = util.promisify(wrapped.get.bind(wrapped)); - let set = util.promisify(dirty.set.bind(dirty)); + const wrapped = db.db.db.wrappedDB; + const get = util.promisify(wrapped.get.bind(wrapped)); + const set = util.promisify(dirty.set.bind(dirty)); // array in which required key values will be accumulated - let neededDBValues = ['pad:' + padId]; + const neededDBValues = [`pad:${padId}`]; // get the actual pad object - let pad = await padManager.getPad(padId); + const pad = await padManager.getPad(padId); // add all authors - neededDBValues.push(...pad.getAllAuthors().map(author => 'globalAuthor:' + author)); + neededDBValues.push(...pad.getAllAuthors().map((author) => `globalAuthor:${author}`)); // add all revisions for (let rev = 0; rev <= pad.head; ++rev) { - neededDBValues.push('pad:' + padId + ':revs:' + rev); + neededDBValues.push(`pad:${padId}:revs:${rev}`); } // add all chat values for (let chat = 0; chat <= pad.chatHead; ++chat) { - neededDBValues.push('pad:' + padId + ':chat:' + chat); + neededDBValues.push(`pad:${padId}:chat:${chat}`); } - for (let dbkey of neededDBValues) { + for (const dbkey of neededDBValues) { let dbvalue = await get(dbkey); if (dbvalue && typeof dbvalue !== 'object') { dbvalue = JSON.parse(dbvalue); diff --git a/bin/importSqlFile.js b/bin/importSqlFile.js index f04af44f9..a67cb8bf0 100644 --- a/bin/importSqlFile.js +++ b/bin/importSqlFile.js @@ -1,69 +1,64 @@ -var startTime = Date.now(); +const startTime = Date.now(); -require("ep_etherpad-lite/node_modules/npm").load({}, function(er,npm) { +require('ep_etherpad-lite/node_modules/npm').load({}, (er, npm) => { + const fs = require('fs'); - var fs = require("fs"); + const ueberDB = require('ep_etherpad-lite/node_modules/ueberdb2'); + const settings = require('ep_etherpad-lite/node/utils/Settings'); + const log4js = require('ep_etherpad-lite/node_modules/log4js'); - var ueberDB = require("ep_etherpad-lite/node_modules/ueberdb2"); - var settings = require("ep_etherpad-lite/node/utils/Settings"); - var log4js = require('ep_etherpad-lite/node_modules/log4js'); - - var dbWrapperSettings = { + const dbWrapperSettings = { cache: 0, writeInterval: 100, - json: false // data is already json encoded + json: false, // data is already json encoded }; - var db = new ueberDB.database(settings.dbType, settings.dbSettings, dbWrapperSettings, log4js.getLogger("ueberDB")); + const db = new ueberDB.database(settings.dbType, settings.dbSettings, dbWrapperSettings, log4js.getLogger('ueberDB')); - var sqlFile = process.argv[2]; + const sqlFile = process.argv[2]; - //stop if the settings file is not set - if(!sqlFile) - { - console.error("Use: node importSqlFile.js $SQLFILE"); + // stop if the settings file is not set + if (!sqlFile) { + console.error('Use: node importSqlFile.js $SQLFILE'); process.exit(1); } - log("initializing db"); - db.init(function(err) { - //there was an error while initializing the database, output it and stop - if(err) - { - console.error("ERROR: Problem while initializing the database"); + log('initializing db'); + db.init((err) => { + // there was an error while initializing the database, output it and stop + if (err) { + console.error('ERROR: Problem while initializing the database'); console.error(err.stack ? err.stack : err); process.exit(1); - } - else - { - log("done"); + } else { + log('done'); - log("open output file..."); - var lines = fs.readFileSync(sqlFile, 'utf8').split("\n"); + log('open output file...'); + const lines = fs.readFileSync(sqlFile, 'utf8').split('\n'); - var count = lines.length; - var keyNo = 0; + const count = lines.length; + let keyNo = 0; - process.stdout.write("Start importing " + count + " keys...\n"); - lines.forEach(function(l) { - if (l.substr(0, 27) == "REPLACE INTO store VALUES (") { - var pos = l.indexOf("', '"); - var key = l.substr(28, pos - 28); - var value = l.substr(pos + 3); + process.stdout.write(`Start importing ${count} keys...\n`); + lines.forEach((l) => { + if (l.substr(0, 27) == 'REPLACE INTO store VALUES (') { + const pos = l.indexOf("', '"); + const key = l.substr(28, pos - 28); + let value = l.substr(pos + 3); value = value.substr(0, value.length - 2); - console.log("key: " + key + " val: " + value); - console.log("unval: " + unescape(value)); + console.log(`key: ${key} val: ${value}`); + console.log(`unval: ${unescape(value)}`); db.set(key, unescape(value), null); keyNo++; if (keyNo % 1000 == 0) { - process.stdout.write(" " + keyNo + "/" + count + "\n"); + process.stdout.write(` ${keyNo}/${count}\n`); } } }); - process.stdout.write("\n"); - process.stdout.write("done. waiting for db to finish transaction. depended on dbms this may take some time...\n"); + process.stdout.write('\n'); + process.stdout.write('done. waiting for db to finish transaction. depended on dbms this may take some time...\n'); - db.doShutdown(function() { - log("finished, imported " + keyNo + " keys."); + db.doShutdown(() => { + log(`finished, imported ${keyNo} keys.`); process.exit(0); }); } @@ -71,22 +66,22 @@ require("ep_etherpad-lite/node_modules/npm").load({}, function(er,npm) { }); function log(str) { - console.log((Date.now() - startTime)/1000 + "\t" + str); + console.log(`${(Date.now() - startTime) / 1000}\t${str}`); } -unescape = function(val) { +unescape = function (val) { // value is a string if (val.substr(0, 1) == "'") { val = val.substr(0, val.length - 1).substr(1); - return val.replace(/\\[0nrbtZ\\'"]/g, function(s) { - switch(s) { - case "\\0": return "\0"; - case "\\n": return "\n"; - case "\\r": return "\r"; - case "\\b": return "\b"; - case "\\t": return "\t"; - case "\\Z": return "\x1a"; + return val.replace(/\\[0nrbtZ\\'"]/g, (s) => { + switch (s) { + case '\\0': return '\0'; + case '\\n': return '\n'; + case '\\r': return '\r'; + case '\\b': return '\b'; + case '\\t': return '\t'; + case '\\Z': return '\x1a'; default: return s.substr(1); } }); diff --git a/bin/migrateDirtyDBtoRealDB.js b/bin/migrateDirtyDBtoRealDB.js index ba329aa34..63425cab7 100644 --- a/bin/migrateDirtyDBtoRealDB.js +++ b/bin/migrateDirtyDBtoRealDB.js @@ -1,6 +1,5 @@ -require("ep_etherpad-lite/node_modules/npm").load({}, function(er,npm) { - - process.chdir(npm.root+'/..') +require('ep_etherpad-lite/node_modules/npm').load({}, (er, npm) => { + process.chdir(`${npm.root}/..`); // This script requires that you have modified your settings.json file // to work with a real database. Please make a backup of your dirty.db @@ -10,40 +9,40 @@ require("ep_etherpad-lite/node_modules/npm").load({}, function(er,npm) { // `node --max-old-space-size=4096 bin/migrateDirtyDBtoRealDB.js` - var settings = require("ep_etherpad-lite/node/utils/Settings"); - var dirty = require("../src/node_modules/dirty"); - var ueberDB = require("../src/node_modules/ueberdb2"); - var log4js = require("../src/node_modules/log4js"); - var dbWrapperSettings = { - "cache": "0", // The cache slows things down when you're mostly writing. - "writeInterval": 0 // Write directly to the database, don't buffer + const settings = require('ep_etherpad-lite/node/utils/Settings'); + let dirty = require('../src/node_modules/dirty'); + const ueberDB = require('../src/node_modules/ueberdb2'); + const log4js = require('../src/node_modules/log4js'); + const dbWrapperSettings = { + cache: '0', // The cache slows things down when you're mostly writing. + writeInterval: 0, // Write directly to the database, don't buffer }; - var db = new ueberDB.database(settings.dbType, settings.dbSettings, dbWrapperSettings, log4js.getLogger("ueberDB")); - var i = 0; - var length = 0; + const db = new ueberDB.database(settings.dbType, settings.dbSettings, dbWrapperSettings, log4js.getLogger('ueberDB')); + let i = 0; + let length = 0; - db.init(function() { - console.log("Waiting for dirtyDB to parse its file."); - dirty = dirty('var/dirty.db').on("load", function() { - dirty.forEach(function(){ + db.init(() => { + console.log('Waiting for dirtyDB to parse its file.'); + dirty = dirty('var/dirty.db').on('load', () => { + dirty.forEach(() => { length++; }); console.log(`Found ${length} records, processing now.`); - dirty.forEach(async function(key, value) { - let error = await db.set(key, value); + dirty.forEach(async (key, value) => { + const error = await db.set(key, value); console.log(`Wrote record ${i}`); i++; if (i === length) { - console.log("finished, just clearing up for a bit..."); - setTimeout(function() { + console.log('finished, just clearing up for a bit...'); + setTimeout(() => { process.exit(0); }, 5000); } }); - console.log("Please wait for all records to flush to database, then kill this process."); + console.log('Please wait for all records to flush to database, then kill this process.'); }); - console.log("done?") + console.log('done?'); }); }); diff --git a/bin/plugins/checkPlugin.js b/bin/plugins/checkPlugin.js index 17a16675a..fa5a5e268 100755 --- a/bin/plugins/checkPlugin.js +++ b/bin/plugins/checkPlugin.js @@ -9,96 +9,96 @@ node bin/plugins/checkPlugins.js ep_whatever autofix autocommit */ -const fs = require("fs"); -const { exec } = require("child_process"); +const fs = require('fs'); +const {exec} = require('child_process'); // get plugin name & path from user input const pluginName = process.argv[2]; -if(!pluginName){ - console.error("no plugin name specified"); +if (!pluginName) { + console.error('no plugin name specified'); process.exit(1); } -const pluginPath = "node_modules/"+pluginName; +const pluginPath = `node_modules/${pluginName}`; -console.log("Checking the plugin: "+ pluginName) +console.log(`Checking the plugin: ${pluginName}`); // Should we autofix? -if (process.argv[3] && process.argv[3] === "autofix") var autoFix = true; +if (process.argv[3] && process.argv[3] === 'autofix') var autoFix = true; // Should we update files where possible? -if (process.argv[5] && process.argv[5] === "autoupdate") var autoUpdate = true; +if (process.argv[5] && process.argv[5] === 'autoupdate') var autoUpdate = true; // Should we automcommit and npm publish?! -if (process.argv[4] && process.argv[4] === "autocommit") var autoCommit = true; +if (process.argv[4] && process.argv[4] === 'autocommit') var autoCommit = true; -if(autoCommit){ - console.warn("Auto commit is enabled, I hope you know what you are doing...") +if (autoCommit) { + console.warn('Auto commit is enabled, I hope you know what you are doing...'); } -fs.readdir(pluginPath, function (err, rootFiles) { - //handling error +fs.readdir(pluginPath, (err, rootFiles) => { + // handling error if (err) { - return console.log('Unable to scan directory: ' + err); + return console.log(`Unable to scan directory: ${err}`); } // rewriting files to lower case - var files = []; + const files = []; // some files we need to know the actual file name. Not compulsory but might help in the future. - var readMeFileName; - var repository; - var hasAutoFixed = false; + let readMeFileName; + let repository; + let hasAutoFixed = false; - for (var i = 0; i < rootFiles.length; i++) { - if(rootFiles[i].toLowerCase().indexOf("readme") !== -1) readMeFileName = rootFiles[i]; + for (let i = 0; i < rootFiles.length; i++) { + if (rootFiles[i].toLowerCase().indexOf('readme') !== -1) readMeFileName = rootFiles[i]; files.push(rootFiles[i].toLowerCase()); } - if(files.indexOf(".git") === -1){ - console.error("No .git folder, aborting"); + if (files.indexOf('.git') === -1) { + console.error('No .git folder, aborting'); process.exit(1); } // do a git pull... var child_process = require('child_process'); - try{ - child_process.execSync('git pull ',{"cwd":pluginPath+"/"}); - }catch(e){ - console.error("Error git pull", e); - }; + try { + child_process.execSync('git pull ', {cwd: `${pluginPath}/`}); + } catch (e) { + console.error('Error git pull', e); + } try { - const path = pluginPath + '/.github/workflows/npmpublish.yml'; + const path = `${pluginPath}/.github/workflows/npmpublish.yml`; if (!fs.existsSync(path)) { console.log('no .github/workflows/npmpublish.yml, create one and set npm secret to auto publish to npm on commit'); if (autoFix) { const npmpublish = fs.readFileSync('bin/plugins/lib/npmpublish.yml', {encoding: 'utf8', flag: 'r'}); - fs.mkdirSync(pluginPath + '/.github/workflows', {recursive: true}); + fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true}); fs.writeFileSync(path, npmpublish); hasAutoFixed = true; console.log("If you haven't already, setup autopublish for this plugin https://github.com/ether/etherpad-lite/wiki/Plugins:-Automatically-publishing-to-npm-on-commit-to-Github-Repo"); } else { console.log('Setup autopublish for this plugin https://github.com/ether/etherpad-lite/wiki/Plugins:-Automatically-publishing-to-npm-on-commit-to-Github-Repo'); } - }else{ + } else { // autopublish exists, we should check the version.. // checkVersion takes two file paths and checks for a version string in them. const currVersionFile = fs.readFileSync(path, {encoding: 'utf8', flag: 'r'}); - const existingConfigLocation = currVersionFile.indexOf("##ETHERPAD_NPM_V="); - const existingValue = parseInt(currVersionFile.substr(existingConfigLocation+17, existingConfigLocation.length)); + const existingConfigLocation = currVersionFile.indexOf('##ETHERPAD_NPM_V='); + const existingValue = parseInt(currVersionFile.substr(existingConfigLocation + 17, existingConfigLocation.length)); const reqVersionFile = fs.readFileSync('bin/plugins/lib/npmpublish.yml', {encoding: 'utf8', flag: 'r'}); - const reqConfigLocation = reqVersionFile.indexOf("##ETHERPAD_NPM_V="); - const reqValue = parseInt(reqVersionFile.substr(reqConfigLocation+17, reqConfigLocation.length)); + const reqConfigLocation = reqVersionFile.indexOf('##ETHERPAD_NPM_V='); + const reqValue = parseInt(reqVersionFile.substr(reqConfigLocation + 17, reqConfigLocation.length)); - if(!existingValue || (reqValue > existingValue)){ + if (!existingValue || (reqValue > existingValue)) { const npmpublish = fs.readFileSync('bin/plugins/lib/npmpublish.yml', {encoding: 'utf8', flag: 'r'}); - fs.mkdirSync(pluginPath + '/.github/workflows', {recursive: true}); + fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true}); fs.writeFileSync(path, npmpublish); hasAutoFixed = true; } @@ -107,152 +107,151 @@ fs.readdir(pluginPath, function (err, rootFiles) { console.error(err); } - if(files.indexOf("package.json") === -1){ - console.warn("no package.json, please create"); + if (files.indexOf('package.json') === -1) { + console.warn('no package.json, please create'); } - if(files.indexOf("package.json") !== -1){ - let packageJSON = fs.readFileSync(pluginPath+"/package.json", {encoding:'utf8', flag:'r'}); - let parsedPackageJSON = JSON.parse(packageJSON); - if(autoFix){ - var updatedPackageJSON = false; - if(!parsedPackageJSON.funding){ + if (files.indexOf('package.json') !== -1) { + const packageJSON = fs.readFileSync(`${pluginPath}/package.json`, {encoding: 'utf8', flag: 'r'}); + const parsedPackageJSON = JSON.parse(packageJSON); + if (autoFix) { + let updatedPackageJSON = false; + if (!parsedPackageJSON.funding) { updatedPackageJSON = true; parsedPackageJSON.funding = { - "type": "individual", - "url": "http://etherpad.org/" - } + type: 'individual', + url: 'http://etherpad.org/', + }; } - if(updatedPackageJSON){ + if (updatedPackageJSON) { hasAutoFixed = true; - fs.writeFileSync(pluginPath+"/package.json", JSON.stringify(parsedPackageJSON, null, 2)); + fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2)); } } - if(packageJSON.toLowerCase().indexOf("repository") === -1){ - console.warn("No repository in package.json"); - if(autoFix){ - console.warn("Repository not detected in package.json. Please add repository section manually.") + if (packageJSON.toLowerCase().indexOf('repository') === -1) { + console.warn('No repository in package.json'); + if (autoFix) { + console.warn('Repository not detected in package.json. Please add repository section manually.'); } - }else{ + } else { // useful for creating README later. repository = parsedPackageJSON.repository.url; } // include lint config - if(packageJSON.toLowerCase().indexOf("devdependencies") === -1 || !parsedPackageJSON.devDependencies.eslint){ - console.warn("Missing eslint reference in devDependencies"); - if(autoFix){ - let devDependencies = { - "eslint": "^7.14.0", - "eslint-config-etherpad": "^1.0.10", - "eslint-plugin-mocha": "^8.0.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prefer-arrow": "^1.2.2", - "eslint-plugin-promise": "^4.2.1" - } + if (packageJSON.toLowerCase().indexOf('devdependencies') === -1 || !parsedPackageJSON.devDependencies.eslint) { + console.warn('Missing eslint reference in devDependencies'); + if (autoFix) { + const devDependencies = { + 'eslint': '^7.14.0', + 'eslint-config-etherpad': '^1.0.10', + 'eslint-plugin-mocha': '^8.0.0', + 'eslint-plugin-node': '^11.1.0', + 'eslint-plugin-prefer-arrow': '^1.2.2', + 'eslint-plugin-promise': '^4.2.1', + }; hasAutoFixed = true; parsedPackageJSON.devDependencies = devDependencies; - fs.writeFileSync(pluginPath+"/package.json", JSON.stringify(parsedPackageJSON, null, 2)); + fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2)); - let child_process = require('child_process'); - try{ - child_process.execSync('npm install',{"cwd":pluginPath+"/"}); + const child_process = require('child_process'); + try { + child_process.execSync('npm install', {cwd: `${pluginPath}/`}); hasAutoFixed = true; - }catch(e){ - console.error("Failed to create package-lock.json"); + } catch (e) { + console.error('Failed to create package-lock.json'); } } } - if(packageJSON.toLowerCase().indexOf("eslintconfig") === -1){ - console.warn("No esLintConfig in package.json"); - if(autoFix){ - let eslintConfig = { - "root": true, - "extends": "etherpad/plugin" - } + if (packageJSON.toLowerCase().indexOf('eslintconfig') === -1) { + console.warn('No esLintConfig in package.json'); + if (autoFix) { + const eslintConfig = { + root: true, + extends: 'etherpad/plugin', + }; hasAutoFixed = true; parsedPackageJSON.eslintConfig = eslintConfig; - fs.writeFileSync(pluginPath+"/package.json", JSON.stringify(parsedPackageJSON, null, 2)); + fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2)); } } - if(packageJSON.toLowerCase().indexOf("scripts") === -1){ - console.warn("No scripts in package.json"); - if(autoFix){ - let scripts = { - "lint": "eslint .", - "lint:fix": "eslint --fix ." - } + if (packageJSON.toLowerCase().indexOf('scripts') === -1) { + console.warn('No scripts in package.json'); + if (autoFix) { + const scripts = { + 'lint': 'eslint .', + 'lint:fix': 'eslint --fix .', + }; hasAutoFixed = true; parsedPackageJSON.scripts = scripts; - fs.writeFileSync(pluginPath+"/package.json", JSON.stringify(parsedPackageJSON, null, 2)); + fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2)); } } - if(packageJSON.toLowerCase().indexOf("engines") === -1){ - console.warn("No engines in package.json"); - if(autoFix){ - let engines = { - "lint": "eslint ." - } + if (packageJSON.toLowerCase().indexOf('engines') === -1) { + console.warn('No engines in package.json'); + if (autoFix) { + const engines = { + lint: 'eslint .', + }; hasAutoFixed = true; parsedPackageJSON.engines = engines; - fs.writeFileSync(pluginPath+"/package.json", JSON.stringify(parsedPackageJSON, null, 2)); + fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2)); } } - } - if(files.indexOf("package-lock.json") === -1){ - console.warn("package-lock.json file not found. Please run npm install in the plugin folder and commit the package-lock.json file.") - if(autoFix){ + if (files.indexOf('package-lock.json') === -1) { + console.warn('package-lock.json file not found. Please run npm install in the plugin folder and commit the package-lock.json file.'); + if (autoFix) { var child_process = require('child_process'); - try{ - child_process.execSync('npm install',{"cwd":pluginPath+"/"}); - console.log("Making package-lock.json"); + try { + child_process.execSync('npm install', {cwd: `${pluginPath}/`}); + console.log('Making package-lock.json'); hasAutoFixed = true; - }catch(e){ - console.error("Failed to create package-lock.json"); + } catch (e) { + console.error('Failed to create package-lock.json'); } } } - if(files.indexOf("readme") === -1 && files.indexOf("readme.md") === -1){ - console.warn("README.md file not found, please create"); - if(autoFix){ - console.log("Autofixing missing README.md file, please edit the README.md file further to include plugin specific details."); - let readme = fs.readFileSync("bin/plugins/lib/README.md", {encoding:'utf8', flag:'r'}) + if (files.indexOf('readme') === -1 && files.indexOf('readme.md') === -1) { + console.warn('README.md file not found, please create'); + if (autoFix) { + console.log('Autofixing missing README.md file, please edit the README.md file further to include plugin specific details.'); + let readme = fs.readFileSync('bin/plugins/lib/README.md', {encoding: 'utf8', flag: 'r'}); readme = readme.replace(/\[plugin_name\]/g, pluginName); - if(repository){ - let org = repository.split("/")[3]; - let name = repository.split("/")[4]; + if (repository) { + const org = repository.split('/')[3]; + const name = repository.split('/')[4]; readme = readme.replace(/\[org_name\]/g, org); readme = readme.replace(/\[repo_url\]/g, name); - fs.writeFileSync(pluginPath+"/README.md", readme); - }else{ - console.warn("Unable to find repository in package.json, aborting.") + fs.writeFileSync(`${pluginPath}/README.md`, readme); + } else { + console.warn('Unable to find repository in package.json, aborting.'); } } } - if(files.indexOf("readme") !== -1 && files.indexOf("readme.md") !== -1){ - let readme = fs.readFileSync(pluginPath+"/"+readMeFileName, {encoding:'utf8', flag:'r'}); - if(readme.toLowerCase().indexOf("license") === -1){ - console.warn("No license section in README"); - if(autoFix){ - console.warn("Please add License section to README manually.") + if (files.indexOf('readme') !== -1 && files.indexOf('readme.md') !== -1) { + const readme = fs.readFileSync(`${pluginPath}/${readMeFileName}`, {encoding: 'utf8', flag: 'r'}); + if (readme.toLowerCase().indexOf('license') === -1) { + console.warn('No license section in README'); + if (autoFix) { + console.warn('Please add License section to README manually.'); } } } - if(files.indexOf("license") === -1 && files.indexOf("license.md") === -1){ - console.warn("LICENSE.md file not found, please create"); - if(autoFix){ + if (files.indexOf('license') === -1 && files.indexOf('license.md') === -1) { + console.warn('LICENSE.md file not found, please create'); + if (autoFix) { hasAutoFixed = true; - console.log("Autofixing missing LICENSE.md file, including Apache 2 license."); - exec("git config user.name", (error, name, stderr) => { + console.log('Autofixing missing LICENSE.md file, including Apache 2 license.'); + exec('git config user.name', (error, name, stderr) => { if (error) { console.log(`error: ${error.message}`); return; @@ -261,120 +260,118 @@ fs.readdir(pluginPath, function (err, rootFiles) { console.log(`stderr: ${stderr}`); return; } - let license = fs.readFileSync("bin/plugins/lib/LICENSE.md", {encoding:'utf8', flag:'r'}); - license = license.replace("[yyyy]", new Date().getFullYear()); - license = license.replace("[name of copyright owner]", name) - fs.writeFileSync(pluginPath+"/LICENSE.md", license); + let license = fs.readFileSync('bin/plugins/lib/LICENSE.md', {encoding: 'utf8', flag: 'r'}); + license = license.replace('[yyyy]', new Date().getFullYear()); + license = license.replace('[name of copyright owner]', name); + fs.writeFileSync(`${pluginPath}/LICENSE.md`, license); }); } } - var travisConfig = fs.readFileSync("bin/plugins/lib/travis.yml", {encoding:'utf8', flag:'r'}); + let travisConfig = fs.readFileSync('bin/plugins/lib/travis.yml', {encoding: 'utf8', flag: 'r'}); travisConfig = travisConfig.replace(/\[plugin_name\]/g, pluginName); - if(files.indexOf(".travis.yml") === -1){ - console.warn(".travis.yml file not found, please create. .travis.yml is used for automatically CI testing Etherpad. It is useful to know if your plugin breaks another feature for example.") + if (files.indexOf('.travis.yml') === -1) { + console.warn('.travis.yml file not found, please create. .travis.yml is used for automatically CI testing Etherpad. It is useful to know if your plugin breaks another feature for example.'); // TODO: Make it check version of the .travis file to see if it needs an update. - if(autoFix){ + if (autoFix) { hasAutoFixed = true; - console.log("Autofixing missing .travis.yml file"); - fs.writeFileSync(pluginPath+"/.travis.yml", travisConfig); - console.log("Travis file created, please sign into travis and enable this repository") + console.log('Autofixing missing .travis.yml file'); + fs.writeFileSync(`${pluginPath}/.travis.yml`, travisConfig); + console.log('Travis file created, please sign into travis and enable this repository'); } } - if(autoFix && autoUpdate){ + if (autoFix && autoUpdate) { // checks the file versioning of .travis and updates it to the latest. - let existingConfig = fs.readFileSync(pluginPath + "/.travis.yml", {encoding:'utf8', flag:'r'}); - let existingConfigLocation = existingConfig.indexOf("##ETHERPAD_TRAVIS_V="); - let existingValue = parseInt(existingConfig.substr(existingConfigLocation+20, existingConfig.length)); + const existingConfig = fs.readFileSync(`${pluginPath}/.travis.yml`, {encoding: 'utf8', flag: 'r'}); + const existingConfigLocation = existingConfig.indexOf('##ETHERPAD_TRAVIS_V='); + const existingValue = parseInt(existingConfig.substr(existingConfigLocation + 20, existingConfig.length)); - let newConfigLocation = travisConfig.indexOf("##ETHERPAD_TRAVIS_V="); - let newValue = parseInt(travisConfig.substr(newConfigLocation+20, travisConfig.length)); - if(existingConfigLocation === -1){ - console.warn("no previous .travis.yml version found so writing new.") + const newConfigLocation = travisConfig.indexOf('##ETHERPAD_TRAVIS_V='); + const newValue = parseInt(travisConfig.substr(newConfigLocation + 20, travisConfig.length)); + if (existingConfigLocation === -1) { + console.warn('no previous .travis.yml version found so writing new.'); // we will write the newTravisConfig to the location. - fs.writeFileSync(pluginPath + "/.travis.yml", travisConfig); - }else{ - if(newValue > existingValue){ - console.log("updating .travis.yml"); - fs.writeFileSync(pluginPath + "/.travis.yml", travisConfig); - hasAutoFixed = true; - } + fs.writeFileSync(`${pluginPath}/.travis.yml`, travisConfig); + } else if (newValue > existingValue) { + console.log('updating .travis.yml'); + fs.writeFileSync(`${pluginPath}/.travis.yml`, travisConfig); + hasAutoFixed = true; } } - if(files.indexOf(".gitignore") === -1){ - console.warn(".gitignore file not found, please create. .gitignore files are useful to ensure files aren't incorrectly commited to a repository.") - if(autoFix){ + if (files.indexOf('.gitignore') === -1) { + console.warn(".gitignore file not found, please create. .gitignore files are useful to ensure files aren't incorrectly commited to a repository."); + if (autoFix) { hasAutoFixed = true; - console.log("Autofixing missing .gitignore file"); - let gitignore = fs.readFileSync("bin/plugins/lib/gitignore", {encoding:'utf8', flag:'r'}); - fs.writeFileSync(pluginPath+"/.gitignore", gitignore); + console.log('Autofixing missing .gitignore file'); + const gitignore = fs.readFileSync('bin/plugins/lib/gitignore', {encoding: 'utf8', flag: 'r'}); + fs.writeFileSync(`${pluginPath}/.gitignore`, gitignore); } } // if we include templates but don't have translations... - if(files.indexOf("templates") !== -1 && files.indexOf("locales") === -1){ - console.warn("Translations not found, please create. Translation files help with Etherpad accessibility."); + if (files.indexOf('templates') !== -1 && files.indexOf('locales') === -1) { + console.warn('Translations not found, please create. Translation files help with Etherpad accessibility.'); } - if(files.indexOf(".ep_initialized") !== -1){ - console.warn(".ep_initialized found, please remove. .ep_initialized should never be commited to git and should only exist once the plugin has been executed one time.") - if(autoFix){ + if (files.indexOf('.ep_initialized') !== -1) { + console.warn('.ep_initialized found, please remove. .ep_initialized should never be commited to git and should only exist once the plugin has been executed one time.'); + if (autoFix) { hasAutoFixed = true; - console.log("Autofixing incorrectly existing .ep_initialized file"); - fs.unlinkSync(pluginPath+"/.ep_initialized"); + console.log('Autofixing incorrectly existing .ep_initialized file'); + fs.unlinkSync(`${pluginPath}/.ep_initialized`); } } - if(files.indexOf("npm-debug.log") !== -1){ - console.warn("npm-debug.log found, please remove. npm-debug.log should never be commited to your repository.") - if(autoFix){ + if (files.indexOf('npm-debug.log') !== -1) { + console.warn('npm-debug.log found, please remove. npm-debug.log should never be commited to your repository.'); + if (autoFix) { hasAutoFixed = true; - console.log("Autofixing incorrectly existing npm-debug.log file"); - fs.unlinkSync(pluginPath+"/npm-debug.log"); + console.log('Autofixing incorrectly existing npm-debug.log file'); + fs.unlinkSync(`${pluginPath}/npm-debug.log`); } } - if(files.indexOf("static") !== -1){ - fs.readdir(pluginPath+"/static", function (errRead, staticFiles) { - if(staticFiles.indexOf("tests") === -1){ - console.warn("Test files not found, please create tests. https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin#writing-and-running-front-end-tests-for-your-plugin") + if (files.indexOf('static') !== -1) { + fs.readdir(`${pluginPath}/static`, (errRead, staticFiles) => { + if (staticFiles.indexOf('tests') === -1) { + console.warn('Test files not found, please create tests. https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin#writing-and-running-front-end-tests-for-your-plugin'); } - }) - }else{ - console.warn("Test files not found, please create tests. https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin#writing-and-running-front-end-tests-for-your-plugin") + }); + } else { + console.warn('Test files not found, please create tests. https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin#writing-and-running-front-end-tests-for-your-plugin'); } // linting begins - if(autoFix){ + if (autoFix) { var lintCmd = 'npm run lint:fix'; - }else{ + } else { var lintCmd = 'npm run lint'; } - try{ - child_process.execSync(lintCmd,{"cwd":pluginPath+"/"}); - console.log("Linting..."); - if(autoFix){ + try { + child_process.execSync(lintCmd, {cwd: `${pluginPath}/`}); + console.log('Linting...'); + if (autoFix) { // todo: if npm run lint doesn't do anything no need for... hasAutoFixed = true; } - }catch(e){ + } catch (e) { // it is gonna throw an error anyway - console.log("Manual linting probably required, check with: npm run lint"); + console.log('Manual linting probably required, check with: npm run lint'); } // linting ends. - if(hasAutoFixed){ - console.log("Fixes applied, please check git diff then run the following command:\n\n") + if (hasAutoFixed) { + console.log('Fixes applied, please check git diff then run the following command:\n\n'); // bump npm Version - if(autoCommit){ + if (autoCommit) { // holy shit you brave. - console.log("Attempting autocommit and auto publish to npm") + console.log('Attempting autocommit and auto publish to npm'); // github should push to npm for us :) - exec("cd node_modules/"+ pluginName + " && git add -A && git commit --allow-empty -m 'autofixes from Etherpad checkPlugins.js' && git push && cd ../..", (error, name, stderr) => { + exec(`cd node_modules/${pluginName} && git add -A && git commit --allow-empty -m 'autofixes from Etherpad checkPlugins.js' && git push && cd ../..`, (error, name, stderr) => { if (error) { console.log(`error: ${error.message}`); return; @@ -383,14 +380,13 @@ fs.readdir(pluginPath, function (err, rootFiles) { console.log(`stderr: ${stderr}`); return; } - console.log("I think she's got it! By George she's got it!") - process.exit(0) + console.log("I think she's got it! By George she's got it!"); + process.exit(0); }); - }else{ - console.log("cd node_modules/"+ pluginName + " && git add -A && git commit --allow-empty -m 'autofixes from Etherpad checkPlugins.js' && npm version patch && git add package.json && git commit --allow-empty -m 'bump version' && git push && npm publish && cd ../..") + } else { + console.log(`cd node_modules/${pluginName} && git add -A && git commit --allow-empty -m 'autofixes from Etherpad checkPlugins.js' && npm version patch && git add package.json && git commit --allow-empty -m 'bump version' && git push && npm publish && cd ../..`); } } - console.log("Finished"); - + console.log('Finished'); }); diff --git a/bin/rebuildPad.js b/bin/rebuildPad.js index 313510ccd..12ff21847 100644 --- a/bin/rebuildPad.js +++ b/bin/rebuildPad.js @@ -3,120 +3,124 @@ known "good" revision. */ -if(process.argv.length != 4 && process.argv.length != 5) { - console.error("Use: node bin/repairPad.js $PADID $REV [$NEWPADID]"); +if (process.argv.length != 4 && process.argv.length != 5) { + console.error('Use: node bin/repairPad.js $PADID $REV [$NEWPADID]'); process.exit(1); } -var npm = require("../src/node_modules/npm"); -var async = require("../src/node_modules/async"); -var ueberDB = require("../src/node_modules/ueberdb2"); +const npm = require('../src/node_modules/npm'); +const async = require('../src/node_modules/async'); +const ueberDB = require('../src/node_modules/ueberdb2'); -var padId = process.argv[2]; -var newRevHead = process.argv[3]; -var newPadId = process.argv[4] || padId + "-rebuilt"; +const padId = process.argv[2]; +const newRevHead = process.argv[3]; +const newPadId = process.argv[4] || `${padId}-rebuilt`; -var db, oldPad, newPad, settings; -var AuthorManager, ChangeSet, Pad, PadManager; +let db, oldPad, newPad, settings; +let AuthorManager, ChangeSet, Pad, PadManager; async.series([ - function(callback) { - npm.load({}, function(err) { - if(err) { - console.error("Could not load NPM: " + err) + function (callback) { + npm.load({}, (err) => { + if (err) { + console.error(`Could not load NPM: ${err}`); process.exit(1); } else { callback(); } - }) + }); }, - function(callback) { + function (callback) { // Get a handle into the database db = require('../src/node/db/DB'); db.init(callback); - }, function(callback) { - PadManager = require('../src/node/db/PadManager'); - Pad = require('../src/node/db/Pad').Pad; - // Get references to the original pad and to a newly created pad - // HACK: This is a standalone script, so we want to write everything - // out to the database immediately. The only problem with this is - // that a driver (like the mysql driver) can hardcode these values. - db.db.db.settings = {cache: 0, writeInterval: 0, json: true}; - // Validate the newPadId if specified and that a pad with that ID does - // not already exist to avoid overwriting it. - if (!PadManager.isValidPadId(newPadId)) { - console.error("Cannot create a pad with that id as it is invalid"); - process.exit(1); - } - PadManager.doesPadExists(newPadId, function(err, exists) { - if (exists) { - console.error("Cannot create a pad with that id as it already exists"); - process.exit(1); - } - }); - PadManager.getPad(padId, function(err, pad) { - oldPad = pad; - newPad = new Pad(newPadId); - callback(); - }); - }, function(callback) { + }, + function (callback) { + PadManager = require('../src/node/db/PadManager'); + Pad = require('../src/node/db/Pad').Pad; + // Get references to the original pad and to a newly created pad + // HACK: This is a standalone script, so we want to write everything + // out to the database immediately. The only problem with this is + // that a driver (like the mysql driver) can hardcode these values. + db.db.db.settings = {cache: 0, writeInterval: 0, json: true}; + // Validate the newPadId if specified and that a pad with that ID does + // not already exist to avoid overwriting it. + if (!PadManager.isValidPadId(newPadId)) { + console.error('Cannot create a pad with that id as it is invalid'); + process.exit(1); + } + PadManager.doesPadExists(newPadId, (err, exists) => { + if (exists) { + console.error('Cannot create a pad with that id as it already exists'); + process.exit(1); + } + }); + PadManager.getPad(padId, (err, pad) => { + oldPad = pad; + newPad = new Pad(newPadId); + callback(); + }); + }, + function (callback) { // Clone all Chat revisions - var chatHead = oldPad.chatHead; - for(var i = 0, curHeadNum = 0; i <= chatHead; i++) { - db.db.get("pad:" + padId + ":chat:" + i, function (err, chat) { - db.db.set("pad:" + newPadId + ":chat:" + curHeadNum++, chat); - console.log("Created: Chat Revision: pad:" + newPadId + ":chat:" + curHeadNum); + const chatHead = oldPad.chatHead; + for (var i = 0, curHeadNum = 0; i <= chatHead; i++) { + db.db.get(`pad:${padId}:chat:${i}`, (err, chat) => { + db.db.set(`pad:${newPadId}:chat:${curHeadNum++}`, chat); + console.log(`Created: Chat Revision: pad:${newPadId}:chat:${curHeadNum}`); }); } callback(); - }, function(callback) { + }, + function (callback) { // Rebuild Pad from revisions up to and including the new revision head - AuthorManager = require("../src/node/db/AuthorManager"); - Changeset = require("ep_etherpad-lite/static/js/Changeset"); + AuthorManager = require('../src/node/db/AuthorManager'); + Changeset = require('ep_etherpad-lite/static/js/Changeset'); // Author attributes are derived from changesets, but there can also be // non-author attributes with specific mappings that changesets depend on // and, AFAICT, cannot be recreated any other way newPad.pool.numToAttrib = oldPad.pool.numToAttrib; - for(var curRevNum = 0; curRevNum <= newRevHead; curRevNum++) { - db.db.get("pad:" + padId + ":revs:" + curRevNum, function(err, rev) { + for (let curRevNum = 0; curRevNum <= newRevHead; curRevNum++) { + db.db.get(`pad:${padId}:revs:${curRevNum}`, (err, rev) => { if (rev.meta) { - throw "The specified revision number could not be found."; + throw 'The specified revision number could not be found.'; } - var newRevNum = ++newPad.head; - var newRevId = "pad:" + newPad.id + ":revs:" + newRevNum; + const newRevNum = ++newPad.head; + const newRevId = `pad:${newPad.id}:revs:${newRevNum}`; db.db.set(newRevId, rev); AuthorManager.addPad(rev.meta.author, newPad.id); newPad.atext = Changeset.applyToAText(rev.changeset, newPad.atext, newPad.pool); - console.log("Created: Revision: pad:" + newPad.id + ":revs:" + newRevNum); + console.log(`Created: Revision: pad:${newPad.id}:revs:${newRevNum}`); if (newRevNum == newRevHead) { callback(); } }); } - }, function(callback) { + }, + function (callback) { // Add saved revisions up to the new revision head console.log(newPad.head); - var newSavedRevisions = []; - for(var i in oldPad.savedRevisions) { - savedRev = oldPad.savedRevisions[i] + const newSavedRevisions = []; + for (const i in oldPad.savedRevisions) { + savedRev = oldPad.savedRevisions[i]; if (savedRev.revNum <= newRevHead) { newSavedRevisions.push(savedRev); - console.log("Added: Saved Revision: " + savedRev.revNum); + console.log(`Added: Saved Revision: ${savedRev.revNum}`); } } newPad.savedRevisions = newSavedRevisions; callback(); - }, function(callback) { + }, + function (callback) { // Save the source pad - db.db.set("pad:"+newPadId, newPad, function(err) { - console.log("Created: Source Pad: pad:" + newPadId); + db.db.set(`pad:${newPadId}`, newPad, (err) => { + console.log(`Created: Source Pad: pad:${newPadId}`); newPad.saveToDatabase().then(() => callback(), callback); }); - } -], function (err) { - if(err) throw err; - else { - console.info("finished"); + }, +], (err) => { + if (err) { throw err; } else { + console.info('finished'); process.exit(0); } }); diff --git a/bin/repairPad.js b/bin/repairPad.js index d495baef5..8408e4b72 100644 --- a/bin/repairPad.js +++ b/bin/repairPad.js @@ -2,47 +2,47 @@ * This is a repair tool. It extracts all datas of a pad, removes and inserts them again. */ -console.warn("WARNING: This script must not be used while etherpad is running!"); +console.warn('WARNING: This script must not be used while etherpad is running!'); if (process.argv.length != 3) { - console.error("Use: node bin/repairPad.js $PADID"); + console.error('Use: node bin/repairPad.js $PADID'); process.exit(1); } // get the padID -var padId = process.argv[2]; +const padId = process.argv[2]; -let npm = require("../src/node_modules/npm"); -npm.load({}, async function(er) { +const npm = require('../src/node_modules/npm'); +npm.load({}, async (er) => { if (er) { - console.error("Could not load NPM: " + er) + console.error(`Could not load NPM: ${er}`); process.exit(1); } try { // intialize database - let settings = require('../src/node/utils/Settings'); - let db = require('../src/node/db/DB'); + const settings = require('../src/node/utils/Settings'); + const db = require('../src/node/db/DB'); await db.init(); // get the pad - let padManager = require('../src/node/db/PadManager'); - let pad = await padManager.getPad(padId); + const padManager = require('../src/node/db/PadManager'); + const pad = await padManager.getPad(padId); // accumulate the required keys - let neededDBValues = ["pad:" + padId]; + const neededDBValues = [`pad:${padId}`]; // add all authors - neededDBValues.push(...pad.getAllAuthors().map(author => "globalAuthor:")); + neededDBValues.push(...pad.getAllAuthors().map((author) => 'globalAuthor:')); // add all revisions for (let rev = 0; rev <= pad.head; ++rev) { - neededDBValues.push("pad:" + padId + ":revs:" + rev); + neededDBValues.push(`pad:${padId}:revs:${rev}`); } // add all chat values for (let chat = 0; chat <= pad.chatHead; ++chat) { - neededDBValues.push("pad:" + padId + ":chat:" + chat); + neededDBValues.push(`pad:${padId}:chat:${chat}`); } // @@ -55,21 +55,20 @@ npm.load({}, async function(er) { // // See gitlab issue #3545 // - console.info("aborting [gitlab #3545]"); + console.info('aborting [gitlab #3545]'); process.exit(1); // now fetch and reinsert every key - neededDBValues.forEach(function(key, value) { - console.log("Key: " + key+ ", value: " + value); + neededDBValues.forEach((key, value) => { + console.log(`Key: ${key}, value: ${value}`); db.remove(key); db.set(key, value); }); - console.info("finished"); + console.info('finished'); process.exit(0); - } catch (er) { - if (er.name === "apierror") { + if (er.name === 'apierror') { console.error(er); } else { console.trace(er); diff --git a/tests/backend/common.js b/tests/backend/common.js index 8445c2e1f..887312809 100644 --- a/tests/backend/common.js +++ b/tests/backend/common.js @@ -1,6 +1,6 @@ /* global __dirname, exports, require */ -function m(mod) { return __dirname + '/../../src/' + mod; } +function m(mod) { return `${__dirname}/../../src/${mod}`; } const apiHandler = require(m('node/handler/APIHandler')); const log4js = require(m('node_modules/log4js')); @@ -25,7 +25,7 @@ const logLevel = exports.logger.level; // https://github.com/mochajs/mocha/issues/2640 process.on('unhandledRejection', (reason, promise) => { throw reason; }); -exports.init = async function() { +exports.init = async function () { if (inited) return exports.agent; inited = true; @@ -50,7 +50,7 @@ exports.init = async function() { backups.authnFailureDelayMs = webaccess.authnFailureDelayMs; webaccess.authnFailureDelayMs = 0; - after(async function() { + after(async function () { webaccess.authnFailureDelayMs = backups.authnFailureDelayMs; await server.stop(); // Note: This does not unset settings that were added. diff --git a/tests/backend/fuzzImportTest.js b/tests/backend/fuzzImportTest.js index 0f03b9e00..e2667e8f9 100644 --- a/tests/backend/fuzzImportTest.js +++ b/tests/backend/fuzzImportTest.js @@ -3,44 +3,44 @@ * Usage: node fuzzImportTest.js */ const common = require('./common'); -const settings = require(__dirname+'/loadSettings').loadSettings(); -const host = "http://" + settings.ip + ":" + settings.port; +const settings = require(`${__dirname}/loadSettings`).loadSettings(); +const host = `http://${settings.ip}:${settings.port}`; const request = require('request'); const froth = require('mocha-froth'); const apiKey = common.apiKey; -var apiVersion = 1; -var testPadId = "TEST_fuzz" + makeid(); +const apiVersion = 1; +const testPadId = `TEST_fuzz${makeid()}`; -var endPoint = function(point, version){ +const endPoint = function (point, version) { version = version || apiVersion; - return '/api/'+version+'/'+point+'?apikey='+apiKey; -} + return `/api/${version}/${point}?apikey=${apiKey}`; +}; -console.log("Testing against padID", testPadId); -console.log("To watch the test live visit " + host + "/p/" + testPadId); -console.log("Tests will start in 5 seconds, click the URL now!"); +console.log('Testing against padID', testPadId); +console.log(`To watch the test live visit ${host}/p/${testPadId}`); +console.log('Tests will start in 5 seconds, click the URL now!'); -setTimeout(function(){ - for (let i=1; i<1000000; i++) { // 1M runs - setTimeout( function timer(){ +setTimeout(() => { + for (let i = 1; i < 1000000; i++) { // 1M runs + setTimeout(() => { runTest(i); - }, i*100 ); // 100 ms + }, i * 100); // 100 ms } -},5000); // wait 5 seconds +}, 5000); // wait 5 seconds -function runTest(number){ - request(host + endPoint('createPad') + '&padID=' + testPadId, function(err, res, body){ - var req = request.post(host + '/p/'+testPadId+'/import', function (err, res, body) { +function runTest(number) { + request(`${host + endPoint('createPad')}&padID=${testPadId}`, (err, res, body) => { + const req = request.post(`${host}/p/${testPadId}/import`, (err, res, body) => { if (err) { - throw new Error("FAILURE", err); - }else{ - console.log("Success"); + throw new Error('FAILURE', err); + } else { + console.log('Success'); } }); - var fN = '/test.txt'; - var cT = 'text/plain'; + let fN = '/test.txt'; + let cT = 'text/plain'; // To be more agressive every other test we mess with Etherpad // We provide a weird file name and also set a weird contentType @@ -49,23 +49,20 @@ function runTest(number){ cT = froth().toString(); } - let form = req.form(); + const form = req.form(); form.append('file', froth().toString(), { filename: fN, - contentType: cT + contentType: cT, }); - }); } function makeid() { - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for( var i=0; i < 5; i++ ){ + for (let i = 0; i < 5; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; } - - diff --git a/tests/backend/specs/api/api.js b/tests/backend/specs/api/api.js index a3d29fd4f..de009c559 100644 --- a/tests/backend/specs/api/api.js +++ b/tests/backend/specs/api/api.js @@ -7,23 +7,23 @@ */ const common = require('../../common'); -const supertest = require(__dirname + '/../../../../src/node_modules/supertest'); -const settings = require(__dirname + '/../../../../src/node/utils/Settings'); -const api = supertest('http://' + settings.ip + ':' + settings.port); +const supertest = require(`${__dirname}/../../../../src/node_modules/supertest`); +const settings = require(`${__dirname}/../../../../src/node/utils/Settings`); +const api = supertest(`http://${settings.ip}:${settings.port}`); -var validateOpenAPI = require(__dirname + '/../../../../src/node_modules/openapi-schema-validation').validate; +const validateOpenAPI = require(`${__dirname}/../../../../src/node_modules/openapi-schema-validation`).validate; const apiKey = common.apiKey; -var apiVersion = 1; +let apiVersion = 1; -var testPadId = makeid(); +const testPadId = makeid(); -describe(__filename, function() { - describe('API Versioning', function() { - it('errors if can not connect', function(done) { +describe(__filename, function () { + describe('API Versioning', function () { + it('errors if can not connect', function (done) { api .get('/api/') - .expect(function(res) { + .expect((res) => { apiVersion = res.body.currentVersion; if (!res.body.currentVersion) throw new Error('No version set in API'); return; @@ -32,12 +32,12 @@ describe(__filename, function() { }); }); - describe('OpenAPI definition', function() { - it('generates valid openapi definition document', function(done) { + describe('OpenAPI definition', function () { + it('generates valid openapi definition document', function (done) { api .get('/api/openapi.json') - .expect(function(res) { - const { valid, errors } = validateOpenAPI(res.body, 3); + .expect((res) => { + const {valid, errors} = validateOpenAPI(res.body, 3); if (!valid) { const prettyErrors = JSON.stringify(errors, null, 2); throw new Error(`Document is not valid OpenAPI. ${errors.length} validation errors:\n${prettyErrors}`); @@ -48,11 +48,11 @@ describe(__filename, function() { }); }); - describe('jsonp support', function() { - it('supports jsonp calls', function(done) { + describe('jsonp support', function () { + it('supports jsonp calls', function (done) { api - .get(endPoint('createPad') + '&jsonp=jsonp_1&padID=' + testPadId) - .expect(function(res) { + .get(`${endPoint('createPad')}&jsonp=jsonp_1&padID=${testPadId}`) + .expect((res) => { if (!res.text.match('jsonp_1')) throw new Error('no jsonp call seen'); }) .expect('Content-Type', /javascript/) @@ -61,15 +61,15 @@ describe(__filename, function() { }); }); -var endPoint = function(point) { - return '/api/' + apiVersion + '/' + point + '?apikey=' + apiKey; +var endPoint = function (point) { + return `/api/${apiVersion}/${point}?apikey=${apiKey}`; }; function makeid() { - var text = ''; - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for (var i = 0; i < 5; i++) { + for (let i = 0; i < 5; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; diff --git a/tests/backend/specs/api/characterEncoding.js b/tests/backend/specs/api/characterEncoding.js index 2bc6c8089..e17e90fe4 100644 --- a/tests/backend/specs/api/characterEncoding.js +++ b/tests/backend/specs/api/characterEncoding.js @@ -5,86 +5,86 @@ */ const common = require('../../common'); -const supertest = require(__dirname+'/../../../../src/node_modules/supertest'); +const supertest = require(`${__dirname}/../../../../src/node_modules/supertest`); const fs = require('fs'); -const settings = require(__dirname + '/../../../../src/node/utils/Settings'); -const api = supertest('http://'+settings.ip+":"+settings.port); +const settings = require(`${__dirname}/../../../../src/node/utils/Settings`); +const api = supertest(`http://${settings.ip}:${settings.port}`); const apiKey = common.apiKey; -var apiVersion = 1; -var testPadId = makeid(); +let apiVersion = 1; +const testPadId = makeid(); -describe(__filename, function() { - describe('Connectivity For Character Encoding', function() { - it('can connect', function(done) { +describe(__filename, function () { + describe('Connectivity For Character Encoding', function () { + it('can connect', function (done) { api.get('/api/') .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('API Versioning', function() { - it('finds the version tag', function(done) { + describe('API Versioning', function () { + it('finds the version tag', function (done) { api.get('/api/') - .expect(function(res){ + .expect((res) => { apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); + if (!res.body.currentVersion) throw new Error('No version set in API'); return; }) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('Permission', function() { - it('errors with invalid APIKey', function(done) { + describe('Permission', function () { + it('errors with invalid APIKey', function (done) { // This is broken because Etherpad doesn't handle HTTP codes properly see #2343 // If your APIKey is password you deserve to fail all tests anyway - var permErrorURL = '/api/'+apiVersion+'/createPad?apikey=password&padID=test'; + const permErrorURL = `/api/${apiVersion}/createPad?apikey=password&padID=test`; api.get(permErrorURL) - .expect(401, done) + .expect(401, done); }); - }) + }); - describe('createPad', function() { - it('creates a new Pad', function(done) { - api.get(endPoint('createPad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create new Pad"); + describe('createPad', function () { + it('creates a new Pad', function (done) { + api.get(`${endPoint('createPad')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to create new Pad'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('setHTML', function() { - it('Sets the HTML of a Pad attempting to weird utf8 encoded content', function(done) { - fs.readFile('../tests/backend/specs/api/emojis.html', 'utf8', function(err, html) { + describe('setHTML', function () { + it('Sets the HTML of a Pad attempting to weird utf8 encoded content', function (done) { + fs.readFile('../tests/backend/specs/api/emojis.html', 'utf8', (err, html) => { api.post(endPoint('setHTML')) .send({ - "padID": testPadId, - "html": html, + padID: testPadId, + html, }) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Can't set HTML properly"); + .expect((res) => { + if (res.body.code !== 0) throw new Error("Can't set HTML properly"); }) .expect('Content-Type', /json/) .expect(200, done); }); }); - }) + }); - describe('getHTML', function() { - it('get the HTML of Pad with emojis', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - if (res.body.data.html.indexOf("🇼") === -1) { - throw new Error("Unable to get the HTML"); + describe('getHTML', function () { + it('get the HTML of Pad with emojis', function (done) { + api.get(`${endPoint('getHTML')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.html.indexOf('🇼') === -1) { + throw new Error('Unable to get the HTML'); } }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); }); /* @@ -93,16 +93,16 @@ describe(__filename, function() { */ -var endPoint = function(point, version){ +var endPoint = function (point, version) { version = version || apiVersion; - return '/api/'+version+'/'+point+'?apikey='+apiKey; -} + return `/api/${version}/${point}?apikey=${apiKey}`; +}; function makeid() { - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for( var i=0; i < 10; i++ ){ + for (let i = 0; i < 10; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; diff --git a/tests/backend/specs/api/chat.js b/tests/backend/specs/api/chat.js index 02a41a32e..d51dbfaee 100644 --- a/tests/backend/specs/api/chat.js +++ b/tests/backend/specs/api/chat.js @@ -1,4 +1,4 @@ -function m(mod) { return __dirname + '/../../../../src/' + mod; } +function m(mod) { return `${__dirname}/../../../../src/${mod}`; } const common = require('../../common'); const settings = require(m('node/utils/Settings')); @@ -6,27 +6,27 @@ const supertest = require(m('node_modules/supertest')); const api = supertest(`http://${settings.ip}:${settings.port}`); const apiKey = common.apiKey; -var apiVersion = 1; -var authorID = ""; -var padID = makeid(); -var timestamp = Date.now(); +let apiVersion = 1; +let authorID = ''; +const padID = makeid(); +const timestamp = Date.now(); -describe(__filename, function() { - describe('API Versioning', function(){ - it('errors if can not connect', function(done) { +describe(__filename, function () { + describe('API Versioning', function () { + it('errors if can not connect', function (done) { api.get('/api/') - .expect(function(res){ + .expect((res) => { apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); + if (!res.body.currentVersion) throw new Error('No version set in API'); return; }) - .expect(200, done) + .expect(200, done); }); - }) + }); // BEGIN GROUP AND AUTHOR TESTS - ///////////////////////////////////// - ///////////////////////////////////// + // /////////////////////////////////// + // /////////////////////////////////// /* Tests performed -> createPad(padID) @@ -36,76 +36,76 @@ describe(__filename, function() { -> getChatHistory(padID) */ - describe('createPad', function(){ - it('creates a new Pad', function(done) { - api.get(endPoint('createPad')+"&padID="+padID) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create new Pad"); + describe('createPad', function () { + it('creates a new Pad', function (done) { + api.get(`${endPoint('createPad')}&padID=${padID}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to create new Pad'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('createAuthor', function(){ - it('Creates an author with a name set', function(done) { + describe('createAuthor', function () { + it('Creates an author with a name set', function (done) { api.get(endPoint('createAuthor')) - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.authorID) throw new Error("Unable to create author"); + .expect((res) => { + if (res.body.code !== 0 || !res.body.data.authorID) throw new Error('Unable to create author'); authorID = res.body.data.authorID; // we will be this author for the rest of the tests }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('appendChatMessage', function(){ - it('Adds a chat message to the pad', function(done) { - api.get(endPoint('appendChatMessage')+"&padID="+padID+"&text=blalblalbha&authorID="+authorID+"&time="+timestamp) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create chat message"); + describe('appendChatMessage', function () { + it('Adds a chat message to the pad', function (done) { + api.get(`${endPoint('appendChatMessage')}&padID=${padID}&text=blalblalbha&authorID=${authorID}&time=${timestamp}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to create chat message'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getChatHead', function(){ - it('Gets the head of chat', function(done) { - api.get(endPoint('getChatHead')+"&padID="+padID) - .expect(function(res){ - if(res.body.data.chatHead !== 0) throw new Error("Chat Head Length is wrong"); + describe('getChatHead', function () { + it('Gets the head of chat', function (done) { + api.get(`${endPoint('getChatHead')}&padID=${padID}`) + .expect((res) => { + if (res.body.data.chatHead !== 0) throw new Error('Chat Head Length is wrong'); - if(res.body.code !== 0) throw new Error("Unable to get chat head"); + if (res.body.code !== 0) throw new Error('Unable to get chat head'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getChatHistory', function(){ - it('Gets Chat History of a Pad', function(done) { - api.get(endPoint('getChatHistory')+"&padID="+padID) - .expect(function(res){ - if(res.body.data.messages.length !== 1) throw new Error("Chat History Length is wrong"); - if(res.body.code !== 0) throw new Error("Unable to get chat history"); + describe('getChatHistory', function () { + it('Gets Chat History of a Pad', function (done) { + api.get(`${endPoint('getChatHistory')}&padID=${padID}`) + .expect((res) => { + if (res.body.data.messages.length !== 1) throw new Error('Chat History Length is wrong'); + if (res.body.code !== 0) throw new Error('Unable to get chat history'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); }); -var endPoint = function(point){ - return '/api/'+apiVersion+'/'+point+'?apikey='+apiKey; -} +var endPoint = function (point) { + return `/api/${apiVersion}/${point}?apikey=${apiKey}`; +}; function makeid() { - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for( var i=0; i < 5; i++ ){ + for (let i = 0; i < 5; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; diff --git a/tests/backend/specs/api/importexport.js b/tests/backend/specs/api/importexport.js index 7dd0754ec..e23e27d8d 100644 --- a/tests/backend/specs/api/importexport.js +++ b/tests/backend/specs/api/importexport.js @@ -6,39 +6,39 @@ */ const common = require('../../common'); -const supertest = require(__dirname+'/../../../../src/node_modules/supertest'); -const settings = require(__dirname+'/../../../../tests/container/loadSettings.js').loadSettings(); -const api = supertest('http://'+settings.ip+":"+settings.port); +const supertest = require(`${__dirname}/../../../../src/node_modules/supertest`); +const settings = require(`${__dirname}/../../../../tests/container/loadSettings.js`).loadSettings(); +const api = supertest(`http://${settings.ip}:${settings.port}`); const apiKey = common.apiKey; -var apiVersion = 1; -var lastEdited = ""; +const apiVersion = 1; +const lastEdited = ''; -var testImports = { - "malformed": { +const testImports = { + 'malformed': { input: '
  • wtf', expectedHTML: 'wtf

    ', - expectedText: 'wtf\n\n' + expectedText: 'wtf\n\n', }, - "nonelistiteminlist #3620":{ + 'nonelistiteminlist #3620': { input: '
      test
    • FOO
    ', expectedHTML: '
      test
    • FOO

    ', - expectedText: '\ttest\n\t* FOO\n\n' + expectedText: '\ttest\n\t* FOO\n\n', }, - "whitespaceinlist #3620":{ + 'whitespaceinlist #3620': { input: '
    • FOO
    ', expectedHTML: '
    • FOO

    ', - expectedText: '\t* FOO\n\n' + expectedText: '\t* FOO\n\n', }, - "prefixcorrectlinenumber":{ + 'prefixcorrectlinenumber': { input: '
    1. should be 1
    2. should be 2
    ', expectedHTML: '
    1. should be 1
    2. should be 2

    ', - expectedText: '\t1. should be 1\n\t2. should be 2\n\n' + expectedText: '\t1. should be 1\n\t2. should be 2\n\n', }, - "prefixcorrectlinenumbernested":{ + 'prefixcorrectlinenumbernested': { input: '
    1. should be 1
      1. foo
    2. should be 2
    ', expectedHTML: '
    1. should be 1
      1. foo
    2. should be 2

    ', - expectedText: '\t1. should be 1\n\t\t1.1. foo\n\t2. should be 2\n\n' + expectedText: '\t1. should be 1\n\t\t1.1. foo\n\t2. should be 2\n\n', }, /* @@ -54,39 +54,39 @@ var testImports = { expectedText: '\t1. should be 1\n\ttest\n\t2. should be 2\n\n' } */ -} +}; -describe(__filename, function() { - Object.keys(testImports).forEach(function(testName) { - var testPadId = makeid(); +describe(__filename, function () { + Object.keys(testImports).forEach((testName) => { + const testPadId = makeid(); test = testImports[testName]; - describe('createPad', function() { - it('creates a new Pad', function(done) { - api.get(endPoint('createPad') + "&padID=" + testPadId) - .expect(function(res) { - if(res.body.code !== 0) throw new Error("Unable to create new Pad"); + describe('createPad', function () { + it('creates a new Pad', function (done) { + api.get(`${endPoint('createPad')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to create new Pad'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('setHTML', function() { - it('Sets the HTML', function(done) { - api.get(endPoint('setHTML') + "&padID=" + testPadId + "&html=" + test.input) - .expect(function(res) { - if(res.body.code !== 0) throw new Error("Error:" + testName) + describe('setHTML', function () { + it('Sets the HTML', function (done) { + api.get(`${endPoint('setHTML')}&padID=${testPadId}&html=${test.input}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error(`Error:${testName}`); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getHTML', function() { - it('Gets back the HTML of a Pad', function(done) { - api.get(endPoint('getHTML') + "&padID=" + testPadId) - .expect(function(res) { - var receivedHtml = res.body.data.html; + describe('getHTML', function () { + it('Gets back the HTML of a Pad', function (done) { + api.get(`${endPoint('getHTML')}&padID=${testPadId}`) + .expect((res) => { + const receivedHtml = res.body.data.html; if (receivedHtml !== test.expectedHTML) { throw new Error(`HTML received from export is not the one we were expecting. Test Name: @@ -103,15 +103,15 @@ describe(__filename, function() { } }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getText', function() { - it('Gets back the Text of a Pad', function(done) { - api.get(endPoint('getText') + "&padID=" + testPadId) - .expect(function(res) { - var receivedText = res.body.data.text; + describe('getText', function () { + it('Gets back the Text of a Pad', function (done) { + api.get(`${endPoint('getText')}&padID=${testPadId}`) + .expect((res) => { + const receivedText = res.body.data.text; if (receivedText !== test.expectedText) { throw new Error(`Text received from export is not the one we were expecting. Test Name: @@ -128,33 +128,33 @@ describe(__filename, function() { } }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); }); }); -var endPoint = function(point, version){ +var endPoint = function (point, version) { version = version || apiVersion; - return '/api/'+version+'/'+point+'?apikey='+apiKey; -} + return `/api/${version}/${point}?apikey=${apiKey}`; +}; function makeid() { - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for( var i=0; i < 5; i++ ){ + for (let i = 0; i < 5; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; } -function generateLongText(){ - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; +function generateLongText() { + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for( var i=0; i < 80000; i++ ){ + for (let i = 0; i < 80000; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; @@ -162,22 +162,19 @@ function generateLongText(){ // Need this to compare arrays (listSavedRevisions test) Array.prototype.equals = function (array) { - // if the other array is a falsy value, return - if (!array) - return false; - // compare lengths - can save a lot of time - if (this.length != array.length) - return false; - for (var i = 0, l=this.length; i < l; i++) { - // Check if we have nested arrays - if (this[i] instanceof Array && array[i] instanceof Array) { - // recurse into the nested arrays - if (!this[i].equals(array[i])) - return false; - } else if (this[i] != array[i]) { - // Warning - two different object instances will never be equal: {x:20} != {x:20} - return false; - } + // if the other array is a falsy value, return + if (!array) return false; + // compare lengths - can save a lot of time + if (this.length != array.length) return false; + for (let i = 0, l = this.length; i < l; i++) { + // Check if we have nested arrays + if (this[i] instanceof Array && array[i] instanceof Array) { + // recurse into the nested arrays + if (!this[i].equals(array[i])) return false; + } else if (this[i] != array[i]) { + // Warning - two different object instances will never be equal: {x:20} != {x:20} + return false; } - return true; -} + } + return true; +}; diff --git a/tests/backend/specs/api/importexportGetPost.js b/tests/backend/specs/api/importexportGetPost.js index d318163cf..eec5fb999 100644 --- a/tests/backend/specs/api/importexportGetPost.js +++ b/tests/backend/specs/api/importexportGetPost.js @@ -6,38 +6,38 @@ const assert = require('assert').strict; const common = require('../../common'); -const superagent = require(__dirname+'/../../../../src/node_modules/superagent'); +const superagent = require(`${__dirname}/../../../../src/node_modules/superagent`); const fs = require('fs'); -const settings = require(__dirname+'/../../../../src/node/utils/Settings'); -const padManager = require(__dirname+'/../../../../src/node/db/PadManager'); -const plugins = require(__dirname+'/../../../../src/static/js/pluginfw/plugin_defs'); +const settings = require(`${__dirname}/../../../../src/node/utils/Settings`); +const padManager = require(`${__dirname}/../../../../src/node/db/PadManager`); +const plugins = require(`${__dirname}/../../../../src/static/js/pluginfw/plugin_defs`); -const padText = fs.readFileSync("../tests/backend/specs/api/test.txt"); -const etherpadDoc = fs.readFileSync("../tests/backend/specs/api/test.etherpad"); -const wordDoc = fs.readFileSync("../tests/backend/specs/api/test.doc"); -const wordXDoc = fs.readFileSync("../tests/backend/specs/api/test.docx"); -const odtDoc = fs.readFileSync("../tests/backend/specs/api/test.odt"); -const pdfDoc = fs.readFileSync("../tests/backend/specs/api/test.pdf"); +const padText = fs.readFileSync('../tests/backend/specs/api/test.txt'); +const etherpadDoc = fs.readFileSync('../tests/backend/specs/api/test.etherpad'); +const wordDoc = fs.readFileSync('../tests/backend/specs/api/test.doc'); +const wordXDoc = fs.readFileSync('../tests/backend/specs/api/test.docx'); +const odtDoc = fs.readFileSync('../tests/backend/specs/api/test.odt'); +const pdfDoc = fs.readFileSync('../tests/backend/specs/api/test.pdf'); let agent; const apiKey = common.apiKey; -var apiVersion = 1; +const apiVersion = 1; const testPadId = makeid(); const testPadIdEnc = encodeURIComponent(testPadId); -describe(__filename, function() { - before(async function() { agent = await common.init(); }); +describe(__filename, function () { + before(async function () { agent = await common.init(); }); - describe('Connectivity', function(){ - it('can connect', async function() { + describe('Connectivity', function () { + it('can connect', async function () { await agent.get('/api/') .expect(200) .expect('Content-Type', /json/); }); }); - describe('API Versioning', function(){ - it('finds the version tag', async function() { + describe('API Versioning', function () { + it('finds the version tag', async function () { await agent.get('/api/') .expect(200) .expect((res) => assert(res.body.currentVersion)); @@ -70,10 +70,10 @@ describe(__filename, function() { curl -s -v --form file=@/home/jose/test.txt http://127.0.0.1:9001/p/foo/import */ - describe('Imports and Exports', function(){ + describe('Imports and Exports', function () { const backups = {}; - beforeEach(async function() { + beforeEach(async function () { backups.hooks = {}; for (const hookName of ['preAuthorize', 'authenticate', 'authorize']) { backups.hooks[hookName] = plugins.hooks[hookName]; @@ -86,43 +86,43 @@ describe(__filename, function() { settings.users = {user: {password: 'user-password'}}; }); - afterEach(async function() { + afterEach(async function () { Object.assign(plugins.hooks, backups.hooks); // Note: This does not unset settings that were added. Object.assign(settings, backups.settings); }); - it('creates a new Pad, imports content to it, checks that content', async function() { - await agent.get(endPoint('createPad') + `&padID=${testPadId}`) + it('creates a new Pad, imports content to it, checks that content', async function () { + await agent.get(`${endPoint('createPad')}&padID=${testPadId}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => assert.equal(res.body.code, 0)); await agent.post(`/p/${testPadId}/import`) .attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'}) .expect(200); - await agent.get(endPoint('getText') + `&padID=${testPadId}`) + await agent.get(`${endPoint('getText')}&padID=${testPadId}`) .expect(200) .expect((res) => assert.equal(res.body.data.text, padText.toString())); }); - it('gets read only pad Id and exports the html and text for this pad', async function(){ - let ro = await agent.get(endPoint('getReadOnlyID')+"&padID="+testPadId) + it('gets read only pad Id and exports the html and text for this pad', async function () { + const ro = await agent.get(`${endPoint('getReadOnlyID')}&padID=${testPadId}`) .expect(200) .expect((res) => assert.ok(JSON.parse(res.text).data.readOnlyID)); - let readOnlyId = JSON.parse(ro.text).data.readOnlyID; + const readOnlyId = JSON.parse(ro.text).data.readOnlyID; await agent.get(`/p/${readOnlyId}/export/html`) .expect(200) - .expect((res) => assert(res.text.indexOf("This is the") !== -1)); + .expect((res) => assert(res.text.indexOf('This is the') !== -1)); await agent.get(`/p/${readOnlyId}/export/txt`) .expect(200) - .expect((res) => assert(res.text.indexOf("This is the") !== -1)); + .expect((res) => assert(res.text.indexOf('This is the') !== -1)); }); - describe('Import/Export tests requiring AbiWord/LibreOffice', function() { - before(function() { + describe('Import/Export tests requiring AbiWord/LibreOffice', function () { + before(function () { if ((!settings.abiword || settings.abiword.indexOf('/') === -1) && (!settings.soffice || settings.soffice.indexOf('/') === -1)) { this.skip(); @@ -131,21 +131,21 @@ describe(__filename, function() { // For some reason word import does not work in testing.. // TODO: fix support for .doc files.. - it('Tries to import .doc that uses soffice or abiword', async function() { + it('Tries to import .doc that uses soffice or abiword', async function () { await agent.post(`/p/${testPadId}/import`) .attach('file', wordDoc, {filename: '/test.doc', contentType: 'application/msword'}) .expect(200) .expect(/FrameCall\('undefined', 'ok'\);/); }); - it('exports DOC', async function() { + it('exports DOC', async function () { await agent.get(`/p/${testPadId}/export/doc`) .buffer(true).parse(superagent.parse['application/octet-stream']) .expect(200) .expect((res) => assert(res.body.length >= 9000)); }); - it('Tries to import .docx that uses soffice or abiword', async function() { + it('Tries to import .docx that uses soffice or abiword', async function () { await agent.post(`/p/${testPadId}/import`) .attach('file', wordXDoc, { filename: '/test.docx', @@ -155,44 +155,43 @@ describe(__filename, function() { .expect(/FrameCall\('undefined', 'ok'\);/); }); - it('exports DOC from imported DOCX', async function() { + it('exports DOC from imported DOCX', async function () { await agent.get(`/p/${testPadId}/export/doc`) .buffer(true).parse(superagent.parse['application/octet-stream']) .expect(200) .expect((res) => assert(res.body.length >= 9100)); }); - it('Tries to import .pdf that uses soffice or abiword', async function() { + it('Tries to import .pdf that uses soffice or abiword', async function () { await agent.post(`/p/${testPadId}/import`) .attach('file', pdfDoc, {filename: '/test.pdf', contentType: 'application/pdf'}) .expect(200) .expect(/FrameCall\('undefined', 'ok'\);/); }); - it('exports PDF', async function() { + it('exports PDF', async function () { await agent.get(`/p/${testPadId}/export/pdf`) .buffer(true).parse(superagent.parse['application/octet-stream']) .expect(200) .expect((res) => assert(res.body.length >= 1000)); }); - it('Tries to import .odt that uses soffice or abiword', async function() { + it('Tries to import .odt that uses soffice or abiword', async function () { await agent.post(`/p/${testPadId}/import`) .attach('file', odtDoc, {filename: '/test.odt', contentType: 'application/odt'}) .expect(200) .expect(/FrameCall\('undefined', 'ok'\);/); }); - it('exports ODT', async function() { + it('exports ODT', async function () { await agent.get(`/p/${testPadId}/export/odt`) .buffer(true).parse(superagent.parse['application/octet-stream']) .expect(200) .expect((res) => assert(res.body.length >= 7000)); }); - }); // End of AbiWord/LibreOffice tests. - it('Tries to import .etherpad', async function() { + it('Tries to import .etherpad', async function () { await agent.post(`/p/${testPadId}/import`) .attach('file', etherpadDoc, { filename: '/test.etherpad', @@ -202,21 +201,21 @@ describe(__filename, function() { .expect(/FrameCall\('true', 'ok'\);/); }); - it('exports Etherpad', async function() { + it('exports Etherpad', async function () { await agent.get(`/p/${testPadId}/export/etherpad`) .buffer(true).parse(superagent.parse.text) .expect(200) .expect(/hello/); }); - it('exports HTML for this Etherpad file', async function() { + it('exports HTML for this Etherpad file', async function () { await agent.get(`/p/${testPadId}/export/html`) .expect(200) .expect('content-type', 'text/html; charset=utf-8') .expect(/
      • hello<\/ul><\/li><\/ul>/); }); - it('Tries to import unsupported file type', async function() { + it('Tries to import unsupported file type', async function () { settings.allowUnknownFileEnds = false; await agent.post(`/p/${testPadId}/import`) .attach('file', padText, {filename: '/test.xasdasdxx', contentType: 'weirdness/jobby'}) @@ -224,7 +223,7 @@ describe(__filename, function() { .expect((res) => assert.doesNotMatch(res.text, /FrameCall\('undefined', 'ok'\);/)); }); - describe('Import authorization checks', function() { + describe('Import authorization checks', function () { let authorize; const deleteTestPad = async () => { @@ -240,18 +239,18 @@ describe(__filename, function() { return pad; }; - beforeEach(async function() { + beforeEach(async function () { await deleteTestPad(); settings.requireAuthorization = true; authorize = () => true; plugins.hooks.authorize = [{hook_fn: (hookName, {req}, cb) => cb([authorize(req)])}]; }); - afterEach(async function() { + afterEach(async function () { await deleteTestPad(); }); - it('!authn !exist -> create', async function() { + it('!authn !exist -> create', async function () { await agent.post(`/p/${testPadIdEnc}/import`) .attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'}) .expect(200); @@ -260,7 +259,7 @@ describe(__filename, function() { assert.equal(pad.text(), padText.toString()); }); - it('!authn exist -> replace', async function() { + it('!authn exist -> replace', async function () { const pad = await createTestPad('before import'); await agent.post(`/p/${testPadIdEnc}/import`) .attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'}) @@ -269,7 +268,7 @@ describe(__filename, function() { assert.equal(pad.text(), padText.toString()); }); - it('authn anonymous !exist -> fail', async function() { + it('authn anonymous !exist -> fail', async function () { settings.requireAuthentication = true; await agent.post(`/p/${testPadIdEnc}/import`) .attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'}) @@ -277,7 +276,7 @@ describe(__filename, function() { assert(!(await padManager.doesPadExist(testPadId))); }); - it('authn anonymous exist -> fail', async function() { + it('authn anonymous exist -> fail', async function () { settings.requireAuthentication = true; const pad = await createTestPad('before import\n'); await agent.post(`/p/${testPadIdEnc}/import`) @@ -286,7 +285,7 @@ describe(__filename, function() { assert.equal(pad.text(), 'before import\n'); }); - it('authn user create !exist -> create', async function() { + it('authn user create !exist -> create', async function () { settings.requireAuthentication = true; await agent.post(`/p/${testPadIdEnc}/import`) .auth('user', 'user-password') @@ -297,7 +296,7 @@ describe(__filename, function() { assert.equal(pad.text(), padText.toString()); }); - it('authn user modify !exist -> fail', async function() { + it('authn user modify !exist -> fail', async function () { settings.requireAuthentication = true; authorize = () => 'modify'; await agent.post(`/p/${testPadIdEnc}/import`) @@ -307,7 +306,7 @@ describe(__filename, function() { assert(!(await padManager.doesPadExist(testPadId))); }); - it('authn user readonly !exist -> fail', async function() { + it('authn user readonly !exist -> fail', async function () { settings.requireAuthentication = true; authorize = () => 'readOnly'; await agent.post(`/p/${testPadIdEnc}/import`) @@ -317,7 +316,7 @@ describe(__filename, function() { assert(!(await padManager.doesPadExist(testPadId))); }); - it('authn user create exist -> replace', async function() { + it('authn user create exist -> replace', async function () { settings.requireAuthentication = true; const pad = await createTestPad('before import\n'); await agent.post(`/p/${testPadIdEnc}/import`) @@ -327,7 +326,7 @@ describe(__filename, function() { assert.equal(pad.text(), padText.toString()); }); - it('authn user modify exist -> replace', async function() { + it('authn user modify exist -> replace', async function () { settings.requireAuthentication = true; authorize = () => 'modify'; const pad = await createTestPad('before import\n'); @@ -338,7 +337,7 @@ describe(__filename, function() { assert.equal(pad.text(), padText.toString()); }); - it('authn user readonly exist -> fail', async function() { + it('authn user readonly exist -> fail', async function () { const pad = await createTestPad('before import\n'); settings.requireAuthentication = true; authorize = () => 'readOnly'; @@ -353,19 +352,16 @@ describe(__filename, function() { }); // End of tests. - - - -var endPoint = function(point, version){ +var endPoint = function (point, version) { version = version || apiVersion; return `/api/${version}/${point}?apikey=${apiKey}`; }; function makeid() { - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for( var i=0; i < 5; i++ ){ + for (let i = 0; i < 5; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; diff --git a/tests/backend/specs/api/instance.js b/tests/backend/specs/api/instance.js index a29f8fdf7..7da967ed2 100644 --- a/tests/backend/specs/api/instance.js +++ b/tests/backend/specs/api/instance.js @@ -4,27 +4,27 @@ * Section "GLOBAL FUNCTIONS" in src/node/db/API.js */ const common = require('../../common'); -const supertest = require(__dirname+'/../../../../src/node_modules/supertest'); -const settings = require(__dirname+'/../../../../src/node/utils/Settings'); -const api = supertest('http://'+settings.ip+":"+settings.port); +const supertest = require(`${__dirname}/../../../../src/node_modules/supertest`); +const settings = require(`${__dirname}/../../../../src/node/utils/Settings`); +const api = supertest(`http://${settings.ip}:${settings.port}`); const apiKey = common.apiKey; -var apiVersion = '1.2.14'; +const apiVersion = '1.2.14'; -describe(__filename, function() { - describe('Connectivity for instance-level API tests', function() { - it('can connect', function(done) { +describe(__filename, function () { + describe('Connectivity for instance-level API tests', function () { + it('can connect', function (done) { api.get('/api/') .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); }); - describe('getStats', function() { - it('Gets the stats of a running instance', function(done) { + describe('getStats', function () { + it('Gets the stats of a running instance', function (done) { api.get(endPoint('getStats')) - .expect(function(res) { - if (res.body.code !== 0) throw new Error("getStats() failed"); + .expect((res) => { + if (res.body.code !== 0) throw new Error('getStats() failed'); if (!(('totalPads' in res.body.data) && (typeof res.body.data.totalPads === 'number'))) { throw new Error(`Response to getStats() does not contain field totalPads, or it's not a number: ${JSON.stringify(res.body.data)}`); @@ -44,7 +44,7 @@ describe(__filename, function() { }); }); -var endPoint = function(point, version){ +var endPoint = function (point, version) { version = version || apiVersion; - return '/api/'+version+'/'+point+'?apikey='+apiKey; -} + return `/api/${version}/${point}?apikey=${apiKey}`; +}; diff --git a/tests/backend/specs/api/pad.js b/tests/backend/specs/api/pad.js index cb242dc17..15ec4f0be 100644 --- a/tests/backend/specs/api/pad.js +++ b/tests/backend/specs/api/pad.js @@ -6,73 +6,73 @@ */ const common = require('../../common'); -const supertest = require(__dirname+'/../../../../src/node_modules/supertest'); -const settings = require(__dirname + '/../../../../src/node/utils/Settings'); -const api = supertest('http://'+settings.ip+":"+settings.port); -const async = require(__dirname+'/../../../../src/node_modules/async'); +const supertest = require(`${__dirname}/../../../../src/node_modules/supertest`); +const settings = require(`${__dirname}/../../../../src/node/utils/Settings`); +const api = supertest(`http://${settings.ip}:${settings.port}`); +const async = require(`${__dirname}/../../../../src/node_modules/async`); const apiKey = common.apiKey; -var apiVersion = 1; -var testPadId = makeid(); -var lastEdited = ""; -var text = generateLongText(); +let apiVersion = 1; +const testPadId = makeid(); +let lastEdited = ''; +const text = generateLongText(); /* * Html document with nested lists of different types, to test its import and * verify it is exported back correctly */ -var ulHtml = '
        • one
        • two
        • 0
        • 1
        • 2
          • 3
          • 4
        1. item
          1. item1
          2. item2
        '; +const ulHtml = '
        • one
        • two
        • 0
        • 1
        • 2
          • 3
          • 4
        1. item
          1. item1
          2. item2
        '; /* * When exported back, Etherpad produces an html which is not exactly the same * textually, but at least it remains standard compliant and has an equal DOM * structure. */ -var expectedHtml = '
        • one
        • two
        • 0
        • 1
        • 2
          • 3
          • 4
        1. item
          1. item1
          2. item2
        '; +const expectedHtml = '
        • one
        • two
        • 0
        • 1
        • 2
          • 3
          • 4
        1. item
          1. item1
          2. item2
        '; /* * Html document with space between list items, to test its import and * verify it is exported back correctly */ -var ulSpaceHtml = '
        • one
        '; +const ulSpaceHtml = '
        • one
        '; /* * When exported back, Etherpad produces an html which is not exactly the same * textually, but at least it remains standard compliant and has an equal DOM * structure. */ -var expectedSpaceHtml = '
        • one
        '; +const expectedSpaceHtml = '
        • one
        '; -describe(__filename, function() { - describe('Connectivity', function() { - it('can connect', function(done) { +describe(__filename, function () { + describe('Connectivity', function () { + it('can connect', function (done) { api.get('/api/') .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('API Versioning', function(){ - it('finds the version tag', function(done) { + describe('API Versioning', function () { + it('finds the version tag', function (done) { api.get('/api/') - .expect(function(res){ + .expect((res) => { apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); + if (!res.body.currentVersion) throw new Error('No version set in API'); return; }) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('Permission', function(){ - it('errors with invalid APIKey', function(done) { + describe('Permission', function () { + it('errors with invalid APIKey', function (done) { // This is broken because Etherpad doesn't handle HTTP codes properly see #2343 // If your APIKey is password you deserve to fail all tests anyway - var permErrorURL = '/api/'+apiVersion+'/createPad?apikey=password&padID=test'; + const permErrorURL = `/api/${apiVersion}/createPad?apikey=password&padID=test`; api.get(permErrorURL) - .expect(401, done) + .expect(401, done); }); - }) + }); /* Pad Tests Order of execution -> deletePad -- This gives us a guaranteed clear environment @@ -116,457 +116,457 @@ describe(__filename, function() { */ - describe('deletePad', function(){ - it('deletes a Pad', function(done) { - api.get(endPoint('deletePad')+"&padID="+testPadId) + describe('deletePad', function () { + it('deletes a Pad', function (done) { + api.get(`${endPoint('deletePad')}&padID=${testPadId}`) .expect('Content-Type', /json/) - .expect(200, done) // @TODO: we shouldn't expect 200 here since the pad may not exist + .expect(200, done); // @TODO: we shouldn't expect 200 here since the pad may not exist }); - }) + }); - describe('createPad', function(){ - it('creates a new Pad', function(done) { - api.get(endPoint('createPad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create new Pad"); + describe('createPad', function () { + it('creates a new Pad', function (done) { + api.get(`${endPoint('createPad')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to create new Pad'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getRevisionsCount', function(){ - it('gets revision count of Pad', function(done) { - api.get(endPoint('getRevisionsCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Revision Count"); - if(res.body.data.revisions !== 0) throw new Error("Incorrect Revision Count"); + describe('getRevisionsCount', function () { + it('gets revision count of Pad', function (done) { + api.get(`${endPoint('getRevisionsCount')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to get Revision Count'); + if (res.body.data.revisions !== 0) throw new Error('Incorrect Revision Count'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getSavedRevisionsCount', function(){ - it('gets saved revisions count of Pad', function(done) { - api.get(endPoint('getSavedRevisionsCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions Count"); - if(res.body.data.savedRevisions !== 0) throw new Error("Incorrect Saved Revisions Count"); + describe('getSavedRevisionsCount', function () { + it('gets saved revisions count of Pad', function (done) { + api.get(`${endPoint('getSavedRevisionsCount')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions Count'); + if (res.body.data.savedRevisions !== 0) throw new Error('Incorrect Saved Revisions Count'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('listSavedRevisions', function(){ - it('gets saved revision list of Pad', function(done) { - api.get(endPoint('listSavedRevisions')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions List"); - if(!res.body.data.savedRevisions.equals([])) throw new Error("Incorrect Saved Revisions List"); + describe('listSavedRevisions', function () { + it('gets saved revision list of Pad', function (done) { + api.get(`${endPoint('listSavedRevisions')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions List'); + if (!res.body.data.savedRevisions.equals([])) throw new Error('Incorrect Saved Revisions List'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getHTML', function(){ - it('get the HTML of Pad', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.html.length <= 1) throw new Error("Unable to get the HTML"); + describe('getHTML', function () { + it('get the HTML of Pad', function (done) { + api.get(`${endPoint('getHTML')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.html.length <= 1) throw new Error('Unable to get the HTML'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); describe('listAllPads', function () { it('list all pads', function (done) { api.get(endPoint('listAllPads')) - .expect(function (res) { + .expect((res) => { if (res.body.data.padIDs.includes(testPadId) !== true) { - throw new Error('Unable to find pad in pad list') + throw new Error('Unable to find pad in pad list'); } }) .expect('Content-Type', /json/) - .expect(200, done) - }) - }) + .expect(200, done); + }); + }); - describe('deletePad', function(){ - it('deletes a Pad', function(done) { - api.get(endPoint('deletePad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Deletion failed") + describe('deletePad', function () { + it('deletes a Pad', function (done) { + api.get(`${endPoint('deletePad')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Deletion failed'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); describe('listAllPads', function () { it('list all pads', function (done) { api.get(endPoint('listAllPads')) - .expect(function (res) { + .expect((res) => { if (res.body.data.padIDs.includes(testPadId) !== false) { - throw new Error('Test pad should not be in pads list') + throw new Error('Test pad should not be in pads list'); } }) .expect('Content-Type', /json/) - .expect(200, done) - }) - }) + .expect(200, done); + }); + }); - describe('getHTML', function(){ - it('get the HTML of a Pad -- Should return a failure', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 1) throw new Error("Pad deletion failed") + describe('getHTML', function () { + it('get the HTML of a Pad -- Should return a failure', function (done) { + api.get(`${endPoint('getHTML')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 1) throw new Error('Pad deletion failed'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('createPad', function(){ - it('creates a new Pad with text', function(done) { - api.get(endPoint('createPad')+"&padID="+testPadId+"&text=testText") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Creation failed") + describe('createPad', function () { + it('creates a new Pad with text', function (done) { + api.get(`${endPoint('createPad')}&padID=${testPadId}&text=testText`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Creation failed'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getText', function(){ - it('gets the Pad text and expect it to be testText with \n which is a line break', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.text !== "testText\n") throw new Error("Pad Creation with text") + describe('getText', function () { + it('gets the Pad text and expect it to be testText with \n which is a line break', function (done) { + api.get(`${endPoint('getText')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.text !== 'testText\n') throw new Error('Pad Creation with text'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('setText', function(){ - it('creates a new Pad with text', function(done) { + describe('setText', function () { + it('creates a new Pad with text', function (done) { api.post(endPoint('setText')) .send({ - "padID": testPadId, - "text": "testTextTwo", + padID: testPadId, + text: 'testTextTwo', }) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad setting text failed"); + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad setting text failed'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getText', function(){ - it('gets the Pad text', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.text !== "testTextTwo\n") throw new Error("Setting Text") + describe('getText', function () { + it('gets the Pad text', function (done) { + api.get(`${endPoint('getText')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.text !== 'testTextTwo\n') throw new Error('Setting Text'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getRevisionsCount', function(){ - it('gets Revision Count of a Pad', function(done) { - api.get(endPoint('getRevisionsCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.revisions !== 1) throw new Error("Unable to get text revision count") + describe('getRevisionsCount', function () { + it('gets Revision Count of a Pad', function (done) { + api.get(`${endPoint('getRevisionsCount')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.revisions !== 1) throw new Error('Unable to get text revision count'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('saveRevision', function(){ - it('saves Revision', function(done) { - api.get(endPoint('saveRevision')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to save Revision"); + describe('saveRevision', function () { + it('saves Revision', function (done) { + api.get(`${endPoint('saveRevision')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to save Revision'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getSavedRevisionsCount', function(){ - it('gets saved revisions count of Pad', function(done) { - api.get(endPoint('getSavedRevisionsCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions Count"); - if(res.body.data.savedRevisions !== 1) throw new Error("Incorrect Saved Revisions Count"); + describe('getSavedRevisionsCount', function () { + it('gets saved revisions count of Pad', function (done) { + api.get(`${endPoint('getSavedRevisionsCount')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions Count'); + if (res.body.data.savedRevisions !== 1) throw new Error('Incorrect Saved Revisions Count'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('listSavedRevisions', function(){ - it('gets saved revision list of Pad', function(done) { - api.get(endPoint('listSavedRevisions')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions List"); - if(!res.body.data.savedRevisions.equals([1])) throw new Error("Incorrect Saved Revisions List"); + describe('listSavedRevisions', function () { + it('gets saved revision list of Pad', function (done) { + api.get(`${endPoint('listSavedRevisions')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions List'); + if (!res.body.data.savedRevisions.equals([1])) throw new Error('Incorrect Saved Revisions List'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) - describe('padUsersCount', function(){ - it('gets User Count of a Pad', function(done) { - api.get(endPoint('padUsersCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.padUsersCount !== 0) throw new Error("Incorrect Pad User count") + }); + describe('padUsersCount', function () { + it('gets User Count of a Pad', function (done) { + api.get(`${endPoint('padUsersCount')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.padUsersCount !== 0) throw new Error('Incorrect Pad User count'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getReadOnlyID', function(){ - it('Gets the Read Only ID of a Pad', function(done) { - api.get(endPoint('getReadOnlyID')+"&padID="+testPadId) - .expect(function(res){ - if(!res.body.data.readOnlyID) throw new Error("No Read Only ID for Pad") + describe('getReadOnlyID', function () { + it('Gets the Read Only ID of a Pad', function (done) { + api.get(`${endPoint('getReadOnlyID')}&padID=${testPadId}`) + .expect((res) => { + if (!res.body.data.readOnlyID) throw new Error('No Read Only ID for Pad'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('listAuthorsOfPad', function(){ - it('Get Authors of the Pad', function(done) { - api.get(endPoint('listAuthorsOfPad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.authorIDs.length !== 0) throw new Error("# of Authors of pad is not 0") + describe('listAuthorsOfPad', function () { + it('Get Authors of the Pad', function (done) { + api.get(`${endPoint('listAuthorsOfPad')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.authorIDs.length !== 0) throw new Error('# of Authors of pad is not 0'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getLastEdited', function(){ - it('Get When Pad was left Edited', function(done) { - api.get(endPoint('getLastEdited')+"&padID="+testPadId) - .expect(function(res){ - if(!res.body.data.lastEdited){ - throw new Error("# of Authors of pad is not 0") - }else{ + describe('getLastEdited', function () { + it('Get When Pad was left Edited', function (done) { + api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`) + .expect((res) => { + if (!res.body.data.lastEdited) { + throw new Error('# of Authors of pad is not 0'); + } else { lastEdited = res.body.data.lastEdited; } }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('setText', function(){ - it('creates a new Pad with text', function(done) { + describe('setText', function () { + it('creates a new Pad with text', function (done) { api.post(endPoint('setText')) .send({ - "padID": testPadId, - "text": "testTextTwo", + padID: testPadId, + text: 'testTextTwo', }) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad setting text failed"); + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad setting text failed'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getLastEdited', function(){ - it('Get When Pad was left Edited', function(done) { - api.get(endPoint('getLastEdited')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.lastEdited <= lastEdited){ - throw new Error("Editing A Pad is not updating when it was last edited") + describe('getLastEdited', function () { + it('Get When Pad was left Edited', function (done) { + api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.lastEdited <= lastEdited) { + throw new Error('Editing A Pad is not updating when it was last edited'); } }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('padUsers', function(){ - it('gets User Count of a Pad', function(done) { - api.get(endPoint('padUsers')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.padUsers.length !== 0) throw new Error("Incorrect Pad Users") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('deletePad', function(){ - it('deletes a Pad', function(done) { - api.get(endPoint('deletePad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Deletion failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - var originalPadId = testPadId; - var newPadId = makeid(); - var copiedPadId = makeid(); - - describe('createPad', function(){ - it('creates a new Pad with text', function(done) { - api.get(endPoint('createPad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Creation failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('setText', function(){ - it('Sets text on a pad Id', function(done) { - api.post(endPoint('setText')+"&padID="+testPadId) - .field({text: text}) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Set Text failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('getText', function(){ - it('Gets text on a pad Id', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Get Text failed") - if(res.body.data.text !== text+"\n") throw new Error("Pad Text not set properly"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('setText', function(){ - it('Sets text on a pad Id including an explicit newline', function(done) { - api.post(endPoint('setText')+"&padID="+testPadId) - .field({text: text+'\n'}) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Set Text failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('getText', function(){ - it("Gets text on a pad Id and doesn't have an excess newline", function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Get Text failed") - if(res.body.data.text !== text+"\n") throw new Error("Pad Text not set properly"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('getLastEdited', function(){ - it('Gets when pad was last edited', function(done) { - api.get(endPoint('getLastEdited')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.lastEdited === 0) throw new Error("Get Last Edited Failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('movePad', function(){ - it('Move a Pad to a different Pad ID', function(done) { - api.get(endPoint('movePad')+"&sourceID="+testPadId+"&destinationID="+newPadId+"&force=true") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Moving Pad Failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('getText', function(){ - it('Gets text on a pad Id', function(done) { - api.get(endPoint('getText')+"&padID="+newPadId) - .expect(function(res){ - if(res.body.data.text !== text+"\n") throw new Error("Pad Get Text failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('movePad', function(){ - it('Move a Pad to a different Pad ID', function(done) { - api.get(endPoint('movePad')+"&sourceID="+newPadId+"&destinationID="+testPadId+"&force=false") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Moving Pad Failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('getText', function(){ - it('Gets text on a pad Id', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.text !== text+"\n") throw new Error("Pad Get Text failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('getLastEdited', function(){ - it('Gets when pad was last edited', function(done) { - api.get(endPoint('getLastEdited')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.lastEdited === 0) throw new Error("Get Last Edited Failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) - - describe('appendText', function(){ - it('Append text to a pad Id', function(done) { - api.get(endPoint('appendText', '1.2.13')+"&padID="+testPadId+"&text=hello") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Append Text failed"); + describe('padUsers', function () { + it('gets User Count of a Pad', function (done) { + api.get(`${endPoint('padUsers')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.padUsers.length !== 0) throw new Error('Incorrect Pad Users'); }) .expect('Content-Type', /json/) .expect(200, done); }); }); - describe('getText', function(){ - it('Gets text on a pad Id', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Get Text failed"); - if(res.body.data.text !== text+"hello\n") throw new Error("Pad Text not set properly"); + describe('deletePad', function () { + it('deletes a Pad', function (done) { + api.get(`${endPoint('deletePad')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Deletion failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + const originalPadId = testPadId; + const newPadId = makeid(); + const copiedPadId = makeid(); + + describe('createPad', function () { + it('creates a new Pad with text', function (done) { + api.get(`${endPoint('createPad')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Creation failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('setText', function () { + it('Sets text on a pad Id', function (done) { + api.post(`${endPoint('setText')}&padID=${testPadId}`) + .field({text}) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Set Text failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('getText', function () { + it('Gets text on a pad Id', function (done) { + api.get(`${endPoint('getText')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Get Text failed'); + if (res.body.data.text !== `${text}\n`) throw new Error('Pad Text not set properly'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('setText', function () { + it('Sets text on a pad Id including an explicit newline', function (done) { + api.post(`${endPoint('setText')}&padID=${testPadId}`) + .field({text: `${text}\n`}) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Set Text failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('getText', function () { + it("Gets text on a pad Id and doesn't have an excess newline", function (done) { + api.get(`${endPoint('getText')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Get Text failed'); + if (res.body.data.text !== `${text}\n`) throw new Error('Pad Text not set properly'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('getLastEdited', function () { + it('Gets when pad was last edited', function (done) { + api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.lastEdited === 0) throw new Error('Get Last Edited Failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('movePad', function () { + it('Move a Pad to a different Pad ID', function (done) { + api.get(`${endPoint('movePad')}&sourceID=${testPadId}&destinationID=${newPadId}&force=true`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Moving Pad Failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('getText', function () { + it('Gets text on a pad Id', function (done) { + api.get(`${endPoint('getText')}&padID=${newPadId}`) + .expect((res) => { + if (res.body.data.text !== `${text}\n`) throw new Error('Pad Get Text failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('movePad', function () { + it('Move a Pad to a different Pad ID', function (done) { + api.get(`${endPoint('movePad')}&sourceID=${newPadId}&destinationID=${testPadId}&force=false`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Moving Pad Failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('getText', function () { + it('Gets text on a pad Id', function (done) { + api.get(`${endPoint('getText')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.data.text !== `${text}\n`) throw new Error('Pad Get Text failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('getLastEdited', function () { + it('Gets when pad was last edited', function (done) { + api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.lastEdited === 0) throw new Error('Get Last Edited Failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('appendText', function () { + it('Append text to a pad Id', function (done) { + api.get(`${endPoint('appendText', '1.2.13')}&padID=${testPadId}&text=hello`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Append Text failed'); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + + describe('getText', function () { + it('Gets text on a pad Id', function (done) { + api.get(`${endPoint('getText')}&padID=${testPadId}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Pad Get Text failed'); + if (res.body.data.text !== `${text}hello\n`) throw new Error('Pad Text not set properly'); }) .expect('Content-Type', /json/) .expect(200, done); @@ -574,42 +574,42 @@ describe(__filename, function() { }); - describe('setHTML', function(){ - it('Sets the HTML of a Pad attempting to pass ugly HTML', function(done) { - var html = "
        Hello HTML
        "; + describe('setHTML', function () { + it('Sets the HTML of a Pad attempting to pass ugly HTML', function (done) { + const html = '
        Hello HTML
        '; api.post(endPoint('setHTML')) .send({ - "padID": testPadId, - "html": html, + padID: testPadId, + html, }) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Crappy HTML Can't be Imported[we weren't able to sanitize it']") + .expect((res) => { + if (res.body.code !== 0) throw new Error("Crappy HTML Can't be Imported[we weren't able to sanitize it']"); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('setHTML', function(){ - it('Sets the HTML of a Pad with complex nested lists of different types', function(done) { + describe('setHTML', function () { + it('Sets the HTML of a Pad with complex nested lists of different types', function (done) { api.post(endPoint('setHTML')) .send({ - "padID": testPadId, - "html": ulHtml, + padID: testPadId, + html: ulHtml, }) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("List HTML cant be imported") + .expect((res) => { + if (res.body.code !== 0) throw new Error('List HTML cant be imported'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getHTML', function(){ - it('Gets back the HTML of a Pad with complex nested lists of different types', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - var receivedHtml = res.body.data.html.replace("
        ", "").toLowerCase(); + describe('getHTML', function () { + it('Gets back the HTML of a Pad with complex nested lists of different types', function (done) { + api.get(`${endPoint('getHTML')}&padID=${testPadId}`) + .expect((res) => { + const receivedHtml = res.body.data.html.replace('
        ', '').toLowerCase(); if (receivedHtml !== expectedHtml) { throw new Error(`HTML received from export is not the one we were expecting. @@ -624,26 +624,26 @@ describe(__filename, function() { } }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('setHTML', function(){ - it('Sets the HTML of a Pad with white space between list items', function(done) { - api.get(endPoint('setHTML')+"&padID="+testPadId+"&html="+ulSpaceHtml) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("List HTML cant be imported") + describe('setHTML', function () { + it('Sets the HTML of a Pad with white space between list items', function (done) { + api.get(`${endPoint('setHTML')}&padID=${testPadId}&html=${ulSpaceHtml}`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('List HTML cant be imported'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('getHTML', function(){ - it('Gets back the HTML of a Pad with complex nested lists of different types', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - var receivedHtml = res.body.data.html.replace("
        ", "").toLowerCase(); + describe('getHTML', function () { + it('Gets back the HTML of a Pad with complex nested lists of different types', function (done) { + api.get(`${endPoint('getHTML')}&padID=${testPadId}`) + .expect((res) => { + const receivedHtml = res.body.data.html.replace('
        ', '').toLowerCase(); if (receivedHtml !== expectedSpaceHtml) { throw new Error(`HTML received from export is not the one we were expecting. Received: @@ -657,69 +657,69 @@ describe(__filename, function() { } }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('createPad', function(){ - it('errors if pad can be created', function(done) { - var badUrlChars = ["/", "%23", "%3F", "%26"]; + describe('createPad', function () { + it('errors if pad can be created', function (done) { + const badUrlChars = ['/', '%23', '%3F', '%26']; async.map( badUrlChars, - function (badUrlChar, cb) { - api.get(endPoint('createPad')+"&padID="+badUrlChar) - .expect(function(res){ - if(res.body.code !== 1) throw new Error("Pad with bad characters was created"); + (badUrlChar, cb) => { + api.get(`${endPoint('createPad')}&padID=${badUrlChar}`) + .expect((res) => { + if (res.body.code !== 1) throw new Error('Pad with bad characters was created'); }) .expect('Content-Type', /json/) .end(cb); }, done); }); - }) + }); - describe('copyPad', function(){ - it('copies the content of a existent pad', function(done) { - api.get(endPoint('copyPad')+"&sourceID="+testPadId+"&destinationID="+copiedPadId+"&force=true") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Copy Pad Failed") + describe('copyPad', function () { + it('copies the content of a existent pad', function (done) { + api.get(`${endPoint('copyPad')}&sourceID=${testPadId}&destinationID=${copiedPadId}&force=true`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Copy Pad Failed'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); - }) + }); - describe('copyPadWithoutHistory', function(){ - var sourcePadId = makeid(); - var newPad; + describe('copyPadWithoutHistory', function () { + const sourcePadId = makeid(); + let newPad; - before(function(done) { + before(function (done) { createNewPadWithHtml(sourcePadId, ulHtml, done); }); - beforeEach(function() { + beforeEach(function () { newPad = makeid(); - }) + }); - it('returns a successful response', function(done) { - api.get(endPoint('copyPadWithoutHistory')+"&sourceID="+sourcePadId+"&destinationID="+newPad+"&force=false") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Copy Pad Without History Failed") + it('returns a successful response', function (done) { + api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${newPad}&force=false`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Copy Pad Without History Failed'); }) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done); }); // this test validates if the source pad's text and attributes are kept - it('creates a new pad with the same content as the source pad', function(done) { - api.get(endPoint('copyPadWithoutHistory')+"&sourceID="+sourcePadId+"&destinationID="+newPad+"&force=false") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Copy Pad Without History Failed") + it('creates a new pad with the same content as the source pad', function (done) { + api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${newPad}&force=false`) + .expect((res) => { + if (res.body.code !== 0) throw new Error('Copy Pad Without History Failed'); }) - .end(function() { - api.get(endPoint('getHTML')+"&padID="+newPad) - .expect(function(res){ - var receivedHtml = res.body.data.html.replace("

        ", "").toLowerCase(); + .end(() => { + api.get(`${endPoint('getHTML')}&padID=${newPad}`) + .expect((res) => { + const receivedHtml = res.body.data.html.replace('

        ', '').toLowerCase(); if (receivedHtml !== expectedHtml) { throw new Error(`HTML received from export is not the one we were expecting. @@ -737,49 +737,49 @@ describe(__filename, function() { }); }); - context('when try copy a pad with a group that does not exist', function() { - var padId = makeid(); - var padWithNonExistentGroup = `notExistentGroup$${padId}` - it('throws an error', function(done) { - api.get(endPoint('copyPadWithoutHistory')+"&sourceID="+sourcePadId+"&destinationID="+padWithNonExistentGroup+"&force=true") - .expect(function(res){ + context('when try copy a pad with a group that does not exist', function () { + const padId = makeid(); + const padWithNonExistentGroup = `notExistentGroup$${padId}`; + it('throws an error', function (done) { + api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padWithNonExistentGroup}&force=true`) + .expect((res) => { // code 1, it means an error has happened - if(res.body.code !== 1) throw new Error("It should report an error") + if (res.body.code !== 1) throw new Error('It should report an error'); }) .expect(200, done); - }) + }); }); - context('when try copy a pad and destination pad already exist', function() { - var padIdExistent = makeid(); + context('when try copy a pad and destination pad already exist', function () { + const padIdExistent = makeid(); - before(function(done) { + before(function (done) { createNewPadWithHtml(padIdExistent, ulHtml, done); }); - context('and force is false', function() { - it('throws an error', function(done) { - api.get(endPoint('copyPadWithoutHistory')+"&sourceID="+sourcePadId+"&destinationID="+padIdExistent+"&force=false") - .expect(function(res){ + context('and force is false', function () { + it('throws an error', function (done) { + api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padIdExistent}&force=false`) + .expect((res) => { // code 1, it means an error has happened - if(res.body.code !== 1) throw new Error("It should report an error") + if (res.body.code !== 1) throw new Error('It should report an error'); }) .expect(200, done); }); }); - context('and force is true', function() { - it('returns a successful response', function(done) { - api.get(endPoint('copyPadWithoutHistory')+"&sourceID="+sourcePadId+"&destinationID="+padIdExistent+"&force=true") - .expect(function(res){ + context('and force is true', function () { + it('returns a successful response', function (done) { + api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padIdExistent}&force=true`) + .expect((res) => { // code 1, it means an error has happened - if(res.body.code !== 0) throw new Error("Copy pad without history with force true failed") + if (res.body.code !== 0) throw new Error('Copy pad without history with force true failed'); }) .expect(200, done); }); }); - }) - }) + }); + }); }); /* @@ -787,38 +787,38 @@ describe(__filename, function() { */ -var createNewPadWithHtml = function(padId, html, cb) { - api.get(endPoint('createPad')+"&padID="+padId) - .end(function() { - api.post(endPoint('setHTML')) - .send({ - "padID": padId, - "html": html, - }) - .end(cb); - }) -} +var createNewPadWithHtml = function (padId, html, cb) { + api.get(`${endPoint('createPad')}&padID=${padId}`) + .end(() => { + api.post(endPoint('setHTML')) + .send({ + padID: padId, + html, + }) + .end(cb); + }); +}; -var endPoint = function(point, version){ +var endPoint = function (point, version) { version = version || apiVersion; - return '/api/'+version+'/'+point+'?apikey='+apiKey; -} + return `/api/${version}/${point}?apikey=${apiKey}`; +}; function makeid() { - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for( var i=0; i < 5; i++ ){ + for (let i = 0; i < 5; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; } -function generateLongText(){ - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; +function generateLongText() { + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for( var i=0; i < 80000; i++ ){ + for (let i = 0; i < 80000; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; @@ -826,22 +826,19 @@ function generateLongText(){ // Need this to compare arrays (listSavedRevisions test) Array.prototype.equals = function (array) { - // if the other array is a falsy value, return - if (!array) - return false; - // compare lengths - can save a lot of time - if (this.length != array.length) - return false; - for (var i = 0, l=this.length; i < l; i++) { - // Check if we have nested arrays - if (this[i] instanceof Array && array[i] instanceof Array) { - // recurse into the nested arrays - if (!this[i].equals(array[i])) - return false; - } else if (this[i] != array[i]) { - // Warning - two different object instances will never be equal: {x:20} != {x:20} - return false; - } + // if the other array is a falsy value, return + if (!array) return false; + // compare lengths - can save a lot of time + if (this.length != array.length) return false; + for (let i = 0, l = this.length; i < l; i++) { + // Check if we have nested arrays + if (this[i] instanceof Array && array[i] instanceof Array) { + // recurse into the nested arrays + if (!this[i].equals(array[i])) return false; + } else if (this[i] != array[i]) { + // Warning - two different object instances will never be equal: {x:20} != {x:20} + return false; } - return true; -} + } + return true; +}; diff --git a/tests/backend/specs/api/sessionsAndGroups.js b/tests/backend/specs/api/sessionsAndGroups.js index 28d7eff7d..3b5e1a912 100644 --- a/tests/backend/specs/api/sessionsAndGroups.js +++ b/tests/backend/specs/api/sessionsAndGroups.js @@ -1,7 +1,7 @@ const assert = require('assert').strict; const common = require('../../common'); -const supertest = require(__dirname + '/../../../../src/node_modules/supertest'); -const settings = require(__dirname + '/../../../../src/node/utils/Settings'); +const supertest = require(`${__dirname}/../../../../src/node_modules/supertest`); +const settings = require(`${__dirname}/../../../../src/node/utils/Settings`); const api = supertest(`http://${settings.ip}:${settings.port}`); const apiKey = common.apiKey; @@ -11,9 +11,9 @@ let authorID = ''; let sessionID = ''; let padID = makeid(); -describe(__filename, function() { - describe('API Versioning', function() { - it('errors if can not connect', async function() { +describe(__filename, function () { + describe('API Versioning', function () { + it('errors if can not connect', async function () { await api.get('/api/') .expect(200) .expect((res) => { @@ -24,8 +24,8 @@ describe(__filename, function() { }); // BEGIN GROUP AND AUTHOR TESTS - ///////////////////////////////////// - ///////////////////////////////////// + // /////////////////////////////////// + // /////////////////////////////////// /* Tests performed -> createGroup() -- should return a groupID @@ -53,8 +53,8 @@ describe(__filename, function() { -> listPadsOfAuthor(authorID) */ - describe('API: Group creation and deletion', function() { - it('createGroup', async function() { + describe('API: Group creation and deletion', function () { + it('createGroup', async function () { await api.get(endPoint('createGroup')) .expect(200) .expect('Content-Type', /json/) @@ -65,8 +65,8 @@ describe(__filename, function() { }); }); - it('listSessionsOfGroup for empty group', async function() { - await api.get(endPoint('listSessionsOfGroup') + `&groupID=${groupID}`) + it('listSessionsOfGroup for empty group', async function () { + await api.get(`${endPoint('listSessionsOfGroup')}&groupID=${groupID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -75,8 +75,8 @@ describe(__filename, function() { }); }); - it('deleteGroup', async function() { - await api.get(endPoint('deleteGroup') + `&groupID=${groupID}`) + it('deleteGroup', async function () { + await api.get(`${endPoint('deleteGroup')}&groupID=${groupID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -84,8 +84,8 @@ describe(__filename, function() { }); }); - it('createGroupIfNotExistsFor', async function() { - await api.get(endPoint('createGroupIfNotExistsFor') + '&groupMapper=management') + it('createGroupIfNotExistsFor', async function () { + await api.get(`${endPoint('createGroupIfNotExistsFor')}&groupMapper=management`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -95,8 +95,8 @@ describe(__filename, function() { }); }); - describe('API: Author creation', function() { - it('createGroup', async function() { + describe('API: Author creation', function () { + it('createGroup', async function () { await api.get(endPoint('createGroup')) .expect(200) .expect('Content-Type', /json/) @@ -107,7 +107,7 @@ describe(__filename, function() { }); }); - it('createAuthor', async function() { + it('createAuthor', async function () { await api.get(endPoint('createAuthor')) .expect(200) .expect('Content-Type', /json/) @@ -117,8 +117,8 @@ describe(__filename, function() { }); }); - it('createAuthor with name', async function() { - await api.get(endPoint('createAuthor') + '&name=john') + it('createAuthor with name', async function () { + await api.get(`${endPoint('createAuthor')}&name=john`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -128,8 +128,8 @@ describe(__filename, function() { }); }); - it('createAuthorIfNotExistsFor', async function() { - await api.get(endPoint('createAuthorIfNotExistsFor') + '&authorMapper=chris') + it('createAuthorIfNotExistsFor', async function () { + await api.get(`${endPoint('createAuthorIfNotExistsFor')}&authorMapper=chris`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -138,8 +138,8 @@ describe(__filename, function() { }); }); - it('getAuthorName', async function() { - await api.get(endPoint('getAuthorName') + `&authorID=${authorID}`) + it('getAuthorName', async function () { + await api.get(`${endPoint('getAuthorName')}&authorID=${authorID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -149,10 +149,10 @@ describe(__filename, function() { }); }); - describe('API: Sessions', function() { - it('createSession', async function() { - await api.get(endPoint('createSession') + - `&authorID=${authorID}&groupID=${groupID}&validUntil=999999999999`) + describe('API: Sessions', function () { + it('createSession', async function () { + await api.get(`${endPoint('createSession') + }&authorID=${authorID}&groupID=${groupID}&validUntil=999999999999`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -162,8 +162,8 @@ describe(__filename, function() { }); }); - it('getSessionInfo', async function() { - await api.get(endPoint('getSessionInfo') + `&sessionID=${sessionID}`) + it('getSessionInfo', async function () { + await api.get(`${endPoint('getSessionInfo')}&sessionID=${sessionID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -174,8 +174,8 @@ describe(__filename, function() { }); }); - it('listSessionsOfGroup', async function() { - await api.get(endPoint('listSessionsOfGroup') + `&groupID=${groupID}`) + it('listSessionsOfGroup', async function () { + await api.get(`${endPoint('listSessionsOfGroup')}&groupID=${groupID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -184,8 +184,8 @@ describe(__filename, function() { }); }); - it('deleteSession', async function() { - await api.get(endPoint('deleteSession') + `&sessionID=${sessionID}`) + it('deleteSession', async function () { + await api.get(`${endPoint('deleteSession')}&sessionID=${sessionID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -193,8 +193,8 @@ describe(__filename, function() { }); }); - it('getSessionInfo of deleted session', async function() { - await api.get(endPoint('getSessionInfo') + `&sessionID=${sessionID}`) + it('getSessionInfo of deleted session', async function () { + await api.get(`${endPoint('getSessionInfo')}&sessionID=${sessionID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -203,9 +203,9 @@ describe(__filename, function() { }); }); - describe('API: Group pad management', function() { - it('listPads', async function() { - await api.get(endPoint('listPads') + `&groupID=${groupID}`) + describe('API: Group pad management', function () { + it('listPads', async function () { + await api.get(`${endPoint('listPads')}&groupID=${groupID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -214,8 +214,8 @@ describe(__filename, function() { }); }); - it('createGroupPad', async function() { - await api.get(endPoint('createGroupPad') + `&groupID=${groupID}&padName=${padID}`) + it('createGroupPad', async function () { + await api.get(`${endPoint('createGroupPad')}&groupID=${groupID}&padName=${padID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -224,8 +224,8 @@ describe(__filename, function() { }); }); - it('listPads after creating a group pad', async function() { - await api.get(endPoint('listPads') + `&groupID=${groupID}`) + it('listPads after creating a group pad', async function () { + await api.get(`${endPoint('listPads')}&groupID=${groupID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -235,9 +235,9 @@ describe(__filename, function() { }); }); - describe('API: Pad security', function() { - it('getPublicStatus', async function() { - await api.get(endPoint('getPublicStatus') + `&padID=${padID}`) + describe('API: Pad security', function () { + it('getPublicStatus', async function () { + await api.get(`${endPoint('getPublicStatus')}&padID=${padID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -246,8 +246,8 @@ describe(__filename, function() { }); }); - it('setPublicStatus', async function() { - await api.get(endPoint('setPublicStatus') + `&padID=${padID}&publicStatus=true`) + it('setPublicStatus', async function () { + await api.get(`${endPoint('setPublicStatus')}&padID=${padID}&publicStatus=true`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -255,8 +255,8 @@ describe(__filename, function() { }); }); - it('getPublicStatus after changing public status', async function() { - await api.get(endPoint('getPublicStatus') + `&padID=${padID}`) + it('getPublicStatus after changing public status', async function () { + await api.get(`${endPoint('getPublicStatus')}&padID=${padID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -267,12 +267,12 @@ describe(__filename, function() { }); // NOT SURE HOW TO POPULAT THIS /-_-\ - /////////////////////////////////////// - /////////////////////////////////////// + // ///////////////////////////////////// + // ///////////////////////////////////// - describe('API: Misc', function() { - it('listPadsOfAuthor', async function() { - await api.get(endPoint('listPadsOfAuthor') + `&authorID=${authorID}`) + describe('API: Misc', function () { + it('listPadsOfAuthor', async function () { + await api.get(`${endPoint('listPadsOfAuthor')}&authorID=${authorID}`) .expect(200) .expect('Content-Type', /json/) .expect((res) => { @@ -284,8 +284,7 @@ describe(__filename, function() { }); - -const endPoint = function(point) { +const endPoint = function (point) { return `/api/${apiVersion}/${point}?apikey=${apiKey}`; }; diff --git a/tests/backend/specs/api/tidy.js b/tests/backend/specs/api/tidy.js index 00fa345dc..78784fff7 100644 --- a/tests/backend/specs/api/tidy.js +++ b/tests/backend/specs/api/tidy.js @@ -1,21 +1,21 @@ -var assert = require('assert') - os = require('os'), - fs = require('fs'), - path = require('path'), - TidyHtml = null, - Settings = null; +const assert = require('assert'); +os = require('os'), +fs = require('fs'), +path = require('path'), +TidyHtml = null, +Settings = null; -var npm = require("../../../../src/node_modules/npm/lib/npm.js"); -var nodeify = require('../../../../src/node_modules/nodeify'); +const npm = require('../../../../src/node_modules/npm/lib/npm.js'); +const nodeify = require('../../../../src/node_modules/nodeify'); -describe(__filename, function() { - describe('tidyHtml', function() { - before(function(done) { - npm.load({}, function(err) { +describe(__filename, function () { + describe('tidyHtml', function () { + before(function (done) { + npm.load({}, (err) => { assert.ok(!err); TidyHtml = require('../../../../src/node/utils/TidyHtml'); Settings = require('../../../../src/node/utils/Settings'); - return done() + return done(); }); }); @@ -23,7 +23,7 @@ describe(__filename, function() { return nodeify(TidyHtml.tidy(file), callback); } - it('Tidies HTML', function(done) { + it('Tidies HTML', function (done) { // If the user hasn't configured Tidy, we skip this tests as it's required for this test if (!Settings.tidyHtml) { this.skip(); @@ -32,15 +32,15 @@ describe(__filename, function() { // Try to tidy up a bad HTML file const tmpDir = os.tmpdir(); - var tmpFile = path.join(tmpDir, 'tmp_' + (Math.floor(Math.random() * 1000000)) + '.html') + const tmpFile = path.join(tmpDir, `tmp_${Math.floor(Math.random() * 1000000)}.html`); fs.writeFileSync(tmpFile, '

        a paragraph

      • List without outer UL
      • trailing closing p

        '); - tidy(tmpFile, function(err){ + tidy(tmpFile, (err) => { assert.ok(!err); // Read the file again - var cleanedHtml = fs.readFileSync(tmpFile).toString(); + const cleanedHtml = fs.readFileSync(tmpFile).toString(); - var expectedHtml = [ + const expectedHtml = [ '', '', '', @@ -57,13 +57,13 @@ describe(__filename, function() { }); }); - it('can deal with errors', function(done) { + it('can deal with errors', function (done) { // If the user hasn't configured Tidy, we skip this tests as it's required for this test if (!Settings.tidyHtml) { this.skip(); } - tidy('/some/none/existing/file.html', function(err) { + tidy('/some/none/existing/file.html', (err) => { assert.ok(err); return done(); }); diff --git a/tests/backend/specs/caching_middleware.js b/tests/backend/specs/caching_middleware.js index a8ff2b615..e8e14a5cf 100644 --- a/tests/backend/specs/caching_middleware.js +++ b/tests/backend/specs/caching_middleware.js @@ -19,13 +19,13 @@ let agent; * * @param {string} fileContent the response body * @param {URI} resource resource URI - * @returns {boolean} if it is plaintext + * @returns {boolean} if it is plaintext */ -function isPlaintextResponse(fileContent, resource){ +function isPlaintextResponse(fileContent, resource) { // callback=require.define&v=1234 - const query = url.parse(resource)['query']; + const query = url.parse(resource).query; // require.define - const jsonp = queryString.parse(query)['callback']; + const jsonp = queryString.parse(query).callback; // returns true if the first letters in fileContent equal the content of `jsonp` return fileContent.substring(0, jsonp.length) === jsonp; @@ -36,40 +36,39 @@ function isPlaintextResponse(fileContent, resource){ * * @param {Request} request */ -function disableAutoDeflate(request){ - request._shouldUnzip = function(){ - return false - } +function disableAutoDeflate(request) { + request._shouldUnzip = function () { + return false; + }; } -describe(__filename, function() { +describe(__filename, function () { const backups = {}; const fantasyEncoding = 'brainwaves'; // non-working encoding until https://github.com/visionmedia/superagent/pull/1560 is resolved const packages = [ - "/javascripts/lib/ep_etherpad-lite/static/js/ace2_common.js?callback=require.define" - , "/javascripts/lib/ep_etherpad-lite/static/js/ace2_inner.js?callback=require.define" - , "/javascripts/lib/ep_etherpad-lite/static/js/pad.js?callback=require.define" - , "/javascripts/lib/ep_etherpad-lite/static/js/timeslider.js?callback=require.define" + '/javascripts/lib/ep_etherpad-lite/static/js/ace2_common.js?callback=require.define', + '/javascripts/lib/ep_etherpad-lite/static/js/ace2_inner.js?callback=require.define', + '/javascripts/lib/ep_etherpad-lite/static/js/pad.js?callback=require.define', + '/javascripts/lib/ep_etherpad-lite/static/js/timeslider.js?callback=require.define', ]; - before(async function() { + before(async function () { agent = await common.init(); }); - beforeEach(async function() { + beforeEach(async function () { backups.settings = {}; - backups.settings['minify'] = settings.minify; + backups.settings.minify = settings.minify; }); - afterEach(async function() { + afterEach(async function () { Object.assign(settings, backups.settings); }); - context('when minify is false', function(){ - before(async function() { + context('when minify is false', function () { + before(async function () { settings.minify = false; }); - it('gets packages uncompressed without Accept-Encoding gzip', async function() { - await Promise.all(packages.map(async (resource) => { - return agent.get(resource) + it('gets packages uncompressed without Accept-Encoding gzip', async function () { + await Promise.all(packages.map(async (resource) => agent.get(resource) .set('Accept-Encoding', fantasyEncoding) .use(disableAutoDeflate) .then((res) => { @@ -77,13 +76,11 @@ describe(__filename, function() { assert.equal(res.header['content-encoding'], undefined); assert.equal(isPlaintextResponse(res.text, resource), true); return; - }) - })) - }) + }))); + }); - it('gets packages compressed with Accept-Encoding gzip', async function() { - await Promise.all(packages.map(async (resource) => { - return agent.get(resource) + it('gets packages compressed with Accept-Encoding gzip', async function () { + await Promise.all(packages.map(async (resource) => agent.get(resource) .set('Accept-Encoding', 'gzip') .use(disableAutoDeflate) .then((res) => { @@ -91,36 +88,28 @@ describe(__filename, function() { assert.equal(res.header['content-encoding'], 'gzip'); assert.equal(isPlaintextResponse(res.text, resource), false); return; - }) - })) - }) + }))); + }); - it('does not cache content-encoding headers', async function(){ + it('does not cache content-encoding headers', async function () { await agent.get(packages[0]) - .set('Accept-Encoding', fantasyEncoding) - .then((res) => { - return assert.equal(res.header['content-encoding'], undefined); - }); + .set('Accept-Encoding', fantasyEncoding) + .then((res) => assert.equal(res.header['content-encoding'], undefined)); await agent.get(packages[0]) - .set('Accept-Encoding', 'gzip') - .then((res) => { - return assert.equal(res.header['content-encoding'], 'gzip'); - }); + .set('Accept-Encoding', 'gzip') + .then((res) => assert.equal(res.header['content-encoding'], 'gzip')); await agent.get(packages[0]) - .set('Accept-Encoding', fantasyEncoding) - .then((res) => { - return assert.equal(res.header['content-encoding'], undefined); - }); - }) + .set('Accept-Encoding', fantasyEncoding) + .then((res) => assert.equal(res.header['content-encoding'], undefined)); + }); }); - context('when minify is true', function(){ - before(async function() { + context('when minify is true', function () { + before(async function () { settings.minify = true; }); - it('gets packages uncompressed without Accept-Encoding gzip', async function() { - await Promise.all(packages.map(async (resource) => { - return agent.get(resource) + it('gets packages uncompressed without Accept-Encoding gzip', async function () { + await Promise.all(packages.map(async (resource) => agent.get(resource) .set('Accept-Encoding', fantasyEncoding) .use(disableAutoDeflate) .then((res) => { @@ -128,13 +117,11 @@ describe(__filename, function() { assert.equal(res.header['content-encoding'], undefined); assert.equal(isPlaintextResponse(res.text, resource), true); return; - }) - })) - }) + }))); + }); - it('gets packages compressed with Accept-Encoding gzip', async function() { - await Promise.all(packages.map(async (resource) => { - return agent.get(resource) + it('gets packages compressed with Accept-Encoding gzip', async function () { + await Promise.all(packages.map(async (resource) => agent.get(resource) .set('Accept-Encoding', 'gzip') .use(disableAutoDeflate) .then((res) => { @@ -142,27 +129,19 @@ describe(__filename, function() { assert.equal(res.header['content-encoding'], 'gzip'); assert.equal(isPlaintextResponse(res.text, resource), false); return; - }) - })) - }) + }))); + }); - it('does not cache content-encoding headers', async function(){ + it('does not cache content-encoding headers', async function () { await agent.get(packages[0]) - .set('Accept-Encoding', fantasyEncoding) - .then((res) => { - return assert.equal(res.header['content-encoding'], undefined); - }); + .set('Accept-Encoding', fantasyEncoding) + .then((res) => assert.equal(res.header['content-encoding'], undefined)); await agent.get(packages[0]) - .set('Accept-Encoding', 'gzip') - .then((res) => { - return assert.equal(res.header['content-encoding'], 'gzip'); - }); + .set('Accept-Encoding', 'gzip') + .then((res) => assert.equal(res.header['content-encoding'], 'gzip')); await agent.get(packages[0]) - .set('Accept-Encoding', fantasyEncoding) - .then((res) => { - return assert.equal(res.header['content-encoding'], undefined); - }); - }) + .set('Accept-Encoding', fantasyEncoding) + .then((res) => assert.equal(res.header['content-encoding'], undefined)); + }); }); - }); diff --git a/tests/backend/specs/contentcollector.js b/tests/backend/specs/contentcollector.js index d5d4ce63b..32faca66a 100644 --- a/tests/backend/specs/contentcollector.js +++ b/tests/backend/specs/contentcollector.js @@ -1,24 +1,24 @@ -const Changeset = require("../../../src/static/js/Changeset"); -const contentcollector = require("../../../src/static/js/contentcollector"); -const AttributePool = require("../../../src/static/js/AttributePool"); -const cheerio = require("../../../src/node_modules/cheerio"); -const util = require('util'); +const Changeset = require('../../../src/static/js/Changeset'); +const contentcollector = require('../../../src/static/js/contentcollector'); +const AttributePool = require('../../../src/static/js/AttributePool'); +const cheerio = require('../../../src/node_modules/cheerio'); +const util = require('util'); const tests = { - nestedLi:{ - description: "Complex nested Li", + nestedLi: { + description: 'Complex nested Li', html: '
        1. one
          1. 1.1
        2. two
        ', - expectedLineAttribs : [ - '*0*1*2*3+1+3', '*0*4*2*5+1+3', '*0*1*2*5+1+3' + expectedLineAttribs: [ + '*0*1*2*3+1+3', '*0*4*2*5+1+3', '*0*1*2*5+1+3', ], expectedText: [ - '*one', '*1.1', '*two' - ] + '*one', '*1.1', '*two', + ], }, - complexNest:{ - description: "Complex list of different types", + complexNest: { + description: 'Complex list of different types', html: '
        • one
        • two
        • 0
        • 1
        • 2
          • 3
          • 4
        1. item
          1. item1
          2. item2
        ', - expectedLineAttribs : [ + expectedLineAttribs: [ '*0*1*2+1+3', '*0*1*2+1+3', '*0*1*2+1+1', @@ -28,113 +28,116 @@ const tests = { '*0*3*2+1+1', '*0*4*2*5+1+4', '*0*6*2*7+1+5', - '*0*6*2*7+1+5' + '*0*6*2*7+1+5', ], expectedText: [ - '*one', '*two', - '*0', '*1', - '*2', '*3', - '*4', '*item', - '*item1', '*item2' - ] + '*one', + '*two', + '*0', + '*1', + '*2', + '*3', + '*4', + '*item', + '*item1', + '*item2', + ], }, ul: { - description : "Tests if uls properly get attributes", - html : "
        • a
        • b
        div

        foo

        ", - expectedLineAttribs : [ '*0*1*2+1+1', '*0*1*2+1+1', '+3' , '+3'], - expectedText: ["*a","*b", "div", "foo"] - } - , + description: 'Tests if uls properly get attributes', + html: '
        • a
        • b
        div

        foo

        ', + expectedLineAttribs: ['*0*1*2+1+1', '*0*1*2+1+1', '+3', '+3'], + expectedText: ['*a', '*b', 'div', 'foo'], + }, ulIndented: { - description : "Tests if indented uls properly get attributes", - html : "
        • a
          • b
        • a

        foo

        ", - expectedLineAttribs : [ '*0*1*2+1+1', '*0*3*2+1+1', '*0*1*2+1+1', '+3' ], - expectedText: ["*a","*b", "*a", "foo"] + description: 'Tests if indented uls properly get attributes', + html: '
        • a
          • b
        • a

        foo

        ', + expectedLineAttribs: ['*0*1*2+1+1', '*0*3*2+1+1', '*0*1*2+1+1', '+3'], + expectedText: ['*a', '*b', '*a', 'foo'], }, ol: { - description : "Tests if ols properly get line numbers when in a normal OL", - html : "
        1. a
        2. b
        3. c

        test

        ", - expectedLineAttribs : ['*0*1*2*3+1+1', '*0*1*2*3+1+1', '*0*1*2*3+1+1', '+4'], - expectedText: ["*a","*b","*c", "test"], - noteToSelf: "Ensure empty P does not induce line attribute marker, wont this break the editor?" - } - , - lineDoBreakInOl:{ - description : "A single completely empty line break within an ol should reset count if OL is closed off..", - html : "
        1. should be 1

        hello

        1. should be 1
        2. should be 2

        ", - expectedLineAttribs : [ '*0*1*2*3+1+b', '+5', '*0*1*2*4+1+b', '*0*1*2*4+1+b', '' ], - expectedText: ["*should be 1","hello", "*should be 1","*should be 2", ""], - noteToSelf: "Shouldn't include attribute marker in the

        line" + description: 'Tests if ols properly get line numbers when in a normal OL', + html: '

        1. a
        2. b
        3. c

        test

        ', + expectedLineAttribs: ['*0*1*2*3+1+1', '*0*1*2*3+1+1', '*0*1*2*3+1+1', '+4'], + expectedText: ['*a', '*b', '*c', 'test'], + noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?', }, - bulletListInOL:{ - description : "A bullet within an OL should not change numbering..", - html : "
        1. should be 1
          • should be a bullet
        2. should be 2

        ", - expectedLineAttribs : [ '*0*1*2*3+1+b', '*0*4*2*3+1+i', '*0*1*2*5+1+b', '' ], - expectedText: ["*should be 1","*should be a bullet","*should be 2", ""] + lineDoBreakInOl: { + description: 'A single completely empty line break within an ol should reset count if OL is closed off..', + html: '
        1. should be 1

        hello

        1. should be 1
        2. should be 2

        ', + expectedLineAttribs: ['*0*1*2*3+1+b', '+5', '*0*1*2*4+1+b', '*0*1*2*4+1+b', ''], + expectedText: ['*should be 1', 'hello', '*should be 1', '*should be 2', ''], + noteToSelf: "Shouldn't include attribute marker in the

        line", }, - testP:{ - description : "A single

        should create a new line", - html : "

        ", - expectedLineAttribs : [ '', ''], - expectedText: ["", ""], - noteToSelf: "

        should create a line break but not break numbering" + bulletListInOL: { + description: 'A bullet within an OL should not change numbering..', + html: '
        1. should be 1
          • should be a bullet
        2. should be 2

        ', + expectedLineAttribs: ['*0*1*2*3+1+b', '*0*4*2*3+1+i', '*0*1*2*5+1+b', ''], + expectedText: ['*should be 1', '*should be a bullet', '*should be 2', ''], + }, + testP: { + description: 'A single

        should create a new line', + html: '

        ', + expectedLineAttribs: ['', ''], + expectedText: ['', ''], + noteToSelf: '

        should create a line break but not break numbering', }, nestedOl: { - description : "Tests if ols properly get line numbers when in a normal OL", - html : "a
        1. b
          1. c
        notlist

        foo

        ", - expectedLineAttribs : [ '+1', '*0*1*2*3+1+1', '*0*4*2*5+1+1', '+7', '+3' ], - expectedText: ["a","*b","*c", "notlist", "foo"], - noteToSelf: "Ensure empty P does not induce line attribute marker, wont this break the editor?" + description: 'Tests if ols properly get line numbers when in a normal OL', + html: 'a
        1. b
          1. c
        notlist

        foo

        ', + expectedLineAttribs: ['+1', '*0*1*2*3+1+1', '*0*4*2*5+1+1', '+7', '+3'], + expectedText: ['a', '*b', '*c', 'notlist', 'foo'], + noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?', }, nestedOl: { - description : "First item being an UL then subsequent being OL will fail", - html : "
        • a
          1. b
          2. c
        ", - expectedLineAttribs : [ '+1', '*0*1*2*3+1+1', '*0*4*2*5+1+1' ], - expectedText: ["a","*b","*c"], - noteToSelf: "Ensure empty P does not induce line attribute marker, wont this break the editor?", - disabled: true + description: 'First item being an UL then subsequent being OL will fail', + html: '
        • a
          1. b
          2. c
        ', + expectedLineAttribs: ['+1', '*0*1*2*3+1+1', '*0*4*2*5+1+1'], + expectedText: ['a', '*b', '*c'], + noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?', + disabled: true, }, - lineDontBreakOL:{ - description : "A single completely empty line break within an ol should NOT reset count", - html : "
        1. should be 1
        2. should be 2
        3. should be 3

        ", - expectedLineAttribs : [ ], - expectedText: ["*should be 1","*should be 2","*should be 3"], + lineDontBreakOL: { + description: 'A single completely empty line break within an ol should NOT reset count', + html: '
        1. should be 1
        2. should be 2
        3. should be 3

        ', + expectedLineAttribs: [], + expectedText: ['*should be 1', '*should be 2', '*should be 3'], noteToSelf: "

        should create a line break but not break numbering -- This is what I can't get working!", - disabled: true - } + disabled: true, + }, -} +}; -describe(__filename, function() { - for (let test in tests) { - let testObj = tests[test]; - describe(test, function() { +describe(__filename, function () { + for (const test in tests) { + const testObj = tests[test]; + describe(test, function () { if (testObj.disabled) { - return xit("DISABLED:", test, function(done){ + return xit('DISABLED:', test, function (done) { done(); - }) + }); } - it(testObj.description, function(done) { - var $ = cheerio.load(testObj.html); // Load HTML into Cheerio - var doc = $('html')[0]; // Creates a dom-like representation of HTML + it(testObj.description, function (done) { + const $ = cheerio.load(testObj.html); // Load HTML into Cheerio + const doc = $('html')[0]; // Creates a dom-like representation of HTML // Create an empty attribute pool - var apool = new AttributePool(); + const apool = new AttributePool(); // Convert a dom tree into a list of lines and attribute liens // using the content collector object - var cc = contentcollector.makeContentCollector(true, null, apool); + const cc = contentcollector.makeContentCollector(true, null, apool); cc.collectContent(doc); - var result = cc.finish(); - var recievedAttributes = result.lineAttribs; - var expectedAttributes = testObj.expectedLineAttribs; - var recievedText = new Array(result.lines) - var expectedText = testObj.expectedText; + const result = cc.finish(); + const recievedAttributes = result.lineAttribs; + const expectedAttributes = testObj.expectedLineAttribs; + const recievedText = new Array(result.lines); + const expectedText = testObj.expectedText; // Check recieved text matches the expected text if (arraysEqual(recievedText[0], expectedText)) { // console.log("PASS: Recieved Text did match Expected Text\nRecieved:", recievedText[0], "\nExpected:", testObj.expectedText) } else { - console.error("FAIL: Recieved Text did not match Expected Text\nRecieved:", recievedText[0], "\nExpected:", testObj.expectedText) + console.error('FAIL: Recieved Text did not match Expected Text\nRecieved:', recievedText[0], '\nExpected:', testObj.expectedText); throw new Error(); } @@ -143,9 +146,9 @@ describe(__filename, function() { // console.log("PASS: Recieved Attributes matched Expected Attributes"); done(); } else { - console.error("FAIL", test, testObj.description); - console.error("FAIL: Recieved Attributes did not match Expected Attributes\nRecieved: ", recievedAttributes, "\nExpected: ", expectedAttributes) - console.error("FAILING HTML", testObj.html); + console.error('FAIL', test, testObj.description); + console.error('FAIL: Recieved Attributes did not match Expected Attributes\nRecieved: ', recievedAttributes, '\nExpected: ', expectedAttributes); + console.error('FAILING HTML', testObj.html); throw new Error(); } }); @@ -154,8 +157,6 @@ describe(__filename, function() { }); - - function arraysEqual(a, b) { if (a === b) return true; if (a == null || b == null) return false; @@ -166,7 +167,7 @@ function arraysEqual(a, b) { // Please note that calling sort on an array will modify that array. // you might want to clone your array first. - for (var i = 0; i < a.length; ++i) { + for (let i = 0; i < a.length; ++i) { if (a[i] !== b[i]) return false; } return true; diff --git a/tests/backend/specs/hooks.js b/tests/backend/specs/hooks.js index 598115b0d..0e0f8075f 100644 --- a/tests/backend/specs/hooks.js +++ b/tests/backend/specs/hooks.js @@ -1,6 +1,6 @@ /* global __dirname, __filename, afterEach, beforeEach, describe, it, process, require */ -function m(mod) { return __dirname + '/../../../src/' + mod; } +function m(mod) { return `${__dirname}/../../../src/${mod}`; } const assert = require('assert').strict; const common = require('../common'); @@ -10,13 +10,13 @@ const sinon = require(m('node_modules/sinon')); const logger = common.logger; -describe(__filename, function() { +describe(__filename, function () { const hookName = 'testHook'; const hookFnName = 'testPluginFileName:testHookFunctionName'; let testHooks; // Convenience shorthand for plugins.hooks[hookName]. let hook; // Convenience shorthand for plugins.hooks[hookName][0]. - beforeEach(async function() { + beforeEach(async function () { // Make sure these are not already set so that we don't accidentally step on someone else's // toes: assert(plugins.hooks[hookName] == null); @@ -30,24 +30,22 @@ describe(__filename, function() { testHooks = plugins.hooks[hookName]; }); - afterEach(async function() { + afterEach(async function () { sinon.restore(); delete plugins.hooks[hookName]; delete hooks.deprecationNotices[hookName]; delete hooks.exportedForTestingOnly.deprecationWarned[hookFnName]; }); - const makeHook = (ret) => { - return { - hook_name: hookName, - // Many tests will likely want to change this. Unfortunately, we can't use a convenience - // wrapper like `(...args) => hookFn(..args)` because the hooks look at Function.length and - // change behavior depending on the number of parameters. - hook_fn: (hn, ctx, cb) => cb(ret), - hook_fn_name: hookFnName, - part: {plugin: 'testPluginName'}, - }; - }; + const makeHook = (ret) => ({ + hook_name: hookName, + // Many tests will likely want to change this. Unfortunately, we can't use a convenience + // wrapper like `(...args) => hookFn(..args)` because the hooks look at Function.length and + // change behavior depending on the number of parameters. + hook_fn: (hn, ctx, cb) => cb(ret), + hook_fn_name: hookFnName, + part: {plugin: 'testPluginName'}, + }); // Hook functions that should work for both synchronous and asynchronous hooks. const supportedSyncHookFunctions = [ @@ -95,30 +93,30 @@ describe(__filename, function() { }, ]; - describe('callHookFnSync', function() { + describe('callHookFnSync', function () { const callHookFnSync = hooks.exportedForTestingOnly.callHookFnSync; // Convenience shorthand. - describe('basic behavior', function() { - it('passes hook name', async function() { + describe('basic behavior', function () { + it('passes hook name', async function () { hook.hook_fn = (hn) => { assert.equal(hn, hookName); }; callHookFnSync(hook); }); - it('passes context', async function() { + it('passes context', async function () { for (const val of ['value', null, undefined]) { hook.hook_fn = (hn, ctx) => { assert.equal(ctx, val); }; callHookFnSync(hook, val); } }); - it('returns the value provided to the callback', async function() { + it('returns the value provided to the callback', async function () { for (const val of ['value', null, undefined]) { hook.hook_fn = (hn, ctx, cb) => { cb(ctx); }; assert.equal(callHookFnSync(hook, val), val); } }); - it('returns the value returned by the hook function', async function() { + it('returns the value returned by the hook function', async function () { for (const val of ['value', null, undefined]) { // Must not have the cb parameter otherwise returning undefined will error. hook.hook_fn = (hn, ctx) => ctx; @@ -126,17 +124,17 @@ describe(__filename, function() { } }); - it('does not catch exceptions', async function() { + it('does not catch exceptions', async function () { hook.hook_fn = () => { throw new Error('test exception'); }; assert.throws(() => callHookFnSync(hook), {message: 'test exception'}); }); - it('callback returns undefined', async function() { + it('callback returns undefined', async function () { hook.hook_fn = (hn, ctx, cb) => { assert.equal(cb('foo'), undefined); }; callHookFnSync(hook); }); - it('checks for deprecation', async function() { + it('checks for deprecation', async function () { sinon.stub(console, 'warn'); hooks.deprecationNotices[hookName] = 'test deprecation'; callHookFnSync(hook); @@ -146,9 +144,9 @@ describe(__filename, function() { }); }); - describe('supported hook function styles', function() { + describe('supported hook function styles', function () { for (const tc of supportedSyncHookFunctions) { - it(tc.name, async function() { + it(tc.name, async function () { sinon.stub(console, 'warn'); sinon.stub(console, 'error'); hook.hook_fn = tc.fn; @@ -164,7 +162,7 @@ describe(__filename, function() { } }); - describe('bad hook function behavior (other than double settle)', function() { + describe('bad hook function behavior (other than double settle)', function () { const promise1 = Promise.resolve('val1'); const promise2 = Promise.resolve('val2'); @@ -192,7 +190,7 @@ describe(__filename, function() { ]; for (const tc of testCases) { - it(tc.name, async function() { + it(tc.name, async function () { sinon.stub(console, 'error'); hook.hook_fn = tc.fn; assert.equal(callHookFnSync(hook), tc.wantVal); @@ -204,8 +202,8 @@ describe(__filename, function() { // Test various ways a hook might attempt to settle twice. (Examples: call the callback a second // time, or call the callback and then return a value.) - describe('bad hook function behavior (double settle)', function() { - beforeEach(function() { + describe('bad hook function behavior (double settle)', function () { + beforeEach(function () { sinon.stub(console, 'error'); }); @@ -243,7 +241,7 @@ describe(__filename, function() { // settle would complicate the tests, and it is sufficient to test only double settles. if (step1.async && step2.async) continue; - it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function() { + it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function () { hook.hook_fn = (hn, ctx, cb) => { step1.fn(cb, new Error(ctx.ret1), ctx.ret1); return step2.fn(cb, new Error(ctx.ret2), ctx.ret2); @@ -306,7 +304,7 @@ describe(__filename, function() { // doesn't, so skip those cases. if (step1.rejects !== step2.rejects) continue; - it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function() { + it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function () { const err = new Error('val'); hook.hook_fn = (hn, ctx, cb) => { step1.fn(cb, err, 'val'); @@ -329,66 +327,66 @@ describe(__filename, function() { }); }); - describe('hooks.callAll', function() { - describe('basic behavior', function() { - it('calls all in order', async function() { + describe('hooks.callAll', function () { + describe('basic behavior', function () { + it('calls all in order', async function () { testHooks.length = 0; testHooks.push(makeHook(1), makeHook(2), makeHook(3)); assert.deepEqual(hooks.callAll(hookName), [1, 2, 3]); }); - it('passes hook name', async function() { + it('passes hook name', async function () { hook.hook_fn = (hn) => { assert.equal(hn, hookName); }; hooks.callAll(hookName); }); - it('undefined context -> {}', async function() { + it('undefined context -> {}', async function () { hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); }; hooks.callAll(hookName); }); - it('null context -> {}', async function() { + it('null context -> {}', async function () { hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); }; hooks.callAll(hookName, null); }); - it('context unmodified', async function() { + it('context unmodified', async function () { const wantContext = {}; hook.hook_fn = (hn, ctx) => { assert.equal(ctx, wantContext); }; hooks.callAll(hookName, wantContext); }); }); - describe('result processing', function() { - it('no registered hooks (undefined) -> []', async function() { + describe('result processing', function () { + it('no registered hooks (undefined) -> []', async function () { delete plugins.hooks.testHook; assert.deepEqual(hooks.callAll(hookName), []); }); - it('no registered hooks (empty list) -> []', async function() { + it('no registered hooks (empty list) -> []', async function () { testHooks.length = 0; assert.deepEqual(hooks.callAll(hookName), []); }); - it('flattens one level', async function() { + it('flattens one level', async function () { testHooks.length = 0; testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]])); assert.deepEqual(hooks.callAll(hookName), [1, 2, [3]]); }); - it('filters out undefined', async function() { + it('filters out undefined', async function () { testHooks.length = 0; testHooks.push(makeHook(), makeHook([2]), makeHook([[3]])); assert.deepEqual(hooks.callAll(hookName), [2, [3]]); }); - it('preserves null', async function() { + it('preserves null', async function () { testHooks.length = 0; testHooks.push(makeHook(null), makeHook([2]), makeHook([[3]])); assert.deepEqual(hooks.callAll(hookName), [null, 2, [3]]); }); - it('all undefined -> []', async function() { + it('all undefined -> []', async function () { testHooks.length = 0; testHooks.push(makeHook(), makeHook()); assert.deepEqual(hooks.callAll(hookName), []); @@ -396,23 +394,23 @@ describe(__filename, function() { }); }); - describe('callHookFnAsync', function() { + describe('callHookFnAsync', function () { const callHookFnAsync = hooks.exportedForTestingOnly.callHookFnAsync; // Convenience shorthand. - describe('basic behavior', function() { - it('passes hook name', async function() { + describe('basic behavior', function () { + it('passes hook name', async function () { hook.hook_fn = (hn) => { assert.equal(hn, hookName); }; await callHookFnAsync(hook); }); - it('passes context', async function() { + it('passes context', async function () { for (const val of ['value', null, undefined]) { hook.hook_fn = (hn, ctx) => { assert.equal(ctx, val); }; await callHookFnAsync(hook, val); } }); - it('returns the value provided to the callback', async function() { + it('returns the value provided to the callback', async function () { for (const val of ['value', null, undefined]) { hook.hook_fn = (hn, ctx, cb) => { cb(ctx); }; assert.equal(await callHookFnAsync(hook, val), val); @@ -420,7 +418,7 @@ describe(__filename, function() { } }); - it('returns the value returned by the hook function', async function() { + it('returns the value returned by the hook function', async function () { for (const val of ['value', null, undefined]) { // Must not have the cb parameter otherwise returning undefined will never resolve. hook.hook_fn = (hn, ctx) => ctx; @@ -429,27 +427,27 @@ describe(__filename, function() { } }); - it('rejects if it throws an exception', async function() { + it('rejects if it throws an exception', async function () { hook.hook_fn = () => { throw new Error('test exception'); }; await assert.rejects(callHookFnAsync(hook), {message: 'test exception'}); }); - it('rejects if rejected Promise passed to callback', async function() { + it('rejects if rejected Promise passed to callback', async function () { hook.hook_fn = (hn, ctx, cb) => cb(Promise.reject(new Error('test exception'))); await assert.rejects(callHookFnAsync(hook), {message: 'test exception'}); }); - it('rejects if rejected Promise returned', async function() { + it('rejects if rejected Promise returned', async function () { hook.hook_fn = (hn, ctx, cb) => Promise.reject(new Error('test exception')); await assert.rejects(callHookFnAsync(hook), {message: 'test exception'}); }); - it('callback returns undefined', async function() { + it('callback returns undefined', async function () { hook.hook_fn = (hn, ctx, cb) => { assert.equal(cb('foo'), undefined); }; await callHookFnAsync(hook); }); - it('checks for deprecation', async function() { + it('checks for deprecation', async function () { sinon.stub(console, 'warn'); hooks.deprecationNotices[hookName] = 'test deprecation'; await callHookFnAsync(hook); @@ -459,7 +457,7 @@ describe(__filename, function() { }); }); - describe('supported hook function styles', function() { + describe('supported hook function styles', function () { const supportedHookFunctions = supportedSyncHookFunctions.concat([ { name: 'legacy async cb', @@ -541,7 +539,7 @@ describe(__filename, function() { ]); for (const tc of supportedSyncHookFunctions.concat(supportedHookFunctions)) { - it(tc.name, async function() { + it(tc.name, async function () { sinon.stub(console, 'warn'); sinon.stub(console, 'error'); hook.hook_fn = tc.fn; @@ -559,8 +557,8 @@ describe(__filename, function() { // Test various ways a hook might attempt to settle twice. (Examples: call the callback a second // time, or call the callback and then return a value.) - describe('bad hook function behavior (double settle)', function() { - beforeEach(function() { + describe('bad hook function behavior (double settle)', function () { + beforeEach(function () { sinon.stub(console, 'error'); }); @@ -688,7 +686,7 @@ describe(__filename, function() { // There can't be a second step if the first step is to return or throw. if (step1.name.startsWith('return ') || step1.name === 'throw') continue; for (const step2 of behaviors) { - it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function() { + it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function () { hook.hook_fn = (hn, ctx, cb) => { step1.fn(cb, new Error(ctx.ret1), ctx.ret1); return step2.fn(cb, new Error(ctx.ret2), ctx.ret2); @@ -729,8 +727,8 @@ describe(__filename, function() { } } assert.equal(console.error.callCount, 1, - 'Got errors:\n' + - console.error.getCalls().map((call) => call.args[0]).join('\n')); + `Got errors:\n${ + console.error.getCalls().map((call) => call.args[0]).join('\n')}`); assert.match(console.error.getCall(0).args[0], /DOUBLE SETTLE BUG/); assert(asyncErr instanceof Error); assert.match(asyncErr.message, /DOUBLE SETTLE BUG/); @@ -741,7 +739,7 @@ describe(__filename, function() { // doesn't, so skip those cases. if (step1.rejects !== step2.rejects) continue; - it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function() { + it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function () { const err = new Error('val'); hook.hook_fn = (hn, ctx, cb) => { step1.fn(cb, err, 'val'); @@ -764,9 +762,9 @@ describe(__filename, function() { }); }); - describe('hooks.aCallAll', function() { - describe('basic behavior', function() { - it('calls all asynchronously, returns values in order', async function() { + describe('hooks.aCallAll', function () { + describe('basic behavior', function () { + it('calls all asynchronously, returns values in order', async function () { testHooks.length = 0; // Delete the boilerplate hook -- this test doesn't use it. let nextIndex = 0; const hookPromises = []; @@ -800,35 +798,35 @@ describe(__filename, function() { assert.deepEqual(await p, [0, 1]); }); - it('passes hook name', async function() { + it('passes hook name', async function () { hook.hook_fn = async (hn) => { assert.equal(hn, hookName); }; await hooks.aCallAll(hookName); }); - it('undefined context -> {}', async function() { + it('undefined context -> {}', async function () { hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); }; await hooks.aCallAll(hookName); }); - it('null context -> {}', async function() { + it('null context -> {}', async function () { hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); }; await hooks.aCallAll(hookName, null); }); - it('context unmodified', async function() { + it('context unmodified', async function () { const wantContext = {}; hook.hook_fn = async (hn, ctx) => { assert.equal(ctx, wantContext); }; await hooks.aCallAll(hookName, wantContext); }); }); - describe('aCallAll callback', function() { - it('exception in callback rejects', async function() { + describe('aCallAll callback', function () { + it('exception in callback rejects', async function () { const p = hooks.aCallAll(hookName, {}, () => { throw new Error('test exception'); }); await assert.rejects(p, {message: 'test exception'}); }); - it('propagates error on exception', async function() { + it('propagates error on exception', async function () { hook.hook_fn = () => { throw new Error('test exception'); }; await hooks.aCallAll(hookName, {}, (err) => { assert(err instanceof Error); @@ -836,54 +834,54 @@ describe(__filename, function() { }); }); - it('propagages null error on success', async function() { + it('propagages null error on success', async function () { await hooks.aCallAll(hookName, {}, (err) => { assert(err == null, `got non-null error: ${err}`); }); }); - it('propagages results on success', async function() { + it('propagages results on success', async function () { hook.hook_fn = () => 'val'; await hooks.aCallAll(hookName, {}, (err, results) => { assert.deepEqual(results, ['val']); }); }); - it('returns callback return value', async function() { + it('returns callback return value', async function () { assert.equal(await hooks.aCallAll(hookName, {}, () => 'val'), 'val'); }); }); - describe('result processing', function() { - it('no registered hooks (undefined) -> []', async function() { + describe('result processing', function () { + it('no registered hooks (undefined) -> []', async function () { delete plugins.hooks[hookName]; assert.deepEqual(await hooks.aCallAll(hookName), []); }); - it('no registered hooks (empty list) -> []', async function() { + it('no registered hooks (empty list) -> []', async function () { testHooks.length = 0; assert.deepEqual(await hooks.aCallAll(hookName), []); }); - it('flattens one level', async function() { + it('flattens one level', async function () { testHooks.length = 0; testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]])); assert.deepEqual(await hooks.aCallAll(hookName), [1, 2, [3]]); }); - it('filters out undefined', async function() { + it('filters out undefined', async function () { testHooks.length = 0; testHooks.push(makeHook(), makeHook([2]), makeHook([[3]]), makeHook(Promise.resolve())); assert.deepEqual(await hooks.aCallAll(hookName), [2, [3]]); }); - it('preserves null', async function() { + it('preserves null', async function () { testHooks.length = 0; testHooks.push(makeHook(null), makeHook([2]), makeHook(Promise.resolve(null))); assert.deepEqual(await hooks.aCallAll(hookName), [null, 2, null]); }); - it('all undefined -> []', async function() { + it('all undefined -> []', async function () { testHooks.length = 0; testHooks.push(makeHook(), makeHook(Promise.resolve())); assert.deepEqual(await hooks.aCallAll(hookName), []); diff --git a/tests/backend/specs/promises.js b/tests/backend/specs/promises.js index 415345328..02c656d45 100644 --- a/tests/backend/specs/promises.js +++ b/tests/backend/specs/promises.js @@ -1,10 +1,10 @@ -function m(mod) { return __dirname + '/../../../src/' + mod; } +function m(mod) { return `${__dirname}/../../../src/${mod}`; } const assert = require('assert').strict; const promises = require(m('node/utils/promises')); -describe(__filename, function() { - describe('promises.timesLimit', function() { +describe(__filename, function () { + describe('promises.timesLimit', function () { let wantIndex = 0; const testPromises = []; const makePromise = (index) => { @@ -25,18 +25,18 @@ describe(__filename, function() { const concurrency = 7; const timesLimitPromise = promises.timesLimit(total, concurrency, makePromise); - it('honors concurrency', async function() { + it('honors concurrency', async function () { assert.equal(wantIndex, concurrency); }); - it('creates another when one completes', async function() { + it('creates another when one completes', async function () { const {promise, resolve} = testPromises.shift(); resolve(); await promise; assert.equal(wantIndex, concurrency + 1); }); - it('creates the expected total number of promises', async function() { + it('creates the expected total number of promises', async function () { while (testPromises.length > 0) { // Resolve them in random order to ensure that the resolution order doesn't matter. const i = Math.floor(Math.random() * Math.floor(testPromises.length)); @@ -47,11 +47,11 @@ describe(__filename, function() { assert.equal(wantIndex, total); }); - it('resolves', async function() { + it('resolves', async function () { await timesLimitPromise; }); - it('does not create too many promises if total < concurrency', async function() { + it('does not create too many promises if total < concurrency', async function () { wantIndex = 0; assert.equal(testPromises.length, 0); const total = 7; @@ -66,21 +66,21 @@ describe(__filename, function() { assert.equal(wantIndex, total); }); - it('accepts total === 0, concurrency > 0', async function() { + it('accepts total === 0, concurrency > 0', async function () { wantIndex = 0; assert.equal(testPromises.length, 0); await promises.timesLimit(0, concurrency, makePromise); assert.equal(wantIndex, 0); }); - it('accepts total === 0, concurrency === 0', async function() { + it('accepts total === 0, concurrency === 0', async function () { wantIndex = 0; assert.equal(testPromises.length, 0); await promises.timesLimit(0, 0, makePromise); assert.equal(wantIndex, 0); }); - it('rejects total > 0, concurrency === 0', async function() { + it('rejects total > 0, concurrency === 0', async function () { await assert.rejects(promises.timesLimit(total, 0, makePromise), RangeError); }); }); diff --git a/tests/backend/specs/socketio.js b/tests/backend/specs/socketio.js index c1f74668d..00877faf9 100644 --- a/tests/backend/specs/socketio.js +++ b/tests/backend/specs/socketio.js @@ -1,6 +1,6 @@ /* global __dirname, __filename, afterEach, before, beforeEach, clearTimeout, describe, it, require, setTimeout */ -function m(mod) { return __dirname + '/../../../src/' + mod; } +function m(mod) { return `${__dirname}/../../../src/${mod}`; } const assert = require('assert').strict; const common = require('../common'); @@ -50,9 +50,7 @@ const getSocketEvent = async (socket, event) => { const connect = async (res) => { // Convert the `set-cookie` header(s) into a `cookie` header. const resCookies = (res == null) ? {} : setCookieParser.parse(res, {map: true}); - const reqCookieHdr = Object.entries(resCookies).map(([name, cookie]) => { - return `${name}=${encodeURIComponent(cookie.value)}`; - }).join('; '); + const reqCookieHdr = Object.entries(resCookies).map(([name, cookie]) => `${name}=${encodeURIComponent(cookie.value)}`).join('; '); logger.debug('socket.io connecting...'); const socket = io(`${common.baseUrl}/`, { @@ -91,7 +89,7 @@ const handshake = async (socket, padID) => { return msg; }; -describe(__filename, function() { +describe(__filename, function () { let agent; let authorize; const backups = {}; @@ -106,8 +104,8 @@ describe(__filename, function() { }; let socket; - before(async function() { agent = await common.init(); }); - beforeEach(async function() { + before(async function () { agent = await common.init(); }); + beforeEach(async function () { backups.hooks = {}; for (const hookName of ['preAuthorize', 'authenticate', 'authorize']) { backups.hooks[hookName] = plugins.hooks[hookName]; @@ -126,12 +124,10 @@ describe(__filename, function() { }; assert(socket == null); authorize = () => true; - plugins.hooks.authorize = [{hook_fn: (hookName, {req}, cb) => { - return cb([authorize(req)]); - }}]; + plugins.hooks.authorize = [{hook_fn: (hookName, {req}, cb) => cb([authorize(req)])}]; await cleanUpPads(); }); - afterEach(async function() { + afterEach(async function () { if (socket) socket.close(); socket = null; await cleanUpPads(); @@ -139,32 +135,32 @@ describe(__filename, function() { Object.assign(settings, backups.settings); }); - describe('Normal accesses', function() { - it('!authn anonymous cookie /p/pad -> 200, ok', async function() { + describe('Normal accesses', function () { + it('!authn anonymous cookie /p/pad -> 200, ok', async function () { const res = await agent.get('/p/pad').expect(200); socket = await connect(res); const clientVars = await handshake(socket, 'pad'); assert.equal(clientVars.type, 'CLIENT_VARS'); }); - it('!authn !cookie -> ok', async function() { + it('!authn !cookie -> ok', async function () { socket = await connect(null); const clientVars = await handshake(socket, 'pad'); assert.equal(clientVars.type, 'CLIENT_VARS'); }); - it('!authn user /p/pad -> 200, ok', async function() { + it('!authn user /p/pad -> 200, ok', async function () { const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); socket = await connect(res); const clientVars = await handshake(socket, 'pad'); assert.equal(clientVars.type, 'CLIENT_VARS'); }); - it('authn user /p/pad -> 200, ok', async function() { + it('authn user /p/pad -> 200, ok', async function () { settings.requireAuthentication = true; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); socket = await connect(res); const clientVars = await handshake(socket, 'pad'); assert.equal(clientVars.type, 'CLIENT_VARS'); }); - it('authz user /p/pad -> 200, ok', async function() { + it('authz user /p/pad -> 200, ok', async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); @@ -172,7 +168,7 @@ describe(__filename, function() { const clientVars = await handshake(socket, 'pad'); assert.equal(clientVars.type, 'CLIENT_VARS'); }); - it('supports pad names with characters that must be percent-encoded', async function() { + it('supports pad names with characters that must be percent-encoded', async function () { settings.requireAuthentication = true; // requireAuthorization is set to true here to guarantee that the user's padAuthorizations // object is populated. Technically this isn't necessary because the user's padAuthorizations @@ -187,8 +183,8 @@ describe(__filename, function() { }); }); - describe('Abnormal access attempts', function() { - it('authn anonymous /p/pad -> 401, error', async function() { + describe('Abnormal access attempts', function () { + it('authn anonymous /p/pad -> 401, error', async function () { settings.requireAuthentication = true; const res = await agent.get('/p/pad').expect(401); // Despite the 401, try to create the pad via a socket.io connection anyway. @@ -196,13 +192,13 @@ describe(__filename, function() { const message = await handshake(socket, 'pad'); assert.equal(message.accessStatus, 'deny'); }); - it('authn !cookie -> error', async function() { + it('authn !cookie -> error', async function () { settings.requireAuthentication = true; socket = await connect(null); const message = await handshake(socket, 'pad'); assert.equal(message.accessStatus, 'deny'); }); - it('authorization bypass attempt -> error', async function() { + it('authorization bypass attempt -> error', async function () { // Only allowed to access /p/pad. authorize = (req) => req.path === '/p/pad'; settings.requireAuthentication = true; @@ -216,13 +212,13 @@ describe(__filename, function() { }); }); - describe('Authorization levels via authorize hook', function() { - beforeEach(async function() { + describe('Authorization levels via authorize hook', function () { + beforeEach(async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; }); - it("level='create' -> can create", async function() { + it("level='create' -> can create", async function () { authorize = () => 'create'; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); socket = await connect(res); @@ -230,7 +226,7 @@ describe(__filename, function() { assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.data.readonly, false); }); - it('level=true -> can create', async function() { + it('level=true -> can create', async function () { authorize = () => true; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); socket = await connect(res); @@ -238,7 +234,7 @@ describe(__filename, function() { assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.data.readonly, false); }); - it("level='modify' -> can modify", async function() { + it("level='modify' -> can modify", async function () { await padManager.getPad('pad'); // Create the pad. authorize = () => 'modify'; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); @@ -247,7 +243,7 @@ describe(__filename, function() { assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.data.readonly, false); }); - it("level='create' settings.editOnly=true -> unable to create", async function() { + it("level='create' settings.editOnly=true -> unable to create", async function () { authorize = () => 'create'; settings.editOnly = true; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); @@ -255,7 +251,7 @@ describe(__filename, function() { const message = await handshake(socket, 'pad'); assert.equal(message.accessStatus, 'deny'); }); - it("level='modify' settings.editOnly=false -> unable to create", async function() { + it("level='modify' settings.editOnly=false -> unable to create", async function () { authorize = () => 'modify'; settings.editOnly = false; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); @@ -263,14 +259,14 @@ describe(__filename, function() { const message = await handshake(socket, 'pad'); assert.equal(message.accessStatus, 'deny'); }); - it("level='readOnly' -> unable to create", async function() { + it("level='readOnly' -> unable to create", async function () { authorize = () => 'readOnly'; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); socket = await connect(res); const message = await handshake(socket, 'pad'); assert.equal(message.accessStatus, 'deny'); }); - it("level='readOnly' -> unable to modify", async function() { + it("level='readOnly' -> unable to modify", async function () { await padManager.getPad('pad'); // Create the pad. authorize = () => 'readOnly'; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); @@ -281,12 +277,12 @@ describe(__filename, function() { }); }); - describe('Authorization levels via user settings', function() { - beforeEach(async function() { + describe('Authorization levels via user settings', function () { + beforeEach(async function () { settings.requireAuthentication = true; }); - it('user.canCreate = true -> can create and modify', async function() { + it('user.canCreate = true -> can create and modify', async function () { settings.users.user.canCreate = true; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); socket = await connect(res); @@ -294,21 +290,21 @@ describe(__filename, function() { assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.data.readonly, false); }); - it('user.canCreate = false -> unable to create', async function() { + it('user.canCreate = false -> unable to create', async function () { settings.users.user.canCreate = false; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); socket = await connect(res); const message = await handshake(socket, 'pad'); assert.equal(message.accessStatus, 'deny'); }); - it('user.readOnly = true -> unable to create', async function() { + it('user.readOnly = true -> unable to create', async function () { settings.users.user.readOnly = true; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); socket = await connect(res); const message = await handshake(socket, 'pad'); assert.equal(message.accessStatus, 'deny'); }); - it('user.readOnly = true -> unable to modify', async function() { + it('user.readOnly = true -> unable to modify', async function () { await padManager.getPad('pad'); // Create the pad. settings.users.user.readOnly = true; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); @@ -317,7 +313,7 @@ describe(__filename, function() { assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.data.readonly, true); }); - it('user.readOnly = false -> can create and modify', async function() { + it('user.readOnly = false -> can create and modify', async function () { settings.users.user.readOnly = false; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); socket = await connect(res); @@ -325,7 +321,7 @@ describe(__filename, function() { assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.data.readonly, false); }); - it('user.readOnly = true, user.canCreate = true -> unable to create', async function() { + it('user.readOnly = true, user.canCreate = true -> unable to create', async function () { settings.users.user.canCreate = true; settings.users.user.readOnly = true; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); @@ -335,13 +331,13 @@ describe(__filename, function() { }); }); - describe('Authorization level interaction between authorize hook and user settings', function() { - beforeEach(async function() { + describe('Authorization level interaction between authorize hook and user settings', function () { + beforeEach(async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; }); - it('authorize hook does not elevate level from user settings', async function() { + it('authorize hook does not elevate level from user settings', async function () { settings.users.user.readOnly = true; authorize = () => 'create'; const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); @@ -349,7 +345,7 @@ describe(__filename, function() { const message = await handshake(socket, 'pad'); assert.equal(message.accessStatus, 'deny'); }); - it('user settings does not elevate level from authorize hook', async function() { + it('user settings does not elevate level from authorize hook', async function () { settings.users.user.readOnly = false; settings.users.user.canCreate = true; authorize = () => 'readOnly'; diff --git a/tests/backend/specs/specialpages.js b/tests/backend/specs/specialpages.js index 89f23bd9b..3e385f6e9 100644 --- a/tests/backend/specs/specialpages.js +++ b/tests/backend/specs/specialpages.js @@ -1,11 +1,11 @@ const common = require('../common'); const settings = require('ep_etherpad-lite/node/utils/Settings'); -describe(__filename, function() { +describe(__filename, function () { let agent; const backups = {}; - before(async function() { agent = await common.init(); }); - beforeEach(async function() { + before(async function () { agent = await common.init(); }); + beforeEach(async function () { backups.settings = {}; for (const setting of ['requireAuthentication', 'requireAuthorization']) { backups.settings[setting] = settings[setting]; @@ -13,12 +13,12 @@ describe(__filename, function() { settings.requireAuthentication = false; settings.requireAuthorization = false; }); - afterEach(async function() { + afterEach(async function () { Object.assign(settings, backups.settings); }); - describe('/javascript', function() { - it('/javascript -> 200', async function() { + describe('/javascript', function () { + it('/javascript -> 200', async function () { await agent.get('/javascript').expect(200); }); }); diff --git a/tests/backend/specs/webaccess.js b/tests/backend/specs/webaccess.js index 4d0793d65..a21cc73a8 100644 --- a/tests/backend/specs/webaccess.js +++ b/tests/backend/specs/webaccess.js @@ -1,19 +1,19 @@ /* global __dirname, __filename, Buffer, afterEach, before, beforeEach, describe, it, require */ -function m(mod) { return __dirname + '/../../../src/' + mod; } +function m(mod) { return `${__dirname}/../../../src/${mod}`; } const assert = require('assert').strict; const common = require('../common'); const plugins = require(m('static/js/pluginfw/plugin_defs')); const settings = require(m('node/utils/Settings')); -describe(__filename, function() { +describe(__filename, function () { let agent; const backups = {}; const authHookNames = ['preAuthorize', 'authenticate', 'authorize']; const failHookNames = ['preAuthzFailure', 'authnFailure', 'authzFailure', 'authFailure']; - before(async function() { agent = await common.init(); }); - beforeEach(async function() { + before(async function () { agent = await common.init(); }); + beforeEach(async function () { backups.hooks = {}; for (const hookName of authHookNames.concat(failHookNames)) { backups.hooks[hookName] = plugins.hooks[hookName]; @@ -30,76 +30,76 @@ describe(__filename, function() { user: {password: 'user-password'}, }; }); - afterEach(async function() { + afterEach(async function () { Object.assign(plugins.hooks, backups.hooks); Object.assign(settings, backups.settings); }); - describe('webaccess: without plugins', function() { - it('!authn !authz anonymous / -> 200', async function() { + describe('webaccess: without plugins', function () { + it('!authn !authz anonymous / -> 200', async function () { settings.requireAuthentication = false; settings.requireAuthorization = false; await agent.get('/').expect(200); }); - it('!authn !authz anonymous /admin/ -> 401', async function() { + it('!authn !authz anonymous /admin/ -> 401', async function () { settings.requireAuthentication = false; settings.requireAuthorization = false; await agent.get('/admin/').expect(401); }); - it('authn !authz anonymous / -> 401', async function() { + it('authn !authz anonymous / -> 401', async function () { settings.requireAuthentication = true; settings.requireAuthorization = false; await agent.get('/').expect(401); }); - it('authn !authz user / -> 200', async function() { + it('authn !authz user / -> 200', async function () { settings.requireAuthentication = true; settings.requireAuthorization = false; await agent.get('/').auth('user', 'user-password').expect(200); }); - it('authn !authz user /admin/ -> 403', async function() { + it('authn !authz user /admin/ -> 403', async function () { settings.requireAuthentication = true; settings.requireAuthorization = false; await agent.get('/admin/').auth('user', 'user-password').expect(403); }); - it('authn !authz admin / -> 200', async function() { + it('authn !authz admin / -> 200', async function () { settings.requireAuthentication = true; settings.requireAuthorization = false; await agent.get('/').auth('admin', 'admin-password').expect(200); }); - it('authn !authz admin /admin/ -> 200', async function() { + it('authn !authz admin /admin/ -> 200', async function () { settings.requireAuthentication = true; settings.requireAuthorization = false; await agent.get('/admin/').auth('admin', 'admin-password').expect(200); }); - it('authn authz user / -> 403', async function() { + it('authn authz user / -> 403', async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; await agent.get('/').auth('user', 'user-password').expect(403); }); - it('authn authz user /admin/ -> 403', async function() { + it('authn authz user /admin/ -> 403', async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; await agent.get('/admin/').auth('user', 'user-password').expect(403); }); - it('authn authz admin / -> 200', async function() { + it('authn authz admin / -> 200', async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; await agent.get('/').auth('admin', 'admin-password').expect(200); }); - it('authn authz admin /admin/ -> 200', async function() { + it('authn authz admin /admin/ -> 200', async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; await agent.get('/admin/').auth('admin', 'admin-password').expect(200); }); - describe('login fails if password is nullish', function() { + describe('login fails if password is nullish', function () { for (const adminPassword of [undefined, null]) { // https://tools.ietf.org/html/rfc7617 says that the username and password are sent as // base64(username + ':' + password), but there's nothing stopping a malicious user from // sending just base64(username) (no colon). The lack of colon could throw off credential // parsing, resulting in successful comparisons against a null or undefined password. for (const creds of ['admin', 'admin:']) { - it(`admin password: ${adminPassword} credentials: ${creds}`, async function() { + it(`admin password: ${adminPassword} credentials: ${creds}`, async function () { settings.users.admin.password = adminPassword; const encCreds = Buffer.from(creds).toString('base64'); await agent.get('/admin/').set('Authorization', `Basic ${encCreds}`).expect(401); @@ -109,7 +109,7 @@ describe(__filename, function() { }); }); - describe('webaccess: preAuthorize, authenticate, and authorize hooks', function() { + describe('webaccess: preAuthorize, authenticate, and authorize hooks', function () { let callOrder; const Handler = class { constructor(hookName, suffix) { @@ -134,7 +134,7 @@ describe(__filename, function() { }; const handlers = {}; - beforeEach(async function() { + beforeEach(async function () { callOrder = []; for (const hookName of authHookNames) { // Create two handlers for each hook to test deferral to the next function. @@ -145,38 +145,38 @@ describe(__filename, function() { } }); - describe('preAuthorize', function() { - beforeEach(async function() { + describe('preAuthorize', function () { + beforeEach(async function () { settings.requireAuthentication = false; settings.requireAuthorization = false; }); - it('defers if it returns []', async function() { + it('defers if it returns []', async function () { await agent.get('/').expect(200); // Note: The preAuthorize hook always runs even if requireAuthorization is false. assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']); }); - it('bypasses authenticate and authorize hooks when true is returned', async function() { + it('bypasses authenticate and authorize hooks when true is returned', async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; handlers.preAuthorize[0].innerHandle = () => [true]; await agent.get('/').expect(200); assert.deepEqual(callOrder, ['preAuthorize_0']); }); - it('bypasses authenticate and authorize hooks when false is returned', async function() { + it('bypasses authenticate and authorize hooks when false is returned', async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; handlers.preAuthorize[0].innerHandle = () => [false]; await agent.get('/').expect(403); assert.deepEqual(callOrder, ['preAuthorize_0']); }); - it('bypasses authenticate and authorize hooks for static content, defers', async function() { + it('bypasses authenticate and authorize hooks for static content, defers', async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; await agent.get('/static/robots.txt').expect(200); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']); }); - it('cannot grant access to /admin', async function() { + it('cannot grant access to /admin', async function () { handlers.preAuthorize[0].innerHandle = () => [true]; await agent.get('/admin/').expect(401); // Notes: @@ -184,15 +184,17 @@ describe(__filename, function() { // 'true' entries are ignored for /admin/* requests. // * The authenticate hook always runs for /admin/* requests even if // settings.requireAuthentication is false. - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1']); }); - it('can deny access to /admin', async function() { + it('can deny access to /admin', async function () { handlers.preAuthorize[0].innerHandle = () => [false]; await agent.get('/admin/').auth('admin', 'admin-password').expect(403); assert.deepEqual(callOrder, ['preAuthorize_0']); }); - it('runs preAuthzFailure hook when access is denied', async function() { + it('runs preAuthzFailure hook when access is denied', async function () { handlers.preAuthorize[0].innerHandle = () => [false]; let called = false; plugins.hooks.preAuthzFailure = [{hook_fn: (hookName, {req, res}, cb) => { @@ -207,149 +209,177 @@ describe(__filename, function() { await agent.get('/admin/').auth('admin', 'admin-password').expect(200, 'injected'); assert(called); }); - it('returns 500 if an exception is thrown', async function() { + it('returns 500 if an exception is thrown', async function () { handlers.preAuthorize[0].innerHandle = () => { throw new Error('exception test'); }; await agent.get('/').expect(500); }); }); - describe('authenticate', function() { - beforeEach(async function() { + describe('authenticate', function () { + beforeEach(async function () { settings.requireAuthentication = true; settings.requireAuthorization = false; }); - it('is not called if !requireAuthentication and not /admin/*', async function() { + it('is not called if !requireAuthentication and not /admin/*', async function () { settings.requireAuthentication = false; await agent.get('/').expect(200); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']); }); - it('is called if !requireAuthentication and /admin/*', async function() { + it('is called if !requireAuthentication and /admin/*', async function () { settings.requireAuthentication = false; await agent.get('/admin/').expect(401); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1']); }); - it('defers if empty list returned', async function() { + it('defers if empty list returned', async function () { await agent.get('/').expect(401); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1']); }); - it('does not defer if return [true], 200', async function() { + it('does not defer if return [true], 200', async function () { handlers.authenticate[0].innerHandle = (req) => { req.session.user = {}; return [true]; }; await agent.get('/').expect(200); // Note: authenticate_1 was not called because authenticate_0 handled it. assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']); }); - it('does not defer if return [false], 401', async function() { + it('does not defer if return [false], 401', async function () { handlers.authenticate[0].innerHandle = (req) => [false]; await agent.get('/').expect(401); // Note: authenticate_1 was not called because authenticate_0 handled it. assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']); }); - it('falls back to HTTP basic auth', async function() { + it('falls back to HTTP basic auth', async function () { await agent.get('/').auth('user', 'user-password').expect(200); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1']); }); - it('passes settings.users in context', async function() { + it('passes settings.users in context', async function () { handlers.authenticate[0].checkContext = ({users}) => { assert.equal(users, settings.users); }; await agent.get('/').expect(401); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1']); }); - it('passes user, password in context if provided', async function() { + it('passes user, password in context if provided', async function () { handlers.authenticate[0].checkContext = ({username, password}) => { assert.equal(username, 'user'); assert.equal(password, 'user-password'); }; await agent.get('/').auth('user', 'user-password').expect(200); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1']); }); - it('does not pass user, password in context if not provided', async function() { + it('does not pass user, password in context if not provided', async function () { handlers.authenticate[0].checkContext = ({username, password}) => { assert(username == null); assert(password == null); }; await agent.get('/').expect(401); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1']); }); - it('errors if req.session.user is not created', async function() { + it('errors if req.session.user is not created', async function () { handlers.authenticate[0].innerHandle = () => [true]; await agent.get('/').expect(500); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']); }); - it('returns 500 if an exception is thrown', async function() { + it('returns 500 if an exception is thrown', async function () { handlers.authenticate[0].innerHandle = () => { throw new Error('exception test'); }; await agent.get('/').expect(500); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']); }); }); - describe('authorize', function() { - beforeEach(async function() { + describe('authorize', function () { + beforeEach(async function () { settings.requireAuthentication = true; settings.requireAuthorization = true; }); - it('is not called if !requireAuthorization (non-/admin)', async function() { + it('is not called if !requireAuthorization (non-/admin)', async function () { settings.requireAuthorization = false; await agent.get('/').auth('user', 'user-password').expect(200); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1']); }); - it('is not called if !requireAuthorization (/admin)', async function() { + it('is not called if !requireAuthorization (/admin)', async function () { settings.requireAuthorization = false; await agent.get('/admin/').auth('admin', 'admin-password').expect(200); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1']); }); - it('defers if empty list returned', async function() { + it('defers if empty list returned', async function () { await agent.get('/').auth('user', 'user-password').expect(403); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1', - 'authorize_0', 'authorize_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1', + 'authorize_0', + 'authorize_1']); }); - it('does not defer if return [true], 200', async function() { + it('does not defer if return [true], 200', async function () { handlers.authorize[0].innerHandle = () => [true]; await agent.get('/').auth('user', 'user-password').expect(200); // Note: authorize_1 was not called because authorize_0 handled it. - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1', - 'authorize_0']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1', + 'authorize_0']); }); - it('does not defer if return [false], 403', async function() { + it('does not defer if return [false], 403', async function () { handlers.authorize[0].innerHandle = (req) => [false]; await agent.get('/').auth('user', 'user-password').expect(403); // Note: authorize_1 was not called because authorize_0 handled it. - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1', - 'authorize_0']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1', + 'authorize_0']); }); - it('passes req.path in context', async function() { + it('passes req.path in context', async function () { handlers.authorize[0].checkContext = ({resource}) => { assert.equal(resource, '/'); }; await agent.get('/').auth('user', 'user-password').expect(403); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1', - 'authorize_0', 'authorize_1']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1', + 'authorize_0', + 'authorize_1']); }); - it('returns 500 if an exception is thrown', async function() { + it('returns 500 if an exception is thrown', async function () { handlers.authorize[0].innerHandle = () => { throw new Error('exception test'); }; await agent.get('/').auth('user', 'user-password').expect(500); - assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', - 'authenticate_0', 'authenticate_1', - 'authorize_0']); + assert.deepEqual(callOrder, ['preAuthorize_0', + 'preAuthorize_1', + 'authenticate_0', + 'authenticate_1', + 'authorize_0']); }); }); }); - describe('webaccess: authnFailure, authzFailure, authFailure hooks', function() { + describe('webaccess: authnFailure, authzFailure, authFailure hooks', function () { const Handler = class { constructor(hookName) { this.hookName = hookName; @@ -372,7 +402,7 @@ describe(__filename, function() { }; const handlers = {}; - beforeEach(function() { + beforeEach(function () { failHookNames.forEach((hookName) => { const handler = new Handler(hookName); handlers[hookName] = handler; @@ -383,61 +413,61 @@ describe(__filename, function() { }); // authn failure tests - it('authn fail, no hooks handle -> 401', async function() { + it('authn fail, no hooks handle -> 401', async function () { await agent.get('/').expect(401); - assert(handlers['authnFailure'].called); - assert(!handlers['authzFailure'].called); - assert(handlers['authFailure'].called); + assert(handlers.authnFailure.called); + assert(!handlers.authzFailure.called); + assert(handlers.authFailure.called); }); - it('authn fail, authnFailure handles', async function() { - handlers['authnFailure'].shouldHandle = true; + it('authn fail, authnFailure handles', async function () { + handlers.authnFailure.shouldHandle = true; await agent.get('/').expect(200, 'authnFailure'); - assert(handlers['authnFailure'].called); - assert(!handlers['authzFailure'].called); - assert(!handlers['authFailure'].called); + assert(handlers.authnFailure.called); + assert(!handlers.authzFailure.called); + assert(!handlers.authFailure.called); }); - it('authn fail, authFailure handles', async function() { - handlers['authFailure'].shouldHandle = true; + it('authn fail, authFailure handles', async function () { + handlers.authFailure.shouldHandle = true; await agent.get('/').expect(200, 'authFailure'); - assert(handlers['authnFailure'].called); - assert(!handlers['authzFailure'].called); - assert(handlers['authFailure'].called); + assert(handlers.authnFailure.called); + assert(!handlers.authzFailure.called); + assert(handlers.authFailure.called); }); - it('authnFailure trumps authFailure', async function() { - handlers['authnFailure'].shouldHandle = true; - handlers['authFailure'].shouldHandle = true; + it('authnFailure trumps authFailure', async function () { + handlers.authnFailure.shouldHandle = true; + handlers.authFailure.shouldHandle = true; await agent.get('/').expect(200, 'authnFailure'); - assert(handlers['authnFailure'].called); - assert(!handlers['authFailure'].called); + assert(handlers.authnFailure.called); + assert(!handlers.authFailure.called); }); // authz failure tests - it('authz fail, no hooks handle -> 403', async function() { + it('authz fail, no hooks handle -> 403', async function () { await agent.get('/').auth('user', 'user-password').expect(403); - assert(!handlers['authnFailure'].called); - assert(handlers['authzFailure'].called); - assert(handlers['authFailure'].called); + assert(!handlers.authnFailure.called); + assert(handlers.authzFailure.called); + assert(handlers.authFailure.called); }); - it('authz fail, authzFailure handles', async function() { - handlers['authzFailure'].shouldHandle = true; + it('authz fail, authzFailure handles', async function () { + handlers.authzFailure.shouldHandle = true; await agent.get('/').auth('user', 'user-password').expect(200, 'authzFailure'); - assert(!handlers['authnFailure'].called); - assert(handlers['authzFailure'].called); - assert(!handlers['authFailure'].called); + assert(!handlers.authnFailure.called); + assert(handlers.authzFailure.called); + assert(!handlers.authFailure.called); }); - it('authz fail, authFailure handles', async function() { - handlers['authFailure'].shouldHandle = true; + it('authz fail, authFailure handles', async function () { + handlers.authFailure.shouldHandle = true; await agent.get('/').auth('user', 'user-password').expect(200, 'authFailure'); - assert(!handlers['authnFailure'].called); - assert(handlers['authzFailure'].called); - assert(handlers['authFailure'].called); + assert(!handlers.authnFailure.called); + assert(handlers.authzFailure.called); + assert(handlers.authFailure.called); }); - it('authzFailure trumps authFailure', async function() { - handlers['authzFailure'].shouldHandle = true; - handlers['authFailure'].shouldHandle = true; + it('authzFailure trumps authFailure', async function () { + handlers.authzFailure.shouldHandle = true; + handlers.authFailure.shouldHandle = true; await agent.get('/').auth('user', 'user-password').expect(200, 'authzFailure'); - assert(handlers['authzFailure'].called); - assert(!handlers['authFailure'].called); + assert(handlers.authzFailure.called); + assert(!handlers.authFailure.called); }); }); }); diff --git a/tests/container/loadSettings.js b/tests/container/loadSettings.js index 4a1c46021..7317f8022 100644 --- a/tests/container/loadSettings.js +++ b/tests/container/loadSettings.js @@ -12,16 +12,16 @@ * back to a default) */ -var jsonminify = require(__dirname+"/../../src/node_modules/jsonminify"); +const jsonminify = require(`${__dirname}/../../src/node_modules/jsonminify`); const fs = require('fs'); -function loadSettings(){ - var settingsStr = fs.readFileSync(__dirname+"/../../settings.json.docker").toString(); +function loadSettings() { + let settingsStr = fs.readFileSync(`${__dirname}/../../settings.json.docker`).toString(); // try to parse the settings try { - if(settingsStr) { - settingsStr = jsonminify(settingsStr).replace(",]","]").replace(",}","}"); - var settings = JSON.parse(settingsStr); + if (settingsStr) { + settingsStr = jsonminify(settingsStr).replace(',]', ']').replace(',}', '}'); + const settings = JSON.parse(settingsStr); // custom settings for running in a container settings.ip = 'localhost'; @@ -29,8 +29,8 @@ function loadSettings(){ return settings; } - }catch(e){ - console.error("whoops something is bad with settings"); + } catch (e) { + console.error('whoops something is bad with settings'); } } diff --git a/tests/container/specs/api/pad.js b/tests/container/specs/api/pad.js index f50b79864..6aeb86708 100644 --- a/tests/container/specs/api/pad.js +++ b/tests/container/specs/api/pad.js @@ -5,34 +5,34 @@ * TODO: unify those two files, and merge in a single one. */ -const supertest = require(__dirname+'/../../../../src/node_modules/supertest'); -const settings = require(__dirname+'/../../loadSettings').loadSettings(); -const api = supertest('http://'+settings.ip+":"+settings.port); +const supertest = require(`${__dirname}/../../../../src/node_modules/supertest`); +const settings = require(`${__dirname}/../../loadSettings`).loadSettings(); +const api = supertest(`http://${settings.ip}:${settings.port}`); -var apiVersion = 1; +const apiVersion = 1; -describe('Connectivity', function(){ - it('can connect', function(done) { +describe('Connectivity', function () { + it('can connect', function (done) { api.get('/api/') - .expect('Content-Type', /json/) - .expect(200, done) + .expect('Content-Type', /json/) + .expect(200, done); }); -}) +}); -describe('API Versioning', function(){ - it('finds the version tag', function(done) { +describe('API Versioning', function () { + it('finds the version tag', function (done) { api.get('/api/') - .expect(function(res){ - if (!res.body.currentVersion) throw new Error("No version set in API"); - return; - }) - .expect(200, done) + .expect((res) => { + if (!res.body.currentVersion) throw new Error('No version set in API'); + return; + }) + .expect(200, done); }); -}) +}); -describe('Permission', function(){ - it('errors with invalid APIKey', function(done) { - api.get('/api/'+apiVersion+'/createPad?apikey=wrong_password&padID=test') - .expect(401, done) +describe('Permission', function () { + it('errors with invalid APIKey', function (done) { + api.get(`/api/${apiVersion}/createPad?apikey=wrong_password&padID=test`) + .expect(401, done); }); -}) +}); diff --git a/tests/frontend/helper.js b/tests/frontend/helper.js index 3445ca0e5..b49d32eb8 100644 --- a/tests/frontend/helper.js +++ b/tests/frontend/helper.js @@ -1,65 +1,65 @@ var helper = {}; -(function(){ - var $iframe, jsLibraries = {}; +(function () { + let $iframe; const + jsLibraries = {}; - helper.init = function(cb){ - $.get('/static/js/jquery.js').done(function(code){ + helper.init = function (cb) { + $.get('/static/js/jquery.js').done((code) => { // make sure we don't override existing jquery - jsLibraries["jquery"] = "if(typeof $ === 'undefined') {\n" + code + "\n}"; + jsLibraries.jquery = `if(typeof $ === 'undefined') {\n${code}\n}`; - $.get('/tests/frontend/lib/sendkeys.js').done(function(code){ - jsLibraries["sendkeys"] = code; + $.get('/tests/frontend/lib/sendkeys.js').done((code) => { + jsLibraries.sendkeys = code; cb(); }); }); - } + }; helper.randomString = function randomString(len) { - var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - var randomstring = ''; - for (var i = 0; i < len; i++) - { - var rnum = Math.floor(Math.random() * chars.length); + const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + let randomstring = ''; + for (let i = 0; i < len; i++) { + const rnum = Math.floor(Math.random() * chars.length); randomstring += chars.substring(rnum, rnum + 1); } return randomstring; - } + }; - var getFrameJQuery = function($iframe){ + const getFrameJQuery = function ($iframe) { /* I tried over 9000 ways to inject javascript into iframes. This is the only way I found that worked in IE 7+8+9, FF and Chrome */ - var win = $iframe[0].contentWindow; - var doc = win.document; + const win = $iframe[0].contentWindow; + const doc = win.document; - //IE 8+9 Hack to make eval appear - //http://stackoverflow.com/questions/2720444/why-does-this-window-object-not-have-the-eval-function - win.execScript && win.execScript("null"); + // IE 8+9 Hack to make eval appear + // http://stackoverflow.com/questions/2720444/why-does-this-window-object-not-have-the-eval-function + win.execScript && win.execScript('null'); - win.eval(jsLibraries["jquery"]); - win.eval(jsLibraries["sendkeys"]); + win.eval(jsLibraries.jquery); + win.eval(jsLibraries.sendkeys); win.$.window = win; win.$.document = doc; return win.$; - } + }; - helper.clearSessionCookies = function(){ + helper.clearSessionCookies = function () { // Expire cookies, so author and language are changed after reloading the pad. // See https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#Example_4_Reset_the_previous_cookie window.document.cookie = 'token=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'; window.document.cookie = 'language=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'; - } + }; // Can only happen when the iframe exists, so we're doing it separately from other cookies - helper.clearPadPrefCookie = function(){ + helper.clearPadPrefCookie = function () { helper.padChrome$.document.cookie = 'prefsHttp=;expires=Thu, 01 Jan 1970 00:00:00 GMT'; - } + }; // Overwrite all prefs in pad cookie. Assumes http, not https. // @@ -67,65 +67,64 @@ var helper = {}; // seem to have independent cookies, UNLESS we put path=/ here (which we don't). // I don't fully understand it, but this function seems to properly simulate // padCookie.setPref in the client code - helper.setPadPrefCookie = function(prefs){ - helper.padChrome$.document.cookie = ("prefsHttp=" + escape(JSON.stringify(prefs)) + ";expires=Thu, 01 Jan 3000 00:00:00 GMT"); - } + helper.setPadPrefCookie = function (prefs) { + helper.padChrome$.document.cookie = (`prefsHttp=${escape(JSON.stringify(prefs))};expires=Thu, 01 Jan 3000 00:00:00 GMT`); + }; // Functionality for knowing what key event type is required for tests - var evtType = "keydown"; + let evtType = 'keydown'; // if it's IE require keypress - if(window.navigator.userAgent.indexOf("MSIE") > -1){ - evtType = "keypress"; + if (window.navigator.userAgent.indexOf('MSIE') > -1) { + evtType = 'keypress'; } // Edge also requires keypress. - if(window.navigator.userAgent.indexOf("Edge") > -1){ - evtType = "keypress"; + if (window.navigator.userAgent.indexOf('Edge') > -1) { + evtType = 'keypress'; } // Opera also requires keypress. - if(window.navigator.userAgent.indexOf("OPR") > -1){ - evtType = "keypress"; + if (window.navigator.userAgent.indexOf('OPR') > -1) { + evtType = 'keypress'; } helper.evtType = evtType; // @todo needs fixing asap // newPad occasionally timeouts, might be a problem with ready/onload code during page setup // This ensures that tests run regardless of this problem - helper.retry = 0 + helper.retry = 0; - helper.newPad = function(cb, padName){ - //build opts object - var opts = {clearCookies: true} - if(typeof cb === 'function'){ - opts.cb = cb + helper.newPad = function (cb, padName) { + // build opts object + let opts = {clearCookies: true}; + if (typeof cb === 'function') { + opts.cb = cb; } else { opts = _.defaults(cb, opts); } // if opts.params is set we manipulate the URL to include URL parameters IE ?foo=Bah. - if(opts.params){ - var encodedParams = "?" + $.param(opts.params); + if (opts.params) { + var encodedParams = `?${$.param(opts.params)}`; } - //clear cookies - if(opts.clearCookies){ + // clear cookies + if (opts.clearCookies) { helper.clearSessionCookies(); } - if(!padName) - padName = "FRONTEND_TEST_" + helper.randomString(20); - $iframe = $(""); + if (!padName) padName = `FRONTEND_TEST_${helper.randomString(20)}`; + $iframe = $(``); // needed for retry - let origPadName = padName; + const origPadName = padName; - //clean up inner iframe references + // clean up inner iframe references helper.padChrome$ = helper.padOuter$ = helper.padInner$ = null; - //remove old iframe - $("#iframe-container iframe").remove(); - //set new iframe - $("#iframe-container").append($iframe); - $iframe.one('load', function(){ + // remove old iframe + $('#iframe-container iframe').remove(); + // set new iframe + $('#iframe-container').append($iframe); + $iframe.one('load', () => { helper.padChrome$ = getFrameJQuery($('#iframe-container iframe')); if (opts.clearCookies) { helper.clearPadPrefCookie(); @@ -133,13 +132,11 @@ var helper = {}; if (opts.padPrefs) { helper.setPadPrefCookie(opts.padPrefs); } - helper.waitFor(function(){ - return !$iframe.contents().find("#editorloadingbox").is(":visible"); - }, 10000).done(function(){ - helper.padOuter$ = getFrameJQuery(helper.padChrome$('iframe[name="ace_outer"]')); - helper.padInner$ = getFrameJQuery( helper.padOuter$('iframe[name="ace_inner"]')); + helper.waitFor(() => !$iframe.contents().find('#editorloadingbox').is(':visible'), 10000).done(() => { + helper.padOuter$ = getFrameJQuery(helper.padChrome$('iframe[name="ace_outer"]')); + helper.padInner$ = getFrameJQuery(helper.padOuter$('iframe[name="ace_inner"]')); - //disable all animations, this makes tests faster and easier + // disable all animations, this makes tests faster and easier helper.padChrome$.fx.off = true; helper.padOuter$.fx.off = true; helper.padInner$.fx.off = true; @@ -149,13 +146,13 @@ var helper = {}; * @type {Array} */ helper.chatMessages = []; - + /* * changeset commits from the server * @type {Array} */ helper.commits = []; - + /* * userInfo messages from the server * @type {Array} @@ -165,23 +162,23 @@ var helper = {}; // listen for server messages helper.spyOnSocketIO(); opts.cb(); - }).fail(function(){ + }).fail(() => { if (helper.retry > 3) { - throw new Error("Pad never loaded"); + throw new Error('Pad never loaded'); } helper.retry++; - helper.newPad(cb,origPadName); + helper.newPad(cb, origPadName); }); }); return padName; - } + }; - helper.waitFor = function(conditionFunc, timeoutTime = 1900, intervalTime = 10) { - var deferred = $.Deferred(); + helper.waitFor = function (conditionFunc, timeoutTime = 1900, intervalTime = 10) { + const deferred = $.Deferred(); const _fail = deferred.fail.bind(deferred); - var listenForFail = false; + let listenForFail = false; deferred.fail = (...args) => { listenForFail = true; return _fail(...args); @@ -202,10 +199,10 @@ var helper = {}; const timeout = setTimeout(() => { clearInterval(intervalCheck); - var error = new Error("wait for condition never became true " + conditionFunc.toString()); + const error = new Error(`wait for condition never became true ${conditionFunc.toString()}`); deferred.reject(error); - if(!listenForFail){ + if (!listenForFail) { throw error; } }, timeoutTime); @@ -222,56 +219,56 @@ var helper = {}; * @returns {Promise} * */ - helper.waitForPromise = async function(...args) { + helper.waitForPromise = async function (...args) { // Note: waitFor() has a strange API: On timeout it rejects, but it also throws an uncatchable // exception unless .fail() has been called. That uncatchable exception is disabled here by // passing a no-op function to .fail(). return await this.waitFor(...args).fail(() => {}); }; - helper.selectLines = function($startLine, $endLine, startOffset, endOffset){ + helper.selectLines = function ($startLine, $endLine, startOffset, endOffset) { // if no offset is provided, use beginning of start line and end of end line startOffset = startOffset || 0; - endOffset = endOffset === undefined ? $endLine.text().length : endOffset; + endOffset = endOffset === undefined ? $endLine.text().length : endOffset; - var inner$ = helper.padInner$; - var selection = inner$.document.getSelection(); - var range = selection.getRangeAt(0); + const inner$ = helper.padInner$; + const selection = inner$.document.getSelection(); + const range = selection.getRangeAt(0); - var start = getTextNodeAndOffsetOf($startLine, startOffset); - var end = getTextNodeAndOffsetOf($endLine, endOffset); + const start = getTextNodeAndOffsetOf($startLine, startOffset); + const end = getTextNodeAndOffsetOf($endLine, endOffset); range.setStart(start.node, start.offset); range.setEnd(end.node, end.offset); selection.removeAllRanges(); selection.addRange(range); - } + }; - var getTextNodeAndOffsetOf = function($targetLine, targetOffsetAtLine){ - var $textNodes = $targetLine.find('*').contents().filter(function(){ + var getTextNodeAndOffsetOf = function ($targetLine, targetOffsetAtLine) { + const $textNodes = $targetLine.find('*').contents().filter(function () { return this.nodeType === Node.TEXT_NODE; }); // search node where targetOffsetAtLine is reached, and its 'inner offset' - var textNodeWhereOffsetIs = null; - var offsetBeforeTextNode = 0; - var offsetInsideTextNode = 0; - $textNodes.each(function(index, element){ - var elementTotalOffset = element.textContent.length; + let textNodeWhereOffsetIs = null; + let offsetBeforeTextNode = 0; + let offsetInsideTextNode = 0; + $textNodes.each((index, element) => { + const elementTotalOffset = element.textContent.length; textNodeWhereOffsetIs = element; offsetInsideTextNode = targetOffsetAtLine - offsetBeforeTextNode; - var foundTextNode = offsetBeforeTextNode + elementTotalOffset >= targetOffsetAtLine; - if (foundTextNode){ - return false; //stop .each by returning false + const foundTextNode = offsetBeforeTextNode + elementTotalOffset >= targetOffsetAtLine; + if (foundTextNode) { + return false; // stop .each by returning false } offsetBeforeTextNode += elementTotalOffset; }); // edge cases - if (textNodeWhereOffsetIs === null){ + if (textNodeWhereOffsetIs === null) { // there was no text node inside $targetLine, so it is an empty line (
        ). // Use beginning of line textNodeWhereOffsetIs = $targetLine.get(0); @@ -279,16 +276,16 @@ var helper = {}; } // avoid errors if provided targetOffsetAtLine is higher than line offset (maxOffset). // Use max allowed instead - var maxOffset = textNodeWhereOffsetIs.textContent.length; + const maxOffset = textNodeWhereOffsetIs.textContent.length; offsetInsideTextNode = Math.min(offsetInsideTextNode, maxOffset); return { node: textNodeWhereOffsetIs, offset: offsetInsideTextNode, }; - } + }; /* Ensure console.log doesn't blow up in IE, ugly but ok for a test framework imho*/ window.console = window.console || {}; - window.console.log = window.console.log || function(){} -})() + window.console.log = window.console.log || function () {}; +})(); diff --git a/tests/frontend/helper/methods.js b/tests/frontend/helper/methods.js index c803a86cd..191202c65 100644 --- a/tests/frontend/helper/methods.js +++ b/tests/frontend/helper/methods.js @@ -2,22 +2,19 @@ * Spys on socket.io messages and saves them into several arrays * that are visible in tests */ -helper.spyOnSocketIO = function (){ - helper.contentWindow().pad.socket.on('message', function(msg){ - if (msg.type == "COLLABROOM") { - +helper.spyOnSocketIO = function () { + helper.contentWindow().pad.socket.on('message', (msg) => { + if (msg.type == 'COLLABROOM') { if (msg.data.type == 'ACCEPT_COMMIT') { helper.commits.push(msg); - } - else if (msg.data.type == 'USER_NEWINFO') { - helper.userInfos.push(msg) - } - else if (msg.data.type == 'CHAT_MESSAGE') { - helper.chatMessages.push(msg) + } else if (msg.data.type == 'USER_NEWINFO') { + helper.userInfos.push(msg); + } else if (msg.data.type == 'CHAT_MESSAGE') { + helper.chatMessages.push(msg); } } - }) -} + }); +}; /** * Makes an edit via `sendkeys` to the position of the caret and ensures ACCEPT_COMMIT @@ -31,14 +28,12 @@ helper.spyOnSocketIO = function (){ * @todo needs to support writing to a specified caret position * */ -helper.edit = async function(message, line){ - let editsNum = helper.commits.length; +helper.edit = async function (message, line) { + const editsNum = helper.commits.length; line = line ? line - 1 : 0; helper.linesDiv()[line].sendkeys(message); - return helper.waitForPromise(function(){ - return editsNum + 1 === helper.commits.length; - }) -} + return helper.waitForPromise(() => editsNum + 1 === helper.commits.length); +}; /** * The pad text as an array of divs @@ -48,11 +43,11 @@ helper.edit = async function(message, line){ * * @returns {Array.} array of divs */ -helper.linesDiv = function(){ - return helper.padInner$('.ace-line').map(function(){ - return $(this) - }).get() -} +helper.linesDiv = function () { + return helper.padInner$('.ace-line').map(function () { + return $(this); + }).get(); +}; /** * The pad text as an array of lines @@ -60,18 +55,18 @@ helper.linesDiv = function(){ * * @returns {Array.} lines of text */ -helper.textLines = function(){ +helper.textLines = function () { return helper.linesDiv().map((div) => div.text()); -} +}; /** * The default pad text transmitted via `clientVars` * * @returns {string} */ -helper.defaultText = function(){ +helper.defaultText = function () { return helper.padChrome$.window.clientVars.collab_client_vars.initialAttributedText.text; -} +}; /** * Sends a chat `message` via `sendKeys` @@ -87,25 +82,23 @@ helper.defaultText = function(){ * @param {string} message the chat message to be sent * @returns {Promise} */ -helper.sendChatMessage = function(message){ - let noOfChatMessages = helper.chatMessages.length; - helper.padChrome$("#chatinput").sendkeys(message) - return helper.waitForPromise(function(){ - return noOfChatMessages + 1 === helper.chatMessages.length; - }) -} +helper.sendChatMessage = function (message) { + const noOfChatMessages = helper.chatMessages.length; + helper.padChrome$('#chatinput').sendkeys(message); + return helper.waitForPromise(() => noOfChatMessages + 1 === helper.chatMessages.length); +}; /** * Opens the settings menu if its hidden via button * * @returns {Promise} */ -helper.showSettings = function() { - if(!helper.isSettingsShown()){ - helper.settingsButton().click() - return helper.waitForPromise(function(){return helper.isSettingsShown(); },2000); +helper.showSettings = function () { + if (!helper.isSettingsShown()) { + helper.settingsButton().click(); + return helper.waitForPromise(() => helper.isSettingsShown(), 2000); } -} +}; /** * Hide the settings menu if its open via button @@ -113,12 +106,12 @@ helper.showSettings = function() { * @returns {Promise} * @todo untested */ -helper.hideSettings = function() { - if(helper.isSettingsShown()){ - helper.settingsButton().click() - return helper.waitForPromise(function(){return !helper.isSettingsShown(); },2000); +helper.hideSettings = function () { + if (helper.isSettingsShown()) { + helper.settingsButton().click(); + return helper.waitForPromise(() => !helper.isSettingsShown(), 2000); } -} +}; /** * Makes the chat window sticky via settings menu if the settings menu is @@ -126,15 +119,13 @@ helper.hideSettings = function() { * * @returns {Promise} */ -helper.enableStickyChatviaSettings = function() { - var stickyChat = helper.padChrome$('#options-stickychat'); - if(helper.isSettingsShown() && !stickyChat.is(':checked')) { +helper.enableStickyChatviaSettings = function () { + const stickyChat = helper.padChrome$('#options-stickychat'); + if (helper.isSettingsShown() && !stickyChat.is(':checked')) { stickyChat.click(); - return helper.waitForPromise(function(){ - return helper.isChatboxSticky(); - },2000); + return helper.waitForPromise(() => helper.isChatboxSticky(), 2000); } -} +}; /** * Unsticks the chat window via settings menu if the settings menu is open @@ -142,13 +133,13 @@ helper.enableStickyChatviaSettings = function() { * * @returns {Promise} */ -helper.disableStickyChatviaSettings = function() { - var stickyChat = helper.padChrome$('#options-stickychat'); - if(helper.isSettingsShown() && stickyChat.is(':checked')) { +helper.disableStickyChatviaSettings = function () { + const stickyChat = helper.padChrome$('#options-stickychat'); + if (helper.isSettingsShown() && stickyChat.is(':checked')) { stickyChat.click(); - return helper.waitForPromise(function(){return !helper.isChatboxSticky()},2000); + return helper.waitForPromise(() => !helper.isChatboxSticky(), 2000); } -} +}; /** * Makes the chat window sticky via an icon on the top right of the chat @@ -156,13 +147,13 @@ helper.disableStickyChatviaSettings = function() { * * @returns {Promise} */ -helper.enableStickyChatviaIcon = function() { - var stickyChat = helper.padChrome$('#titlesticky'); - if(helper.isChatboxShown() && !helper.isChatboxSticky()) { +helper.enableStickyChatviaIcon = function () { + const stickyChat = helper.padChrome$('#titlesticky'); + if (helper.isChatboxShown() && !helper.isChatboxSticky()) { stickyChat.click(); - return helper.waitForPromise(function(){return helper.isChatboxSticky()},2000); + return helper.waitForPromise(() => helper.isChatboxSticky(), 2000); } -} +}; /** * Disables the stickyness of the chat window via an icon on the @@ -170,12 +161,12 @@ helper.enableStickyChatviaIcon = function() { * * @returns {Promise} */ -helper.disableStickyChatviaIcon = function() { - if(helper.isChatboxShown() && helper.isChatboxSticky()) { - helper.titlecross().click() - return helper.waitForPromise(function(){return !helper.isChatboxSticky()},2000); +helper.disableStickyChatviaIcon = function () { + if (helper.isChatboxShown() && helper.isChatboxSticky()) { + helper.titlecross().click(); + return helper.waitForPromise(() => !helper.isChatboxSticky(), 2000); } -} +}; /** * Sets the src-attribute of the main iframe to the timeslider @@ -189,15 +180,14 @@ helper.disableStickyChatviaIcon = function() { * @todo for some reason this does only work the first time, you cannot * goto rev 0 and then via the same method to rev 5. Use buttons instead */ -helper.gotoTimeslider = function(revision){ - revision = Number.isInteger(revision) ? '#'+revision : ''; - var iframe = $('#iframe-container iframe'); - iframe.attr('src', iframe.attr('src')+'/timeslider' + revision); +helper.gotoTimeslider = function (revision) { + revision = Number.isInteger(revision) ? `#${revision}` : ''; + const iframe = $('#iframe-container iframe'); + iframe.attr('src', `${iframe.attr('src')}/timeslider${revision}`); - return helper.waitForPromise(function(){ - return helper.timesliderTimerTime() - && !Number.isNaN(new Date(helper.timesliderTimerTime()).getTime()) },10000); -} + return helper.waitForPromise(() => helper.timesliderTimerTime() && + !Number.isNaN(new Date(helper.timesliderTimerTime()).getTime()), 10000); +}; /** * Clicks in the timeslider at a specific offset @@ -206,24 +196,24 @@ helper.gotoTimeslider = function(revision){ * @todo no mousemove test * @param {number} X coordinate */ -helper.sliderClick = function(X){ - let sliderBar = helper.sliderBar() - let edown = new jQuery.Event('mousedown'); - let eup = new jQuery.Event('mouseup'); +helper.sliderClick = function (X) { + const sliderBar = helper.sliderBar(); + const edown = new jQuery.Event('mousedown'); + const eup = new jQuery.Event('mouseup'); edown.clientX = eup.clientX = X; edown.clientY = eup.clientY = sliderBar.offset().top; sliderBar.trigger(edown); sliderBar.trigger(eup); -} +}; /** * The timeslider text as an array of lines * * @returns {Array.} lines of text */ -helper.timesliderTextLines = function(){ - return helper.contentWindow().$('.ace-line').map(function(){ - return $(this).text() - }).get() -} +helper.timesliderTextLines = function () { + return helper.contentWindow().$('.ace-line').map(function () { + return $(this).text(); + }).get(); +}; diff --git a/tests/frontend/helper/ui.js b/tests/frontend/helper/ui.js index 211e29ecf..d83cbee97 100644 --- a/tests/frontend/helper/ui.js +++ b/tests/frontend/helper/ui.js @@ -3,9 +3,9 @@ * * @returns {HTMLElement} contentWindow */ -helper.contentWindow = function(){ +helper.contentWindow = function () { return $('#iframe-container iframe')[0].contentWindow; -} +}; /** * Opens the chat unless it is already open via an @@ -13,117 +13,118 @@ helper.contentWindow = function(){ * * @returns {Promise} */ -helper.showChat = function(){ - var chaticon = helper.chatIcon(); - if(chaticon.hasClass('visible')) { - chaticon.click() - return helper.waitForPromise(function(){return !chaticon.hasClass('visible'); },2000) +helper.showChat = function () { + const chaticon = helper.chatIcon(); + if (chaticon.hasClass('visible')) { + chaticon.click(); + return helper.waitForPromise(() => !chaticon.hasClass('visible'), 2000); } -} +}; /** * Closes the chat window if it is shown and not sticky * * @returns {Promise} */ -helper.hideChat = function(){ - if(helper.isChatboxShown() && !helper.isChatboxSticky()) { - helper.titlecross().click() - return helper.waitForPromise(function(){return !helper.isChatboxShown(); },2000); +helper.hideChat = function () { + if (helper.isChatboxShown() && !helper.isChatboxSticky()) { + helper.titlecross().click(); + return helper.waitForPromise(() => !helper.isChatboxShown(), 2000); } -} +}; /** * Gets the chat icon from the bottom right of the page * * @returns {HTMLElement} the chat icon */ -helper.chatIcon = function(){return helper.padChrome$('#chaticon')} +helper.chatIcon = function () { return helper.padChrome$('#chaticon'); }; /** * The chat messages from the UI * * @returns {Array.} */ -helper.chatTextParagraphs = function(){return helper.padChrome$('#chattext').children("p")} +helper.chatTextParagraphs = function () { return helper.padChrome$('#chattext').children('p'); }; /** * Returns true if the chat box is sticky * * @returns {boolean} stickyness of the chat box */ -helper.isChatboxSticky = function() { +helper.isChatboxSticky = function () { return helper.padChrome$('#chatbox').hasClass('stickyChat'); -} +}; /** * Returns true if the chat box is shown * * @returns {boolean} visibility of the chat box */ -helper.isChatboxShown = function() { +helper.isChatboxShown = function () { return helper.padChrome$('#chatbox').hasClass('visible'); -} +}; /** * Gets the settings menu * * @returns {HTMLElement} the settings menu */ -helper.settingsMenu = function(){return helper.padChrome$('#settings') }; +helper.settingsMenu = function () { return helper.padChrome$('#settings'); }; /** * Gets the settings button * * @returns {HTMLElement} the settings button */ -helper.settingsButton = function(){return helper.padChrome$("button[data-l10n-id='pad.toolbar.settings.title']") } +helper.settingsButton = function () { return helper.padChrome$("button[data-l10n-id='pad.toolbar.settings.title']"); }; /** * Gets the titlecross icon * * @returns {HTMLElement} the titlecross icon */ -helper.titlecross = function(){return helper.padChrome$('#titlecross')} +helper.titlecross = function () { return helper.padChrome$('#titlecross'); }; /** * Returns true if the settings menu is visible * * @returns {boolean} is the settings menu shown? */ -helper.isSettingsShown = function() { +helper.isSettingsShown = function () { return helper.padChrome$('#settings').hasClass('popup-show'); -} +}; /** * Gets the timer div of a timeslider that has the datetime of the revision * * @returns {HTMLElement} timer */ -helper.timesliderTimer = function(){ - if(typeof helper.contentWindow().$ == 'function'){ - return helper.contentWindow().$('#timer') } +helper.timesliderTimer = function () { + if (typeof helper.contentWindow().$ === 'function') { + return helper.contentWindow().$('#timer'); } +}; /** * Gets the time of the revision on a timeslider * * @returns {HTMLElement} timer */ -helper.timesliderTimerTime = function(){ - if(helper.timesliderTimer()){ - return helper.timesliderTimer().text() +helper.timesliderTimerTime = function () { + if (helper.timesliderTimer()) { + return helper.timesliderTimer().text(); } -} +}; /** * The ui-slidar-bar element in the timeslider * * @returns {HTMLElement} */ -helper.sliderBar = function(){ - return helper.contentWindow().$('#ui-slider-bar') -} +helper.sliderBar = function () { + return helper.contentWindow().$('#ui-slider-bar'); +}; /** * revision_date element @@ -131,9 +132,9 @@ helper.sliderBar = function(){ * * @returns {HTMLElement} */ -helper.revisionDateElem = function(){ +helper.revisionDateElem = function () { return helper.contentWindow().$('#revision_date').text(); -} +}; /** * revision_label element @@ -141,6 +142,6 @@ helper.revisionDateElem = function(){ * * @returns {HTMLElement} */ -helper.revisionLabelElem = function(){ - return helper.contentWindow().$('#revision_label') -} +helper.revisionLabelElem = function () { + return helper.contentWindow().$('#revision_label'); +}; diff --git a/tests/frontend/runner.js b/tests/frontend/runner.js index 0ab380fb7..0a5095815 100644 --- a/tests/frontend/runner.js +++ b/tests/frontend/runner.js @@ -1,11 +1,10 @@ -$(function(){ - - function stringifyException(exception){ - var err = exception.stack || exception.toString(); +$(() => { + function stringifyException(exception) { + let err = exception.stack || exception.toString(); // FF / Opera do not add the message if (!~err.indexOf(exception.message)) { - err = exception.message + '\n' + err; + err = `${exception.message}\n${err}`; } // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we @@ -14,57 +13,57 @@ $(function(){ // Safari doesn't give you a stack. Let's at least provide a source line. if (!exception.stack && exception.sourceURL && exception.line !== undefined) { - err += "\n(" + exception.sourceURL + ":" + exception.line + ")"; + err += `\n(${exception.sourceURL}:${exception.line})`; } return err; } function CustomRunner(runner) { - var stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }; + const stats = {suites: 0, tests: 0, passes: 0, pending: 0, failures: 0}; if (!runner) return; - runner.on('start', function(){ - stats.start = new Date; + runner.on('start', () => { + stats.start = new Date(); }); - runner.on('suite', function(suite){ + runner.on('suite', (suite) => { suite.root || stats.suites++; if (suite.root) return; append(suite.title); level++; }); - runner.on('suite end', function(suite){ + runner.on('suite end', (suite) => { if (suite.root) return; level--; - if(level == 0) { - append(""); + if (level == 0) { + append(''); } }); // Scroll down test display after each test - let mochaEl = $('#mocha')[0]; - runner.on('test', function(){ + const mochaEl = $('#mocha')[0]; + runner.on('test', () => { mochaEl.scrollTop = mochaEl.scrollHeight; }); // max time a test is allowed to run // TODO this should be lowered once timeslider_revision.js is faster - var killTimeout; - runner.on('test end', function(){ + let killTimeout; + runner.on('test end', () => { stats.tests++; }); - runner.on('pass', function(test){ - if(killTimeout) clearTimeout(killTimeout); - killTimeout = setTimeout(function(){ - append("FINISHED - [red]no test started since 3 minutes, tests stopped[clear]"); + runner.on('pass', (test) => { + if (killTimeout) clearTimeout(killTimeout); + killTimeout = setTimeout(() => { + append('FINISHED - [red]no test started since 3 minutes, tests stopped[clear]'); }, 60000 * 3); - var medium = test.slow() / 2; + const medium = test.slow() / 2; test.speed = test.duration > test.slow() ? 'slow' : test.duration > medium @@ -72,107 +71,104 @@ $(function(){ : 'fast'; stats.passes++; - append("->","[green]PASSED[clear] :", test.title," ",test.duration,"ms"); + append('->', '[green]PASSED[clear] :', test.title, ' ', test.duration, 'ms'); }); - runner.on('fail', function(test, err){ - if(killTimeout) clearTimeout(killTimeout); - killTimeout = setTimeout(function(){ - append("FINISHED - [red]no test started since 3 minutes, tests stopped[clear]"); + runner.on('fail', (test, err) => { + if (killTimeout) clearTimeout(killTimeout); + killTimeout = setTimeout(() => { + append('FINISHED - [red]no test started since 3 minutes, tests stopped[clear]'); }, 60000 * 3); stats.failures++; test.err = err; - append("->","[red]FAILED[clear] :", test.title, stringifyException(test.err)); + append('->', '[red]FAILED[clear] :', test.title, stringifyException(test.err)); }); - runner.on('pending', function(test){ - if(killTimeout) clearTimeout(killTimeout); - killTimeout = setTimeout(function(){ - append("FINISHED - [red]no test started since 3 minutes, tests stopped[clear]"); + runner.on('pending', (test) => { + if (killTimeout) clearTimeout(killTimeout); + killTimeout = setTimeout(() => { + append('FINISHED - [red]no test started since 3 minutes, tests stopped[clear]'); }, 60000 * 3); stats.pending++; - append("->","[yellow]PENDING[clear]:", test.title); + append('->', '[yellow]PENDING[clear]:', test.title); }); - var $console = $("#console"); - var level = 0; - var append = function(){ - var text = Array.prototype.join.apply(arguments, [" "]); - var oldText = $console.text(); + const $console = $('#console'); + var level = 0; + var append = function () { + const text = Array.prototype.join.apply(arguments, [' ']); + const oldText = $console.text(); - var space = ""; - for(var i=0;i 0){ - var split = line.substr(0,100); - line = line.substr(100); - if(splitedText.length > 0) splitedText+="\n"; - splitedText += split; - } - }); - - //indent all lines with the given amount of space - var newText = _(splitedText.split("\n")).map(function(line){ - return space + line; - }).join("\\n"); - - $console.text(oldText + newText + "\\n"); + let space = ''; + for (let i = 0; i < level * 2; i++) { + space += ' '; } - var total = runner.total; - runner.on('end', function(){ - stats.end = new Date; - stats.duration = stats.end - stats.start; - var minutes = Math.floor(stats.duration / 1000 / 60); - var seconds = Math.round((stats.duration / 1000) % 60) // chrome < 57 does not like this .toString().padStart("2","0"); - if(stats.tests === total){ - append("FINISHED -", stats.passes, "tests passed,", stats.failures, "tests failed,", stats.pending," pending, duration: " + minutes + ":" + seconds); - } else if (stats.tests > total) { - append("FINISHED - but more tests than planned returned", stats.passes, "tests passed,", stats.failures, "tests failed,", stats.pending," pending, duration: " + minutes + ":" + seconds); - append(total,"tests, but",stats.tests,"returned. There is probably a problem with your async code or error handling, see https://github.com/mochajs/mocha/issues/1327"); - } - else { - append("FINISHED - but not all tests returned", stats.passes, "tests passed,", stats.failures, "tests failed,", stats.pending, "tests pending, duration: " + minutes + ":" + seconds); - append(total,"tests, but only",stats.tests,"returned. Check for failed before/beforeEach-hooks (no `test end` is called for them and subsequent tests of the same suite are skipped), see https://github.com/mochajs/mocha/pull/1043"); + let splitedText = ''; + _(text.split('\n')).each((line) => { + while (line.length > 0) { + const split = line.substr(0, 100); + line = line.substr(100); + if (splitedText.length > 0) splitedText += '\n'; + splitedText += split; } }); + + // indent all lines with the given amount of space + const newText = _(splitedText.split('\n')).map((line) => space + line).join('\\n'); + + $console.text(`${oldText + newText}\\n`); + }; + + const total = runner.total; + runner.on('end', () => { + stats.end = new Date(); + stats.duration = stats.end - stats.start; + const minutes = Math.floor(stats.duration / 1000 / 60); + const seconds = Math.round((stats.duration / 1000) % 60); // chrome < 57 does not like this .toString().padStart("2","0"); + if (stats.tests === total) { + append('FINISHED -', stats.passes, 'tests passed,', stats.failures, 'tests failed,', stats.pending, ` pending, duration: ${minutes}:${seconds}`); + } else if (stats.tests > total) { + append('FINISHED - but more tests than planned returned', stats.passes, 'tests passed,', stats.failures, 'tests failed,', stats.pending, ` pending, duration: ${minutes}:${seconds}`); + append(total, 'tests, but', stats.tests, 'returned. There is probably a problem with your async code or error handling, see https://github.com/mochajs/mocha/issues/1327'); + } else { + append('FINISHED - but not all tests returned', stats.passes, 'tests passed,', stats.failures, 'tests failed,', stats.pending, `tests pending, duration: ${minutes}:${seconds}`); + append(total, 'tests, but only', stats.tests, 'returned. Check for failed before/beforeEach-hooks (no `test end` is called for them and subsequent tests of the same suite are skipped), see https://github.com/mochajs/mocha/pull/1043'); + } + }); } - //http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery - var getURLParameter = function (name) { + // http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery + const getURLParameter = function (name) { return decodeURI( - (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1] + (RegExp(`${name}=` + '(.+?)(&|$)').exec(location.search) || [, null])[1], ); - } + }; - //get the list of specs and filter it if requested - var specs = specs_list.slice(); + // get the list of specs and filter it if requested + const specs = specs_list.slice(); - //inject spec scripts into the dom - var $body = $('body'); - $.each(specs, function(i, spec){ - if(spec[0] != "/"){ // if the spec isn't a plugin spec which means the spec file might be in a different subfolder - $body.append('') - }else{ - $body.append('') + // inject spec scripts into the dom + const $body = $('body'); + $.each(specs, (i, spec) => { + if (spec[0] != '/') { // if the spec isn't a plugin spec which means the spec file might be in a different subfolder + $body.append(``); + } else { + $body.append(``); } }); - //initalize the test helper - helper.init(function(){ - //configure and start the test framework - var grep = getURLParameter("grep"); - if(grep != "null"){ + // initalize the test helper + helper.init(() => { + // configure and start the test framework + const grep = getURLParameter('grep'); + if (grep != 'null') { mocha.grep(grep); } - var runner = mocha.run(); - CustomRunner(runner) + const runner = mocha.run(); + CustomRunner(runner); }); }); diff --git a/tests/frontend/specs/alphabet.js b/tests/frontend/specs/alphabet.js index 5d16c983a..a0ad61bdf 100644 --- a/tests/frontend/specs/alphabet.js +++ b/tests/frontend/specs/alphabet.js @@ -1,27 +1,24 @@ -describe("All the alphabet works n stuff", function(){ - var expectedString = "abcdefghijklmnopqrstuvwxyz"; +describe('All the alphabet works n stuff', function () { + const expectedString = 'abcdefghijklmnopqrstuvwxyz'; - //create a new pad before each test run - beforeEach(function(cb){ + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("when you enter any char it appears right", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('when you enter any char it appears right', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const firstTextElement = inner$('div').first(); // simulate key presses to delete content firstTextElement.sendkeys('{selectall}'); // select all firstTextElement.sendkeys('{del}'); // clear the first line firstTextElement.sendkeys(expectedString); // insert the string - helper.waitFor(function(){ - return inner$("div").first().text() === expectedString; - }, 2000).done(done); + helper.waitFor(() => inner$('div').first().text() === expectedString, 2000).done(done); }); - }); diff --git a/tests/frontend/specs/authorship_of_editions.js b/tests/frontend/specs/authorship_of_editions.js index 0c173e962..6cf14b869 100644 --- a/tests/frontend/specs/authorship_of_editions.js +++ b/tests/frontend/specs/authorship_of_editions.js @@ -1,46 +1,46 @@ -describe('author of pad edition', function() { - var REGULAR_LINE = 0; - var LINE_WITH_ORDERED_LIST = 1; - var LINE_WITH_UNORDERED_LIST = 2; +describe('author of pad edition', function () { + const REGULAR_LINE = 0; + const LINE_WITH_ORDERED_LIST = 1; + const LINE_WITH_UNORDERED_LIST = 2; // author 1 creates a new pad with some content (regular lines and lists) - before(function(done) { - var padId = helper.newPad(function() { + before(function (done) { + var padId = helper.newPad(() => { // make sure pad has at least 3 lines - var $firstLine = helper.padInner$('div').first(); - var threeLines = ['regular line', 'line with ordered list', 'line with unordered list'].join('
        '); + const $firstLine = helper.padInner$('div').first(); + const threeLines = ['regular line', 'line with ordered list', 'line with unordered list'].join('
        '); $firstLine.html(threeLines); // wait for lines to be processed by Etherpad - helper.waitFor(function() { - var $lineWithUnorderedList = getLine(LINE_WITH_UNORDERED_LIST); + helper.waitFor(() => { + const $lineWithUnorderedList = getLine(LINE_WITH_UNORDERED_LIST); return $lineWithUnorderedList.text() === 'line with unordered list'; - }).done(function() { + }).done(() => { // create the unordered list - var $lineWithUnorderedList = getLine(LINE_WITH_UNORDERED_LIST); + const $lineWithUnorderedList = getLine(LINE_WITH_UNORDERED_LIST); $lineWithUnorderedList.sendkeys('{selectall}'); - var $insertUnorderedListButton = helper.padChrome$('.buttonicon-insertunorderedlist'); + const $insertUnorderedListButton = helper.padChrome$('.buttonicon-insertunorderedlist'); $insertUnorderedListButton.click(); - helper.waitFor(function() { - var $lineWithUnorderedList = getLine(LINE_WITH_UNORDERED_LIST); + helper.waitFor(() => { + const $lineWithUnorderedList = getLine(LINE_WITH_UNORDERED_LIST); return $lineWithUnorderedList.find('ul li').length === 1; - }).done(function() { + }).done(() => { // create the ordered list - var $lineWithOrderedList = getLine(LINE_WITH_ORDERED_LIST); + const $lineWithOrderedList = getLine(LINE_WITH_ORDERED_LIST); $lineWithOrderedList.sendkeys('{selectall}'); - var $insertOrderedListButton = helper.padChrome$('.buttonicon-insertorderedlist'); + const $insertOrderedListButton = helper.padChrome$('.buttonicon-insertorderedlist'); $insertOrderedListButton.click(); - helper.waitFor(function() { - var $lineWithOrderedList = getLine(LINE_WITH_ORDERED_LIST); + helper.waitFor(() => { + const $lineWithOrderedList = getLine(LINE_WITH_ORDERED_LIST); return $lineWithOrderedList.find('ol li').length === 1; - }).done(function() { + }).done(() => { // Reload pad, to make changes as a second user. Need a timeout here to make sure // all changes were saved before reloading - setTimeout(function() { + setTimeout(() => { // Expire cookie, so author is changed after reloading the pad. // See https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#Example_4_Reset_the_previous_cookie helper.padChrome$.document.cookie = 'token=foo;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'; @@ -55,55 +55,51 @@ describe('author of pad edition', function() { }); // author 2 makes some changes on the pad - it('marks only the new content as changes of the second user on a regular line', function(done) { + it('marks only the new content as changes of the second user on a regular line', function (done) { changeLineAndCheckOnlyThatChangeIsFromThisAuthor(REGULAR_LINE, 'x', done); }); - it('marks only the new content as changes of the second user on a line with ordered list', function(done) { + it('marks only the new content as changes of the second user on a line with ordered list', function (done) { changeLineAndCheckOnlyThatChangeIsFromThisAuthor(LINE_WITH_ORDERED_LIST, 'y', done); }); - it('marks only the new content as changes of the second user on a line with unordered list', function(done) { + it('marks only the new content as changes of the second user on a line with unordered list', function (done) { changeLineAndCheckOnlyThatChangeIsFromThisAuthor(LINE_WITH_UNORDERED_LIST, 'z', done); }); /* ********************** Helper functions ************************ */ - var getLine = function(lineNumber) { + var getLine = function (lineNumber) { return helper.padInner$('div').eq(lineNumber); - } + }; - var getAuthorFromClassList = function(classes) { - return classes.find(function(cls) { - return cls.startsWith('author'); - }); - } + const getAuthorFromClassList = function (classes) { + return classes.find((cls) => cls.startsWith('author')); + }; - var changeLineAndCheckOnlyThatChangeIsFromThisAuthor = function(lineNumber, textChange, done) { + var changeLineAndCheckOnlyThatChangeIsFromThisAuthor = function (lineNumber, textChange, done) { // get original author class - var classes = getLine(lineNumber).find('span').first().attr('class').split(' '); - var originalAuthor = getAuthorFromClassList(classes); + const classes = getLine(lineNumber).find('span').first().attr('class').split(' '); + const originalAuthor = getAuthorFromClassList(classes); // make change on target line - var $regularLine = getLine(lineNumber); + const $regularLine = getLine(lineNumber); helper.selectLines($regularLine, $regularLine, 2, 2); // place caret after 2nd char of line $regularLine.sendkeys(textChange); // wait for change to be processed by Etherpad - var otherAuthorsOfLine; - helper.waitFor(function() { - var authorsOfLine = getLine(lineNumber).find('span').map(function() { + let otherAuthorsOfLine; + helper.waitFor(() => { + const authorsOfLine = getLine(lineNumber).find('span').map(function () { return getAuthorFromClassList($(this).attr('class').split(' ')); }).get(); - otherAuthorsOfLine = authorsOfLine.filter(function(author) { - return author !== originalAuthor; - }); - var lineHasChangeOfThisAuthor = otherAuthorsOfLine.length > 0; + otherAuthorsOfLine = authorsOfLine.filter((author) => author !== originalAuthor); + const lineHasChangeOfThisAuthor = otherAuthorsOfLine.length > 0; return lineHasChangeOfThisAuthor; - }).done(function() { - var thisAuthor = otherAuthorsOfLine[0]; - var $changeOfThisAuthor = getLine(lineNumber).find('span.' + thisAuthor); + }).done(() => { + const thisAuthor = otherAuthorsOfLine[0]; + const $changeOfThisAuthor = getLine(lineNumber).find(`span.${thisAuthor}`); expect($changeOfThisAuthor.text()).to.be(textChange); done(); }); - } + }; }); diff --git a/tests/frontend/specs/bold.js b/tests/frontend/specs/bold.js index 94e3a9b5b..a7c46e1bc 100644 --- a/tests/frontend/specs/bold.js +++ b/tests/frontend/specs/bold.js @@ -1,64 +1,64 @@ -describe("bold button", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('bold button', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("makes text bold on click", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text bold on click', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - //get the bold button and click it - var $boldButton = chrome$(".buttonicon-bold"); + // get the bold button and click it + const $boldButton = chrome$('.buttonicon-bold'); $boldButton.click(); - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); + // ace creates a new dom element when you press a button, so just get the first text element again + const $newFirstTextElement = inner$('div').first(); // is there a element now? - var isBold = $newFirstTextElement.find("b").length === 1; + const isBold = $newFirstTextElement.find('b').length === 1; - //expect it to be bold + // expect it to be bold expect(isBold).to.be(true); - //make sure the text hasn't changed + // make sure the text hasn't changed expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); done(); }); - it("makes text bold on keypress", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text bold on keypress', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - var e = inner$.Event(helper.evtType); + const e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 66; // b - inner$("#innerdocbody").trigger(e); + inner$('#innerdocbody').trigger(e); - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); + // ace creates a new dom element when you press a button, so just get the first text element again + const $newFirstTextElement = inner$('div').first(); // is there a element now? - var isBold = $newFirstTextElement.find("b").length === 1; + const isBold = $newFirstTextElement.find('b').length === 1; - //expect it to be bold + // expect it to be bold expect(isBold).to.be(true); - //make sure the text hasn't changed + // make sure the text hasn't changed expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); done(); diff --git a/tests/frontend/specs/caret.js b/tests/frontend/specs/caret.js index b15dd1597..1fb8d8aa7 100644 --- a/tests/frontend/specs/caret.js +++ b/tests/frontend/specs/caret.js @@ -1,7 +1,7 @@ -describe("As the caret is moved is the UI properly updated?", function(){ - var padName; - var numberOfRows = 50; -/* +describe('As the caret is moved is the UI properly updated?', function () { + let padName; + const numberOfRows = 50; + /* //create a new pad before each test run beforeEach(function(cb){ @@ -28,7 +28,7 @@ describe("As the caret is moved is the UI properly updated?", function(){ * How do we keep the authors focus on a line if the lines above the author are modified? We should only redraw the user to a location if they are typing and make sure shift and arrow keys aren't redrawing the UI else highlight - copy/paste would get broken * How can we simulate an edit event in the test framework? */ -/* + /* // THIS DOESNT WORK IN CHROME AS IT DOESNT MOVE THE CURSOR! it("down arrow", function(done){ var inner$ = helper.padInner$; @@ -194,7 +194,6 @@ console.log(inner$); }); - /* it("Creates N rows, changes height of rows, updates UI by caret key events", function(done){ var inner$ = helper.padInner$; @@ -264,7 +263,6 @@ console.log(inner$); }).done(function(){ // Once the DOM has registered the items - }); }); @@ -284,54 +282,51 @@ console.log(inner$); done(); }); */ - }); -function prepareDocument(n, target){ // generates a random document with random content on n lines - var i = 0; - while(i < n){ // for each line +function prepareDocument(n, target) { // generates a random document with random content on n lines + let i = 0; + while (i < n) { // for each line target.sendkeys(makeStr()); // generate a random string and send that to the editor target.sendkeys('{enter}'); // generator an enter keypress i++; // rinse n times } } -function keyEvent(target, charCode, ctrl, shift){ // sends a charCode to the window - - var e = target.Event(helper.evtType); - if(ctrl){ +function keyEvent(target, charCode, ctrl, shift) { // sends a charCode to the window + const e = target.Event(helper.evtType); + if (ctrl) { e.ctrlKey = true; // Control key } - if(shift){ + if (shift) { e.shiftKey = true; // Shift Key } e.which = charCode; e.keyCode = charCode; - target("#innerdocbody").trigger(e); + target('#innerdocbody').trigger(e); } -function makeStr(){ // from http://stackoverflow.com/questions/1349404/generate-a-string-of-5-random-characters-in-javascript - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; +function makeStr() { // from http://stackoverflow.com/questions/1349404/generate-a-string-of-5-random-characters-in-javascript + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for( var i=0; i < 5; i++ ) - text += possible.charAt(Math.floor(Math.random() * possible.length)); + for (let i = 0; i < 5; i++) text += possible.charAt(Math.floor(Math.random() * possible.length)); return text; } -function isScrolledIntoView(elem, $){ // from http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling - var docViewTop = $(window).scrollTop(); - var docViewBottom = docViewTop + $(window).height(); - var elemTop = $(elem).offset().top; // how far the element is from the top of it's container - var elemBottom = elemTop + $(elem).height(); // how far plus the height of the elem.. IE is it all in? - elemBottom = elemBottom - 16; // don't ask, sorry but this is needed.. - return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); +function isScrolledIntoView(elem, $) { // from http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling + const docViewTop = $(window).scrollTop(); + const docViewBottom = docViewTop + $(window).height(); + const elemTop = $(elem).offset().top; // how far the element is from the top of it's container + let elemBottom = elemTop + $(elem).height(); // how far plus the height of the elem.. IE is it all in? + elemBottom -= 16; // don't ask, sorry but this is needed.. + return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); } -function caretPosition($){ - var doc = $.window.document; - var pos = doc.getSelection(); +function caretPosition($) { + const doc = $.window.document; + const pos = doc.getSelection(); pos.y = pos.anchorNode.parentElement.offsetTop; pos.x = pos.anchorNode.parentElement.offsetLeft; return pos; diff --git a/tests/frontend/specs/change_user_color.js b/tests/frontend/specs/change_user_color.js index 5969eabe2..3b4b3d20e 100644 --- a/tests/frontend/specs/change_user_color.js +++ b/tests/frontend/specs/change_user_color.js @@ -1,102 +1,101 @@ -describe("change user color", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('change user color', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("Color picker matches original color and remembers the user color after a refresh", function(done) { + it('Color picker matches original color and remembers the user color after a refresh', function (done) { this.timeout(60000); - var chrome$ = helper.padChrome$; + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); + // click on the settings button to make settings visible + const $userButton = chrome$('.buttonicon-showusers'); $userButton.click(); - var $userSwatch = chrome$("#myswatch"); + const $userSwatch = chrome$('#myswatch'); $userSwatch.click(); - var fb = chrome$.farbtastic('#colorpicker') - var $colorPickerSave = chrome$("#mycolorpickersave"); - var $colorPickerPreview = chrome$("#mycolorpickerpreview"); + const fb = chrome$.farbtastic('#colorpicker'); + const $colorPickerSave = chrome$('#mycolorpickersave'); + const $colorPickerPreview = chrome$('#mycolorpickerpreview'); // Same color represented in two different ways - const testColorHash = '#abcdef' - const testColorRGB = 'rgb(171, 205, 239)' + const testColorHash = '#abcdef'; + const testColorRGB = 'rgb(171, 205, 239)'; // Check that the color picker matches the automatically assigned random color on the swatch. // NOTE: This has a tiny chance of creating a false positive for passing in the // off-chance the randomly assigned color is the same as the test color. - expect($colorPickerPreview.css('background-color')).to.be($userSwatch.css('background-color')) + expect($colorPickerPreview.css('background-color')).to.be($userSwatch.css('background-color')); // The swatch updates as the test color is picked. - fb.setColor(testColorHash) - expect($colorPickerPreview.css('background-color')).to.be(testColorRGB) + fb.setColor(testColorHash); + expect($colorPickerPreview.css('background-color')).to.be(testColorRGB); $colorPickerSave.click(); - expect($userSwatch.css('background-color')).to.be(testColorRGB) + expect($userSwatch.css('background-color')).to.be(testColorRGB); - setTimeout(function(){ //give it a second to save the color on the server side + setTimeout(() => { // give it a second to save the color on the server side helper.newPad({ // get a new pad, but don't clear the cookies - clearCookies: false - , cb: function(){ - var chrome$ = helper.padChrome$; + clearCookies: false, + cb() { + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); + // click on the settings button to make settings visible + const $userButton = chrome$('.buttonicon-showusers'); $userButton.click(); - var $userSwatch = chrome$("#myswatch"); + const $userSwatch = chrome$('#myswatch'); $userSwatch.click(); - var $colorPickerPreview = chrome$("#mycolorpickerpreview"); + const $colorPickerPreview = chrome$('#mycolorpickerpreview'); - expect($colorPickerPreview.css('background-color')).to.be(testColorRGB) - expect($userSwatch.css('background-color')).to.be(testColorRGB) + expect($colorPickerPreview.css('background-color')).to.be(testColorRGB); + expect($userSwatch.css('background-color')).to.be(testColorRGB); done(); - } + }, }); }, 1000); }); - it("Own user color is shown when you enter a chat", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('Own user color is shown when you enter a chat', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - var $colorOption = helper.padChrome$('#options-colorscheck'); + const $colorOption = helper.padChrome$('#options-colorscheck'); if (!$colorOption.is(':checked')) { $colorOption.click(); } - //click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); + // click on the settings button to make settings visible + const $userButton = chrome$('.buttonicon-showusers'); $userButton.click(); - var $userSwatch = chrome$("#myswatch"); + const $userSwatch = chrome$('#myswatch'); $userSwatch.click(); - var fb = chrome$.farbtastic('#colorpicker') - var $colorPickerSave = chrome$("#mycolorpickersave"); + const fb = chrome$.farbtastic('#colorpicker'); + const $colorPickerSave = chrome$('#mycolorpickersave'); // Same color represented in two different ways - const testColorHash = '#abcdef' - const testColorRGB = 'rgb(171, 205, 239)' + const testColorHash = '#abcdef'; + const testColorRGB = 'rgb(171, 205, 239)'; - fb.setColor(testColorHash) + fb.setColor(testColorHash); $colorPickerSave.click(); - //click on the chat button to make chat visible - var $chatButton = chrome$("#chaticon"); + // click on the chat button to make chat visible + const $chatButton = chrome$('#chaticon'); $chatButton.click(); - var $chatInput = chrome$("#chatinput"); + const $chatInput = chrome$('#chatinput'); $chatInput.sendkeys('O hi'); // simulate a keypress of typing user $chatInput.sendkeys('{enter}'); // simulate a keypress of enter actually does evt.which = 10 not 13 - //check if chat shows up - helper.waitFor(function(){ - return chrome$("#chattext").children("p").length !== 0; // wait until the chat message shows up - }).done(function(){ - var $firstChatMessage = chrome$("#chattext").children("p"); + // check if chat shows up + helper.waitFor(() => chrome$('#chattext').children('p').length !== 0, // wait until the chat message shows up + ).done(() => { + const $firstChatMessage = chrome$('#chattext').children('p'); expect($firstChatMessage.css('background-color')).to.be(testColorRGB); // expect the first chat message to be of the user's color done(); }); diff --git a/tests/frontend/specs/change_user_name.js b/tests/frontend/specs/change_user_name.js index b0a5df15f..d0d9b763c 100644 --- a/tests/frontend/specs/change_user_name.js +++ b/tests/frontend/specs/change_user_name.js @@ -1,70 +1,69 @@ -describe("change username value", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('change username value', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("Remembers the user name after a refresh", function(done) { + it('Remembers the user name after a refresh', function (done) { this.timeout(60000); - var chrome$ = helper.padChrome$; + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); + // click on the settings button to make settings visible + const $userButton = chrome$('.buttonicon-showusers'); $userButton.click(); - var $usernameInput = chrome$("#myusernameedit"); + const $usernameInput = chrome$('#myusernameedit'); $usernameInput.click(); $usernameInput.val('John McLear'); $usernameInput.blur(); - setTimeout(function(){ //give it a second to save the username on the server side + setTimeout(() => { // give it a second to save the username on the server side helper.newPad({ // get a new pad, but don't clear the cookies - clearCookies: false - , cb: function(){ - var chrome$ = helper.padChrome$; + clearCookies: false, + cb() { + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); + // click on the settings button to make settings visible + const $userButton = chrome$('.buttonicon-showusers'); $userButton.click(); - var $usernameInput = chrome$("#myusernameedit"); - expect($usernameInput.val()).to.be('John McLear') + const $usernameInput = chrome$('#myusernameedit'); + expect($usernameInput.val()).to.be('John McLear'); done(); - } + }, }); }, 1000); }); - it("Own user name is shown when you enter a chat", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('Own user name is shown when you enter a chat', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); + // click on the settings button to make settings visible + const $userButton = chrome$('.buttonicon-showusers'); $userButton.click(); - var $usernameInput = chrome$("#myusernameedit"); + const $usernameInput = chrome$('#myusernameedit'); $usernameInput.click(); $usernameInput.val('John McLear'); $usernameInput.blur(); - //click on the chat button to make chat visible - var $chatButton = chrome$("#chaticon"); + // click on the chat button to make chat visible + const $chatButton = chrome$('#chaticon'); $chatButton.click(); - var $chatInput = chrome$("#chatinput"); + const $chatInput = chrome$('#chatinput'); $chatInput.sendkeys('O hi'); // simulate a keypress of typing JohnMcLear $chatInput.sendkeys('{enter}'); // simulate a keypress of enter actually does evt.which = 10 not 13 - //check if chat shows up - helper.waitFor(function(){ - return chrome$("#chattext").children("p").length !== 0; // wait until the chat message shows up - }).done(function(){ - var $firstChatMessage = chrome$("#chattext").children("p"); - var containsJohnMcLear = $firstChatMessage.text().indexOf("John McLear") !== -1; // does the string contain John McLear + // check if chat shows up + helper.waitFor(() => chrome$('#chattext').children('p').length !== 0, // wait until the chat message shows up + ).done(() => { + const $firstChatMessage = chrome$('#chattext').children('p'); + const containsJohnMcLear = $firstChatMessage.text().indexOf('John McLear') !== -1; // does the string contain John McLear expect(containsJohnMcLear).to.be(true); // expect the first chat message to contain JohnMcLear done(); }); diff --git a/tests/frontend/specs/chat.js b/tests/frontend/specs/chat.js index caf19bbf5..d45988d60 100644 --- a/tests/frontend/specs/chat.js +++ b/tests/frontend/specs/chat.js @@ -1,11 +1,11 @@ -describe("Chat messages and UI", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('Chat messages and UI', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); }); - it("opens chat, sends a message, makes sure it exists on the page and hides chat", async function() { - var chatValue = "JohnMcLear"; + it('opens chat, sends a message, makes sure it exists on the page and hides chat', async function () { + const chatValue = 'JohnMcLear'; await helper.showChat(); await helper.sendChatMessage(`${chatValue}{enter}`); @@ -18,33 +18,33 @@ describe("Chat messages and UI", function(){ // 12:38 // JohnMcLear //

        - let username = helper.chatTextParagraphs().children("b").text(); - let time = helper.chatTextParagraphs().children(".time").text(); + const username = helper.chatTextParagraphs().children('b').text(); + const time = helper.chatTextParagraphs().children('.time').text(); expect(helper.chatTextParagraphs().text()).to.be(`${username}${time} ${chatValue}`); await helper.hideChat(); }); - it("makes sure that an empty message can't be sent", async function() { - var chatValue = "mluto"; + it("makes sure that an empty message can't be sent", async function () { + const chatValue = 'mluto'; await helper.showChat(); await helper.sendChatMessage(`{enter}${chatValue}{enter}`); // simulate a keypress of typing enter, mluto and enter (to send 'mluto') - let chat = helper.chatTextParagraphs(); + const chat = helper.chatTextParagraphs(); expect(chat.length).to.be(1); // check that the received message is not the empty one - let username = chat.children("b").text(); - let time = chat.children(".time").text(); + const username = chat.children('b').text(); + const time = chat.children('.time').text(); expect(chat.text()).to.be(`${username}${time} ${chatValue}`); }); - it("makes chat stick to right side of the screen via settings, remove sticky via settings, close it", async function() { + it('makes chat stick to right side of the screen via settings, remove sticky via settings, close it', async function () { await helper.showSettings(); await helper.enableStickyChatviaSettings(); @@ -60,7 +60,7 @@ describe("Chat messages and UI", function(){ expect(helper.isChatboxShown()).to.be(false); }); - it("makes chat stick to right side of the screen via icon on the top right, remove sticky via icon, close it", async function() { + it('makes chat stick to right side of the screen via icon on the top right, remove sticky via icon, close it', async function () { await helper.showChat(); await helper.enableStickyChatviaIcon(); @@ -76,39 +76,36 @@ describe("Chat messages and UI", function(){ expect(helper.isChatboxShown()).to.be(false); }); - xit("Checks showChat=false URL Parameter hides chat then when removed it shows chat", function(done) { + xit('Checks showChat=false URL Parameter hides chat then when removed it shows chat', function (done) { this.timeout(60000); - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - setTimeout(function(){ //give it a second to save the username on the server side + setTimeout(() => { // give it a second to save the username on the server side helper.newPad({ // get a new pad, but don't clear the cookies clearCookies: false, - params:{ - showChat: "false" - }, cb: function(){ - var chrome$ = helper.padChrome$; - var chaticon = chrome$("#chaticon"); + params: { + showChat: 'false', + }, cb() { + const chrome$ = helper.padChrome$; + const chaticon = chrome$('#chaticon'); // chat should be hidden. - expect(chaticon.is(":visible")).to.be(false); + expect(chaticon.is(':visible')).to.be(false); - setTimeout(function(){ //give it a second to save the username on the server side + setTimeout(() => { // give it a second to save the username on the server side helper.newPad({ // get a new pad, but don't clear the cookies - clearCookies: false - , cb: function(){ - var chrome$ = helper.padChrome$; - var chaticon = chrome$("#chaticon"); + clearCookies: false, + cb() { + const chrome$ = helper.padChrome$; + const chaticon = chrome$('#chaticon'); // chat should be visible. - expect(chaticon.is(":visible")).to.be(true); + expect(chaticon.is(':visible')).to.be(true); done(); - } + }, }); }, 1000); - - } + }, }); }, 1000); - }); - }); diff --git a/tests/frontend/specs/chat_load_messages.js b/tests/frontend/specs/chat_load_messages.js index 29040798d..29c1734ca 100644 --- a/tests/frontend/specs/chat_load_messages.js +++ b/tests/frontend/specs/chat_load_messages.js @@ -1,85 +1,77 @@ -describe("chat-load-messages", function(){ - var padName; +describe('chat-load-messages', function () { + let padName; - it("creates a pad", function(done) { + it('creates a pad', function (done) { padName = helper.newPad(done); this.timeout(60000); }); - it("adds a lot of messages", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - var chatButton = chrome$("#chaticon"); + it('adds a lot of messages', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; + const chatButton = chrome$('#chaticon'); chatButton.click(); - var chatInput = chrome$("#chatinput"); - var chatText = chrome$("#chattext"); + const chatInput = chrome$('#chatinput'); + const chatText = chrome$('#chattext'); this.timeout(60000); - var messages = 140; - for(var i=1; i <= messages; i++) { - var num = ''+i; - if(num.length == 1) - num = '00'+num; - if(num.length == 2) - num = '0'+num; - chatInput.sendkeys('msg' + num); + const messages = 140; + for (let i = 1; i <= messages; i++) { + let num = `${i}`; + if (num.length == 1) num = `00${num}`; + if (num.length == 2) num = `0${num}`; + chatInput.sendkeys(`msg${num}`); chatInput.sendkeys('{enter}'); } - helper.waitFor(function(){ - return chatText.children("p").length == messages; - }, 60000).always(function(){ - expect(chatText.children("p").length).to.be(messages); + helper.waitFor(() => chatText.children('p').length == messages, 60000).always(() => { + expect(chatText.children('p').length).to.be(messages); helper.newPad(done, padName); - }); + }); }); - it("checks initial message count", function(done) { - var chatText; - var expectedCount = 101; - var chrome$ = helper.padChrome$; - helper.waitFor(function(){ - var chatButton = chrome$("#chaticon"); + it('checks initial message count', function (done) { + let chatText; + const expectedCount = 101; + const chrome$ = helper.padChrome$; + helper.waitFor(() => { + const chatButton = chrome$('#chaticon'); chatButton.click(); - chatText = chrome$("#chattext"); - return chatText.children("p").length == expectedCount; - }).always(function(){ - expect(chatText.children("p").length).to.be(expectedCount); + chatText = chrome$('#chattext'); + return chatText.children('p').length == expectedCount; + }).always(() => { + expect(chatText.children('p').length).to.be(expectedCount); done(); }); }); - it("loads more messages", function(done) { - var expectedCount = 122; - var chrome$ = helper.padChrome$; - var chatButton = chrome$("#chaticon"); + it('loads more messages', function (done) { + const expectedCount = 122; + const chrome$ = helper.padChrome$; + const chatButton = chrome$('#chaticon'); chatButton.click(); - var chatText = chrome$("#chattext"); - var loadMsgBtn = chrome$("#chatloadmessagesbutton"); + const chatText = chrome$('#chattext'); + const loadMsgBtn = chrome$('#chatloadmessagesbutton'); loadMsgBtn.click(); - helper.waitFor(function(){ - return chatText.children("p").length == expectedCount; - }).always(function(){ - expect(chatText.children("p").length).to.be(expectedCount); + helper.waitFor(() => chatText.children('p').length == expectedCount).always(() => { + expect(chatText.children('p').length).to.be(expectedCount); done(); }); }); - it("checks for button vanishing", function(done) { - var expectedDisplay = 'none'; - var chrome$ = helper.padChrome$; - var chatButton = chrome$("#chaticon"); + it('checks for button vanishing', function (done) { + const expectedDisplay = 'none'; + const chrome$ = helper.padChrome$; + const chatButton = chrome$('#chaticon'); chatButton.click(); - var chatText = chrome$("#chattext"); - var loadMsgBtn = chrome$("#chatloadmessagesbutton"); - var loadMsgBall = chrome$("#chatloadmessagesball"); + const chatText = chrome$('#chattext'); + const loadMsgBtn = chrome$('#chatloadmessagesbutton'); + const loadMsgBall = chrome$('#chatloadmessagesball'); loadMsgBtn.click(); - helper.waitFor(function(){ - return loadMsgBtn.css('display') == expectedDisplay && - loadMsgBall.css('display') == expectedDisplay; - }).always(function(){ + helper.waitFor(() => loadMsgBtn.css('display') == expectedDisplay && + loadMsgBall.css('display') == expectedDisplay).always(() => { expect(loadMsgBtn.css('display')).to.be(expectedDisplay); expect(loadMsgBall.css('display')).to.be(expectedDisplay); done(); diff --git a/tests/frontend/specs/clear_authorship_colors.js b/tests/frontend/specs/clear_authorship_colors.js index 143a8612d..0be189625 100644 --- a/tests/frontend/specs/clear_authorship_colors.js +++ b/tests/frontend/specs/clear_authorship_colors.js @@ -1,133 +1,128 @@ -describe("clear authorship colors button", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('clear authorship colors button', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("makes text clear authorship colors", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text clear authorship colors', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // override the confirm dialogue functioon - helper.padChrome$.window.confirm = function(){ + helper.padChrome$.window.confirm = function () { return true; - } + }; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); // Get the original text - var originalText = inner$("div").first().text(); + const originalText = inner$('div').first().text(); // Set some new text - var sentText = "Hello"; + const sentText = 'Hello'; - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); $firstTextElement.sendkeys(sentText); $firstTextElement.sendkeys('{rightarrow}'); - helper.waitFor(function(){ - return inner$("div span").first().attr("class").indexOf("author") !== -1; // wait until we have the full value available - }).done(function(){ - //IE hates you if you don't give focus to the inner frame bevore you do a clearAuthorship - inner$("div").first().focus(); + helper.waitFor(() => inner$('div span').first().attr('class').indexOf('author') !== -1, // wait until we have the full value available + ).done(() => { + // IE hates you if you don't give focus to the inner frame bevore you do a clearAuthorship + inner$('div').first().focus(); - //get the clear authorship colors button and click it - var $clearauthorshipcolorsButton = chrome$(".buttonicon-clearauthorship"); + // get the clear authorship colors button and click it + const $clearauthorshipcolorsButton = chrome$('.buttonicon-clearauthorship'); $clearauthorshipcolorsButton.click(); // does the first divs span include an author class? - var hasAuthorClass = inner$("div span").first().attr("class").indexOf("author") !== -1; - //expect(hasAuthorClass).to.be(false); + var hasAuthorClass = inner$('div span').first().attr('class').indexOf('author') !== -1; + // expect(hasAuthorClass).to.be(false); // does the first div include an author class? - var hasAuthorClass = inner$("div").first().attr("class").indexOf("author") !== -1; + var hasAuthorClass = inner$('div').first().attr('class').indexOf('author') !== -1; expect(hasAuthorClass).to.be(false); - helper.waitFor(function(){ - var disconnectVisible = chrome$("div.disconnected").attr("class").indexOf("visible") === -1 - return (disconnectVisible === true) + helper.waitFor(() => { + const disconnectVisible = chrome$('div.disconnected').attr('class').indexOf('visible') === -1; + return (disconnectVisible === true); }); - var disconnectVisible = chrome$("div.disconnected").attr("class").indexOf("visible") === -1 + const disconnectVisible = chrome$('div.disconnected').attr('class').indexOf('visible') === -1; expect(disconnectVisible).to.be(true); done(); }); - }); - it("makes text clear authorship colors and checks it can't be undone", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it("makes text clear authorship colors and checks it can't be undone", function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // override the confirm dialogue functioon - helper.padChrome$.window.confirm = function(){ + helper.padChrome$.window.confirm = function () { return true; - } + }; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); // Get the original text - var originalText = inner$("div").first().text(); + const originalText = inner$('div').first().text(); // Set some new text - var sentText = "Hello"; + const sentText = 'Hello'; - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); $firstTextElement.sendkeys(sentText); $firstTextElement.sendkeys('{rightarrow}'); - helper.waitFor(function(){ - return inner$("div span").first().attr("class").indexOf("author") !== -1; // wait until we have the full value available - }).done(function(){ - //IE hates you if you don't give focus to the inner frame bevore you do a clearAuthorship - inner$("div").first().focus(); + helper.waitFor(() => inner$('div span').first().attr('class').indexOf('author') !== -1, // wait until we have the full value available + ).done(() => { + // IE hates you if you don't give focus to the inner frame bevore you do a clearAuthorship + inner$('div').first().focus(); - //get the clear authorship colors button and click it - var $clearauthorshipcolorsButton = chrome$(".buttonicon-clearauthorship"); + // get the clear authorship colors button and click it + const $clearauthorshipcolorsButton = chrome$('.buttonicon-clearauthorship'); $clearauthorshipcolorsButton.click(); // does the first divs span include an author class? - var hasAuthorClass = inner$("div span").first().attr("class").indexOf("author") !== -1; - //expect(hasAuthorClass).to.be(false); + var hasAuthorClass = inner$('div span').first().attr('class').indexOf('author') !== -1; + // expect(hasAuthorClass).to.be(false); // does the first div include an author class? - var hasAuthorClass = inner$("div").first().attr("class").indexOf("author") !== -1; + var hasAuthorClass = inner$('div').first().attr('class').indexOf('author') !== -1; expect(hasAuthorClass).to.be(false); - var e = inner$.Event(helper.evtType); + const e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 90; // z - inner$("#innerdocbody").trigger(e); // shouldn't od anything + inner$('#innerdocbody').trigger(e); // shouldn't od anything // does the first div include an author class? - hasAuthorClass = inner$("div").first().attr("class").indexOf("author") !== -1; + hasAuthorClass = inner$('div').first().attr('class').indexOf('author') !== -1; expect(hasAuthorClass).to.be(false); // get undo and redo buttons - var $undoButton = chrome$(".buttonicon-undo"); + const $undoButton = chrome$('.buttonicon-undo'); // click the button $undoButton.click(); // shouldn't do anything - hasAuthorClass = inner$("div").first().attr("class").indexOf("author") !== -1; + hasAuthorClass = inner$('div').first().attr('class').indexOf('author') !== -1; expect(hasAuthorClass).to.be(false); - helper.waitFor(function(){ - var disconnectVisible = chrome$("div.disconnected").attr("class").indexOf("visible") === -1 - return (disconnectVisible === true) + helper.waitFor(() => { + const disconnectVisible = chrome$('div.disconnected').attr('class').indexOf('visible') === -1; + return (disconnectVisible === true); }); - var disconnectVisible = chrome$("div.disconnected").attr("class").indexOf("visible") === -1 + const disconnectVisible = chrome$('div.disconnected').attr('class').indexOf('visible') === -1; expect(disconnectVisible).to.be(true); done(); }); - }); }); - diff --git a/tests/frontend/specs/delete.js b/tests/frontend/specs/delete.js index 639980f5f..4267aeec7 100644 --- a/tests/frontend/specs/delete.js +++ b/tests/frontend/specs/delete.js @@ -1,36 +1,36 @@ -describe("delete keystroke", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('delete keystroke', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("makes text delete", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text delete', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); // get the original length of this element - var elementLength = $firstTextElement.text().length; + const elementLength = $firstTextElement.text().length; // get the original string value minus the last char - var originalTextValue = $firstTextElement.text(); - var originalTextValueMinusFirstChar = originalTextValue.substring(1, originalTextValue.length ); + const originalTextValue = $firstTextElement.text(); + const originalTextValueMinusFirstChar = originalTextValue.substring(1, originalTextValue.length); // simulate key presses to delete content $firstTextElement.sendkeys('{leftarrow}'); // simulate a keypress of the left arrow key $firstTextElement.sendkeys('{del}'); // simulate a keypress of delete - //ace creates a new dom element when you press a keystroke, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); + // ace creates a new dom element when you press a keystroke, so just get the first text element again + const $newFirstTextElement = inner$('div').first(); // get the new length of this element - var newElementLength = $newFirstTextElement.text().length; + const newElementLength = $newFirstTextElement.text().length; - //expect it to be one char less in length - expect(newElementLength).to.be((elementLength-1)); + // expect it to be one char less in length + expect(newElementLength).to.be((elementLength - 1)); done(); }); diff --git a/tests/frontend/specs/drag_and_drop.js b/tests/frontend/specs/drag_and_drop.js index 821d3aacc..a9726111c 100644 --- a/tests/frontend/specs/drag_and_drop.js +++ b/tests/frontend/specs/drag_and_drop.js @@ -1,39 +1,39 @@ // WARNING: drag and drop is only simulated on these tests, so manual testing might also be necessary -describe('drag and drop', function() { - before(function(done) { - helper.newPad(function() { +describe('drag and drop', function () { + before(function (done) { + helper.newPad(() => { createScriptWithSeveralLines(done); }); this.timeout(60000); }); - context('when user drags part of one line and drops it far form its original place', function() { - before(function(done) { + context('when user drags part of one line and drops it far form its original place', function () { + before(function (done) { selectPartOfSourceLine(); dragSelectedTextAndDropItIntoMiddleOfLine(TARGET_LINE); // make sure DnD was correctly simulated - helper.waitFor(function() { - var $targetLine = getLine(TARGET_LINE); - var sourceWasMovedToTarget = $targetLine.text() === 'Target line [line 1]'; + helper.waitFor(() => { + const $targetLine = getLine(TARGET_LINE); + const sourceWasMovedToTarget = $targetLine.text() === 'Target line [line 1]'; return sourceWasMovedToTarget; }).done(done); }); - context('and user triggers UNDO', function() { - before(function() { - var $undoButton = helper.padChrome$(".buttonicon-undo"); + context('and user triggers UNDO', function () { + before(function () { + const $undoButton = helper.padChrome$('.buttonicon-undo'); $undoButton.click(); }); - it('moves text back to its original place', function(done) { + it('moves text back to its original place', function (done) { // test text was removed from drop target - var $targetLine = getLine(TARGET_LINE); + const $targetLine = getLine(TARGET_LINE); expect($targetLine.text()).to.be('Target line []'); // test text was added back to original place - var $firstSourceLine = getLine(FIRST_SOURCE_LINE); - var $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); + const $firstSourceLine = getLine(FIRST_SOURCE_LINE); + const $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); expect($firstSourceLine.text()).to.be('Source line 1.'); expect($lastSourceLine.text()).to.be('Source line 2.'); @@ -42,33 +42,33 @@ describe('drag and drop', function() { }); }); - context('when user drags some lines far form its original place', function() { - before(function(done) { + context('when user drags some lines far form its original place', function () { + before(function (done) { selectMultipleSourceLines(); dragSelectedTextAndDropItIntoMiddleOfLine(TARGET_LINE); // make sure DnD was correctly simulated - helper.waitFor(function() { - var $lineAfterTarget = getLine(TARGET_LINE + 1); - var sourceWasMovedToTarget = $lineAfterTarget.text() !== '...'; + helper.waitFor(() => { + const $lineAfterTarget = getLine(TARGET_LINE + 1); + const sourceWasMovedToTarget = $lineAfterTarget.text() !== '...'; return sourceWasMovedToTarget; }).done(done); }); - context('and user triggers UNDO', function() { - before(function() { - var $undoButton = helper.padChrome$(".buttonicon-undo"); + context('and user triggers UNDO', function () { + before(function () { + const $undoButton = helper.padChrome$('.buttonicon-undo'); $undoButton.click(); }); - it('moves text back to its original place', function(done) { + it('moves text back to its original place', function (done) { // test text was removed from drop target - var $targetLine = getLine(TARGET_LINE); + const $targetLine = getLine(TARGET_LINE); expect($targetLine.text()).to.be('Target line []'); // test text was added back to original place - var $firstSourceLine = getLine(FIRST_SOURCE_LINE); - var $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); + const $firstSourceLine = getLine(FIRST_SOURCE_LINE); + const $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); expect($firstSourceLine.text()).to.be('Source line 1.'); expect($lastSourceLine.text()).to.be('Source line 2.'); @@ -81,88 +81,88 @@ describe('drag and drop', function() { var TARGET_LINE = 2; var FIRST_SOURCE_LINE = 5; - var getLine = function(lineNumber) { - var $lines = helper.padInner$('div'); + var getLine = function (lineNumber) { + const $lines = helper.padInner$('div'); return $lines.slice(lineNumber, lineNumber + 1); - } + }; - var createScriptWithSeveralLines = function(done) { + var createScriptWithSeveralLines = function (done) { // create some lines to be used on the tests - var $firstLine = helper.padInner$('div').first(); + const $firstLine = helper.padInner$('div').first(); $firstLine.html('...
        ...
        Target line []
        ...
        ...
        Source line 1.
        Source line 2.
        '); // wait for lines to be split - helper.waitFor(function(){ - var $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); + helper.waitFor(() => { + const $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); return $lastSourceLine.text() === 'Source line 2.'; }).done(done); - } + }; - var selectPartOfSourceLine = function() { - var $sourceLine = getLine(FIRST_SOURCE_LINE); + var selectPartOfSourceLine = function () { + const $sourceLine = getLine(FIRST_SOURCE_LINE); // select 'line 1' from 'Source line 1.' - var start = 'Source '.length; - var end = start + 'line 1'.length; + const start = 'Source '.length; + const end = start + 'line 1'.length; helper.selectLines($sourceLine, $sourceLine, start, end); - } - var selectMultipleSourceLines = function() { - var $firstSourceLine = getLine(FIRST_SOURCE_LINE); - var $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); + }; + var selectMultipleSourceLines = function () { + const $firstSourceLine = getLine(FIRST_SOURCE_LINE); + const $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); helper.selectLines($firstSourceLine, $lastSourceLine); - } + }; - var dragSelectedTextAndDropItIntoMiddleOfLine = function(targetLineNumber) { + var dragSelectedTextAndDropItIntoMiddleOfLine = function (targetLineNumber) { // dragstart: start dragging content triggerEvent('dragstart'); // drop: get HTML data from selected text - var draggedHtml = getHtmlFromSelectedText(); + const draggedHtml = getHtmlFromSelectedText(); triggerEvent('drop'); // dragend: remove original content + insert HTML data into target moveSelectionIntoTarget(draggedHtml, targetLineNumber); triggerEvent('dragend'); - } + }; - var getHtmlFromSelectedText = function() { - var innerDocument = helper.padInner$.document; + var getHtmlFromSelectedText = function () { + const innerDocument = helper.padInner$.document; - var range = innerDocument.getSelection().getRangeAt(0); - var clonedSelection = range.cloneContents(); - var span = innerDocument.createElement('span'); + const range = innerDocument.getSelection().getRangeAt(0); + const clonedSelection = range.cloneContents(); + const span = innerDocument.createElement('span'); span.id = 'buffer'; span.appendChild(clonedSelection); - var draggedHtml = span.outerHTML; + const draggedHtml = span.outerHTML; return draggedHtml; - } + }; - var triggerEvent = function(eventName) { - var event = helper.padInner$.Event(eventName); + var triggerEvent = function (eventName) { + const event = helper.padInner$.Event(eventName); helper.padInner$('#innerdocbody').trigger(event); - } + }; - var moveSelectionIntoTarget = function(draggedHtml, targetLineNumber) { - var innerDocument = helper.padInner$.document; + var moveSelectionIntoTarget = function (draggedHtml, targetLineNumber) { + const innerDocument = helper.padInner$.document; // delete original content innerDocument.execCommand('delete'); // set position to insert content on target line - var $target = getLine(targetLineNumber); + const $target = getLine(targetLineNumber); $target.sendkeys('{selectall}{rightarrow}{leftarrow}'); // Insert content. // Based on http://stackoverflow.com/a/6691294, to be IE-compatible - var range = innerDocument.getSelection().getRangeAt(0); - var frag = innerDocument.createDocumentFragment(); - var el = innerDocument.createElement('div'); + const range = innerDocument.getSelection().getRangeAt(0); + const frag = innerDocument.createDocumentFragment(); + const el = innerDocument.createElement('div'); el.innerHTML = draggedHtml; while (el.firstChild) { frag.appendChild(el.firstChild); } range.insertNode(frag); - } + }; }); diff --git a/tests/frontend/specs/embed_value.js b/tests/frontend/specs/embed_value.js index a0e056412..d6fb8c977 100644 --- a/tests/frontend/specs/embed_value.js +++ b/tests/frontend/specs/embed_value.js @@ -1,135 +1,133 @@ -describe("embed links", function(){ - var objectify = function (str) { - var hash = {}; - var parts = str.split('&'); - for(var i = 0; i < parts.length; i++) - { - var keyValue = parts[i].split('='); +describe('embed links', function () { + const objectify = function (str) { + const hash = {}; + const parts = str.split('&'); + for (let i = 0; i < parts.length; i++) { + const keyValue = parts[i].split('='); hash[keyValue[0]] = keyValue[1]; } return hash; - } + }; - var checkiFrameCode = function(embedCode, readonly){ - //turn the code into an html element - var $embediFrame = $(embedCode); + const checkiFrameCode = function (embedCode, readonly) { + // turn the code into an html element + const $embediFrame = $(embedCode); - //read and check the frame attributes - var width = $embediFrame.attr("width"); - var height = $embediFrame.attr("height"); - var name = $embediFrame.attr("name"); + // read and check the frame attributes + const width = $embediFrame.attr('width'); + const height = $embediFrame.attr('height'); + const name = $embediFrame.attr('name'); expect(width).to.be('100%'); expect(height).to.be('600'); - expect(name).to.be(readonly ? "embed_readonly" : "embed_readwrite"); + expect(name).to.be(readonly ? 'embed_readonly' : 'embed_readwrite'); - //parse the url - var src = $embediFrame.attr("src"); - var questionMark = src.indexOf("?"); - var url = src.substr(0,questionMark); - var paramsStr = src.substr(questionMark+1); - var params = objectify(paramsStr); + // parse the url + const src = $embediFrame.attr('src'); + const questionMark = src.indexOf('?'); + const url = src.substr(0, questionMark); + const paramsStr = src.substr(questionMark + 1); + const params = objectify(paramsStr); - var expectedParams = { - showControls: 'true' - , showChat: 'true' - , showLineNumbers: 'true' - , useMonospaceFont: 'false' - } + const expectedParams = { + showControls: 'true', + showChat: 'true', + showLineNumbers: 'true', + useMonospaceFont: 'false', + }; - //check the url - if(readonly){ - expect(url.indexOf("r.") > 0).to.be(true); + // check the url + if (readonly) { + expect(url.indexOf('r.') > 0).to.be(true); } else { expect(url).to.be(helper.padChrome$.window.location.href); } - //check if all parts of the url are like expected + // check if all parts of the url are like expected expect(params).to.eql(expectedParams); - } + }; - describe("read and write", function(){ - //create a new pad before each test run - beforeEach(function(cb){ + describe('read and write', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - describe("the share link", function(){ - it("is the actual pad url", function(done){ - var chrome$ = helper.padChrome$; + describe('the share link', function () { + it('is the actual pad url', function (done) { + const chrome$ = helper.padChrome$; - //open share dropdown - chrome$(".buttonicon-embed").click(); + // open share dropdown + chrome$('.buttonicon-embed').click(); - //get the link of the share field + the actual pad url and compare them - var shareLink = chrome$("#linkinput").val(); - var padURL = chrome$.window.location.href; + // get the link of the share field + the actual pad url and compare them + const shareLink = chrome$('#linkinput').val(); + const padURL = chrome$.window.location.href; expect(shareLink).to.be(padURL); done(); }); }); - describe("the embed as iframe code", function(){ - it("is an iframe with the the correct url parameters and correct size", function(done){ - var chrome$ = helper.padChrome$; + describe('the embed as iframe code', function () { + it('is an iframe with the the correct url parameters and correct size', function (done) { + const chrome$ = helper.padChrome$; - //open share dropdown - chrome$(".buttonicon-embed").click(); + // open share dropdown + chrome$('.buttonicon-embed').click(); - //get the link of the share field + the actual pad url and compare them - var embedCode = chrome$("#embedinput").val(); + // get the link of the share field + the actual pad url and compare them + const embedCode = chrome$('#embedinput').val(); - checkiFrameCode(embedCode, false) + checkiFrameCode(embedCode, false); done(); }); }); }); - describe("when read only option is set", function(){ - beforeEach(function(cb){ + describe('when read only option is set', function () { + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - describe("the share link", function(){ - it("shows a read only url", function(done){ - var chrome$ = helper.padChrome$; + describe('the share link', function () { + it('shows a read only url', function (done) { + const chrome$ = helper.padChrome$; - //open share dropdown - chrome$(".buttonicon-embed").click(); + // open share dropdown + chrome$('.buttonicon-embed').click(); chrome$('#readonlyinput').click(); chrome$('#readonlyinput:checkbox:not(:checked)').attr('checked', 'checked'); - //get the link of the share field + the actual pad url and compare them - var shareLink = chrome$("#linkinput").val(); - var containsReadOnlyLink = shareLink.indexOf("r.") > 0 + // get the link of the share field + the actual pad url and compare them + const shareLink = chrome$('#linkinput').val(); + const containsReadOnlyLink = shareLink.indexOf('r.') > 0; expect(containsReadOnlyLink).to.be(true); done(); }); }); - describe("the embed as iframe code", function(){ - it("is an iframe with the the correct url parameters and correct size", function(done){ - var chrome$ = helper.padChrome$; + describe('the embed as iframe code', function () { + it('is an iframe with the the correct url parameters and correct size', function (done) { + const chrome$ = helper.padChrome$; - //open share dropdown - chrome$(".buttonicon-embed").click(); - //check read only checkbox, a bit hacky + // open share dropdown + chrome$('.buttonicon-embed').click(); + // check read only checkbox, a bit hacky chrome$('#readonlyinput').click(); chrome$('#readonlyinput:checkbox:not(:checked)').attr('checked', 'checked'); - //get the link of the share field + the actual pad url and compare them - var embedCode = chrome$("#embedinput").val(); + // get the link of the share field + the actual pad url and compare them + const embedCode = chrome$('#embedinput').val(); checkiFrameCode(embedCode, true); done(); }); }); - }); }); diff --git a/tests/frontend/specs/enter.js b/tests/frontend/specs/enter.js index 9c3457b02..6108d7f82 100644 --- a/tests/frontend/specs/enter.js +++ b/tests/frontend/specs/enter.js @@ -1,32 +1,30 @@ -describe("enter keystroke", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('enter keystroke', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("creates a new line & puts cursor onto a new line", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('creates a new line & puts cursor onto a new line', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); // get the original string value minus the last char - var originalTextValue = $firstTextElement.text(); + const originalTextValue = $firstTextElement.text(); // simulate key presses to enter content $firstTextElement.sendkeys('{enter}'); - //ace creates a new dom element when you press a keystroke, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); + // ace creates a new dom element when you press a keystroke, so just get the first text element again + const $newFirstTextElement = inner$('div').first(); - helper.waitFor(function(){ - return inner$("div").first().text() === ""; - }).done(function(){ - var $newSecondLine = inner$("div").first().next(); - var newFirstTextElementValue = inner$("div").first().text(); - expect(newFirstTextElementValue).to.be(""); // expect the first line to be blank + helper.waitFor(() => inner$('div').first().text() === '').done(() => { + const $newSecondLine = inner$('div').first().next(); + const newFirstTextElementValue = inner$('div').first().text(); + expect(newFirstTextElementValue).to.be(''); // expect the first line to be blank expect($newSecondLine.text()).to.be(originalTextValue); // expect the second line to be the same as the original first line. done(); }); diff --git a/tests/frontend/specs/font_type.js b/tests/frontend/specs/font_type.js index ad220d882..51971da39 100644 --- a/tests/frontend/specs/font_type.js +++ b/tests/frontend/specs/font_type.js @@ -1,31 +1,31 @@ -describe("font select", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('font select', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("makes text RobotoMono", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text RobotoMono', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); + // click on the settings button to make settings visible + const $settingsButton = chrome$('.buttonicon-settings'); $settingsButton.click(); - //get the font menu and RobotoMono option - var $viewfontmenu = chrome$("#viewfontmenu"); - var $RobotoMonooption = $viewfontmenu.find("[value=RobotoMono]"); + // get the font menu and RobotoMono option + const $viewfontmenu = chrome$('#viewfontmenu'); + const $RobotoMonooption = $viewfontmenu.find('[value=RobotoMono]'); - //select RobotoMono and fire change event + // select RobotoMono and fire change event // $RobotoMonooption.attr('selected','selected'); // commenting out above will break safari test - $viewfontmenu.val("RobotoMono"); + $viewfontmenu.val('RobotoMono'); $viewfontmenu.change(); - //check if font changed to RobotoMono - var fontFamily = inner$("body").css("font-family").toLowerCase(); - var containsStr = fontFamily.indexOf("robotomono"); + // check if font changed to RobotoMono + const fontFamily = inner$('body').css('font-family').toLowerCase(); + const containsStr = fontFamily.indexOf('robotomono'); expect(containsStr).to.not.be(-1); done(); diff --git a/tests/frontend/specs/helper.js b/tests/frontend/specs/helper.js index e6b06412d..6bc6a3643 100644 --- a/tests/frontend/specs/helper.js +++ b/tests/frontend/specs/helper.js @@ -1,34 +1,34 @@ -describe("the test helper", function(){ - describe("the newPad method", function(){ - xit("doesn't leak memory if you creates iframes over and over again", function(done){ +describe('the test helper', function () { + describe('the newPad method', function () { + xit("doesn't leak memory if you creates iframes over and over again", function (done) { this.timeout(100000); - var times = 10; + let times = 10; - var loadPad = function(){ - helper.newPad(function(){ + var loadPad = function () { + helper.newPad(() => { times--; - if(times > 0){ + if (times > 0) { loadPad(); } else { done(); } - }) - } + }); + }; loadPad(); }); - it("gives me 3 jquery instances of chrome, outer and inner", function(done){ + it('gives me 3 jquery instances of chrome, outer and inner', function (done) { this.timeout(10000); - helper.newPad(function(){ - //check if the jquery selectors have the desired elements - expect(helper.padChrome$("#editbar").length).to.be(1); - expect(helper.padOuter$("#outerdocbody").length).to.be(1); - expect(helper.padInner$("#innerdocbody").length).to.be(1); + helper.newPad(() => { + // check if the jquery selectors have the desired elements + expect(helper.padChrome$('#editbar').length).to.be(1); + expect(helper.padOuter$('#outerdocbody').length).to.be(1); + expect(helper.padInner$('#innerdocbody').length).to.be(1); - //check if the document object was set correctly + // check if the document object was set correctly expect(helper.padChrome$.window.document).to.be(helper.padChrome$.document); expect(helper.padOuter$.window.document).to.be(helper.padOuter$.document); expect(helper.padInner$.window.document).to.be(helper.padInner$.document); @@ -43,7 +43,7 @@ describe("the test helper", function(){ // However this doesn't seem to always be easily replicated, so this // timeout may or may end up in the code. None the less, we test here // to catch it if the bug comes up again. - it("clears cookies", function(done) { + it('clears cookies', function (done) { this.timeout(60000); // set cookies far into the future to make sure they're not expired yet @@ -53,20 +53,20 @@ describe("the test helper", function(){ expect(window.document.cookie).to.contain('token=foo'); expect(window.document.cookie).to.contain('language=bar'); - helper.newPad(function(){ + helper.newPad(() => { // helper function seems to have cleared cookies // NOTE: this doesn't yet mean it's proven to have taken effect by this point in execution - var firstCookie = window.document.cookie + const firstCookie = window.document.cookie; expect(firstCookie).to.not.contain('token=foo'); expect(firstCookie).to.not.contain('language=bar'); - var chrome$ = helper.padChrome$; + const chrome$ = helper.padChrome$; // click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); + const $userButton = chrome$('.buttonicon-showusers'); $userButton.click(); - var $usernameInput = chrome$("#myusernameedit"); + const $usernameInput = chrome$('#myusernameedit'); $usernameInput.click(); $usernameInput.val('John McLear'); @@ -84,9 +84,9 @@ describe("the test helper", function(){ // be sure. expect(window.document.cookie).to.not.contain('prefsHtml=baz'); - setTimeout(function(){ //give it a second to save the username on the server side - helper.newPad(function(){ // get a new pad, let it clear the cookies - var chrome$ = helper.padChrome$; + setTimeout(() => { // give it a second to save the username on the server side + helper.newPad(() => { // get a new pad, let it clear the cookies + const chrome$ = helper.padChrome$; // helper function seems to have cleared cookies // NOTE: this doesn't yet mean cookies were cleared effectively. @@ -99,11 +99,11 @@ describe("the test helper", function(){ expect(window.document.cookie).to.not.be(firstCookie); // click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); + const $userButton = chrome$('.buttonicon-showusers'); $userButton.click(); // confirm that the session was actually cleared - var $usernameInput = chrome$("#myusernameedit"); + const $usernameInput = chrome$('#myusernameedit'); expect($usernameInput.val()).to.be(''); done(); @@ -112,43 +112,41 @@ describe("the test helper", function(){ }); }); - it("sets pad prefs cookie", function(done) { + it('sets pad prefs cookie', function (done) { this.timeout(60000); helper.newPad({ - padPrefs: {foo:"bar"}, - cb: function(){ - var chrome$ = helper.padChrome$; + padPrefs: {foo: 'bar'}, + cb() { + const chrome$ = helper.padChrome$; expect(chrome$.document.cookie).to.contain('prefsHttp=%7B%22'); expect(chrome$.document.cookie).to.contain('foo%22%3A%22bar'); done(); - } + }, }); }); }); - describe("the waitFor method", function(){ - it("takes a timeout and waits long enough", function(done){ + describe('the waitFor method', function () { + it('takes a timeout and waits long enough', function (done) { this.timeout(2000); - var startTime = Date.now(); + const startTime = Date.now(); - helper.waitFor(function(){ - return false; - }, 1500).fail(function(){ - var duration = Date.now() - startTime; + helper.waitFor(() => false, 1500).fail(() => { + const duration = Date.now() - startTime; expect(duration).to.be.greaterThan(1490); done(); }); }); - it("takes an interval and checks on every interval", function(done){ + it('takes an interval and checks on every interval', function (done) { this.timeout(4000); - var checks = 0; + let checks = 0; - helper.waitFor(function(){ + helper.waitFor(() => { checks++; return false; - }, 2000, 100).fail(function(){ + }, 2000, 100).fail(() => { // One at the beginning, and 19-20 more depending on whether it's the timeout or the final // poll that wins at 2000ms. expect(checks).to.be.greaterThan(15); @@ -157,7 +155,7 @@ describe("the test helper", function(){ }); }); - it('rejects if the predicate throws', async function() { + it('rejects if the predicate throws', async function () { let err; await helper.waitFor(() => { throw new Error('test exception'); }) .fail(() => {}) // Suppress the redundant uncatchable exception. @@ -166,44 +164,38 @@ describe("the test helper", function(){ expect(err.message).to.be('test exception'); }); - describe("returns a deferred object", function(){ - it("it calls done after success", function(done){ - helper.waitFor(function(){ - return true; - }).done(function(){ + describe('returns a deferred object', function () { + it('it calls done after success', function (done) { + helper.waitFor(() => true).done(() => { done(); }); }); - it("calls fail after failure", function(done){ - helper.waitFor(function(){ - return false; - },0).fail(function(){ + it('calls fail after failure', function (done) { + helper.waitFor(() => false, 0).fail(() => { done(); }); }); - xit("throws if you don't listen for fails", function(done){ - var onerror = window.onerror; - window.onerror = function(){ + xit("throws if you don't listen for fails", function (done) { + const onerror = window.onerror; + window.onerror = function () { window.onerror = onerror; done(); - } + }; - helper.waitFor(function(){ - return false; - },100); + helper.waitFor(() => false, 100); }); }); - describe('checks first then sleeps', function() { - it('resolves quickly if the predicate is immediately true', async function() { + describe('checks first then sleeps', function () { + it('resolves quickly if the predicate is immediately true', async function () { const before = Date.now(); await helper.waitFor(() => true, 1000, 900); expect(Date.now() - before).to.be.lessThan(800); }); - it('polls exactly once if timeout < interval', async function() { + it('polls exactly once if timeout < interval', async function () { let calls = 0; await helper.waitFor(() => { calls++; }, 1, 1000) .fail(() => {}) // Suppress the redundant uncatchable exception. @@ -211,18 +203,18 @@ describe("the test helper", function(){ expect(calls).to.be(1); }); - it('resolves if condition is immediately true even if timeout is 0', async function() { + it('resolves if condition is immediately true even if timeout is 0', async function () { await helper.waitFor(() => true, 0); }); }); }); - describe('the waitForPromise method', function() { - it('returns a Promise', async function() { + describe('the waitForPromise method', function () { + it('returns a Promise', async function () { expect(helper.waitForPromise(() => true)).to.be.a(Promise); }); - it('takes a timeout and waits long enough', async function() { + it('takes a timeout and waits long enough', async function () { this.timeout(2000); const startTime = Date.now(); let rejected; @@ -233,60 +225,60 @@ describe("the test helper", function(){ expect(duration).to.be.greaterThan(1490); }); - it('takes an interval and checks on every interval', async function() { + it('takes an interval and checks on every interval', async function () { this.timeout(4000); let checks = 0; let rejected; await helper.waitForPromise(() => { checks++; return false; }, 2000, 100) .catch(() => { rejected = true; }); expect(rejected).to.be(true); - // `checks` is expected to be 20 or 21: one at the beginning, plus 19 or 20 more depending on - // whether it's the timeout or the final poll that wins at 2000ms. Margin is added to reduce - // flakiness on slow test machines. + // `checks` is expected to be 20 or 21: one at the beginning, plus 19 or 20 more depending on + // whether it's the timeout or the final poll that wins at 2000ms. Margin is added to reduce + // flakiness on slow test machines. expect(checks).to.be.greaterThan(15); expect(checks).to.be.lessThan(24); }); }); - describe("the selectLines method", function(){ + describe('the selectLines method', function () { // function to support tests, use a single way to represent whitespaces - var cleanText = function(text){ + const cleanText = function (text) { return text // IE replaces line breaks with a whitespace, so we need to unify its behavior // for other browsers, to have all tests running for all browsers - .replace(/\n/gi, "") - .replace(/\s/gi, " "); - } + .replace(/\n/gi, '') + .replace(/\s/gi, ' '); + }; - before(function(done){ - helper.newPad(function() { + before(function (done) { + helper.newPad(() => { // create some lines to be used on the tests - var $firstLine = helper.padInner$("div").first(); - $firstLine.sendkeys("{selectall}some{enter}short{enter}lines{enter}to test{enter}{enter}"); + const $firstLine = helper.padInner$('div').first(); + $firstLine.sendkeys('{selectall}some{enter}short{enter}lines{enter}to test{enter}{enter}'); // wait for lines to be split - helper.waitFor(function(){ - var $fourthLine = helper.padInner$("div").eq(3); - return $fourthLine.text() === "to test"; + helper.waitFor(() => { + const $fourthLine = helper.padInner$('div').eq(3); + return $fourthLine.text() === 'to test'; }).done(done); }); this.timeout(60000); }); - it("changes editor selection to be between startOffset of $startLine and endOffset of $endLine", function(done){ - var inner$ = helper.padInner$; + it('changes editor selection to be between startOffset of $startLine and endOffset of $endLine', function (done) { + const inner$ = helper.padInner$; - var startOffset = 2; - var endOffset = 4; + const startOffset = 2; + const endOffset = 4; - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(3); + const $lines = inner$('div'); + const $startLine = $lines.eq(1); + const $endLine = $lines.eq(3); helper.selectLines($startLine, $endLine, startOffset, endOffset); - var selection = inner$.document.getSelection(); + const selection = inner$.document.getSelection(); /* * replace() is required here because Firefox keeps the line breaks. @@ -295,24 +287,24 @@ describe("the test helper", function(){ * is not consistent between browsers but that's the situation so that's * how I'm covering it in this test. */ - expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("ort lines to t"); + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm, ''))).to.be('ort lines to t'); done(); }); - it("ends selection at beginning of $endLine when it is an empty line", function(done){ - var inner$ = helper.padInner$; + it('ends selection at beginning of $endLine when it is an empty line', function (done) { + const inner$ = helper.padInner$; - var startOffset = 2; - var endOffset = 1; + const startOffset = 2; + const endOffset = 1; - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(4); + const $lines = inner$('div'); + const $startLine = $lines.eq(1); + const $endLine = $lines.eq(4); helper.selectLines($startLine, $endLine, startOffset, endOffset); - var selection = inner$.document.getSelection(); + const selection = inner$.document.getSelection(); /* * replace() is required here because Firefox keeps the line breaks. @@ -321,24 +313,24 @@ describe("the test helper", function(){ * is not consistent between browsers but that's the situation so that's * how I'm covering it in this test. */ - expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("ort lines to test"); + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm, ''))).to.be('ort lines to test'); done(); }); - it("ends selection at beginning of $endLine when its offset is zero", function(done){ - var inner$ = helper.padInner$; + it('ends selection at beginning of $endLine when its offset is zero', function (done) { + const inner$ = helper.padInner$; - var startOffset = 2; - var endOffset = 0; + const startOffset = 2; + const endOffset = 0; - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(3); + const $lines = inner$('div'); + const $startLine = $lines.eq(1); + const $endLine = $lines.eq(3); helper.selectLines($startLine, $endLine, startOffset, endOffset); - var selection = inner$.document.getSelection(); + const selection = inner$.document.getSelection(); /* * replace() is required here because Firefox keeps the line breaks. @@ -347,24 +339,24 @@ describe("the test helper", function(){ * is not consistent between browsers but that's the situation so that's * how I'm covering it in this test. */ - expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("ort lines "); + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm, ''))).to.be('ort lines '); done(); }); - it("selects full line when offset is longer than line content", function(done){ - var inner$ = helper.padInner$; + it('selects full line when offset is longer than line content', function (done) { + const inner$ = helper.padInner$; - var startOffset = 2; - var endOffset = 50; + const startOffset = 2; + const endOffset = 50; - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(3); + const $lines = inner$('div'); + const $startLine = $lines.eq(1); + const $endLine = $lines.eq(3); helper.selectLines($startLine, $endLine, startOffset, endOffset); - var selection = inner$.document.getSelection(); + const selection = inner$.document.getSelection(); /* * replace() is required here because Firefox keeps the line breaks. @@ -373,21 +365,21 @@ describe("the test helper", function(){ * is not consistent between browsers but that's the situation so that's * how I'm covering it in this test. */ - expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("ort lines to test"); + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm, ''))).to.be('ort lines to test'); done(); }); - it("selects all text between beginning of $startLine and end of $endLine when no offset is provided", function(done){ - var inner$ = helper.padInner$; + it('selects all text between beginning of $startLine and end of $endLine when no offset is provided', function (done) { + const inner$ = helper.padInner$; - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(3); + const $lines = inner$('div'); + const $startLine = $lines.eq(1); + const $endLine = $lines.eq(3); helper.selectLines($startLine, $endLine); - var selection = inner$.document.getSelection(); + const selection = inner$.document.getSelection(); /* * replace() is required here because Firefox keeps the line breaks. @@ -396,73 +388,73 @@ describe("the test helper", function(){ * is not consistent between browsers but that's the situation so that's * how I'm covering it in this test. */ - expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("short lines to test"); + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm, ''))).to.be('short lines to test'); done(); }); }); - describe('helper',function(){ - before(function(cb){ - helper.newPad(function(){ + describe('helper', function () { + before(function (cb) { + helper.newPad(() => { cb(); - }) - }) + }); + }); - it(".textLines() returns the text of the pad as strings", async function(){ - let lines = helper.textLines(); - let defaultText = helper.defaultText(); + it('.textLines() returns the text of the pad as strings', async function () { + const lines = helper.textLines(); + const defaultText = helper.defaultText(); expect(Array.isArray(lines)).to.be(true); expect(lines[0]).to.be.an('string'); // @todo // final "\n" is added automatically, but my understanding is this should happen // only when the default text does not end with "\n" already - expect(lines.join("\n")+"\n").to.equal(defaultText); - }) + expect(`${lines.join('\n')}\n`).to.equal(defaultText); + }); - it(".linesDiv() returns the text of the pad as div elements", async function(){ - let lines = helper.linesDiv(); - let defaultText = helper.defaultText(); + it('.linesDiv() returns the text of the pad as div elements', async function () { + const lines = helper.linesDiv(); + const defaultText = helper.defaultText(); expect(Array.isArray(lines)).to.be(true); expect(lines[0]).to.be.an('object'); expect(lines[0].text()).to.be.an('string'); - _.each(defaultText.split("\n"), function(line, index){ - //last line of default text - if(index === lines.length){ + _.each(defaultText.split('\n'), (line, index) => { + // last line of default text + if (index === lines.length) { expect(line).to.equal(''); } else { expect(lines[index].text()).to.equal(line); } - }) - }) + }); + }); - it(".edit() defaults to send an edit to the first line", async function(){ - let firstLine = helper.textLines()[0]; - await helper.edit("line") + it('.edit() defaults to send an edit to the first line', async function () { + const firstLine = helper.textLines()[0]; + await helper.edit('line'); expect(helper.textLines()[0]).to.be(`line${firstLine}`); - }) + }); - it(".edit() to the line specified with parameter lineNo", async function(){ - let firstLine = helper.textLines()[0]; - await helper.edit("second line", 2); + it('.edit() to the line specified with parameter lineNo', async function () { + const firstLine = helper.textLines()[0]; + await helper.edit('second line', 2); - let text = helper.textLines(); + const text = helper.textLines(); expect(text[0]).to.equal(firstLine); - expect(text[1]).to.equal("second line"); - }) + expect(text[1]).to.equal('second line'); + }); - it(".edit() supports sendkeys syntax ({selectall},{del},{enter})", async function(){ + it('.edit() supports sendkeys syntax ({selectall},{del},{enter})', async function () { expect(helper.textLines()[0]).to.not.equal(''); // select first line - helper.linesDiv()[0].sendkeys("{selectall}") + helper.linesDiv()[0].sendkeys('{selectall}'); // delete first line - await helper.edit("{del}") + await helper.edit('{del}'); expect(helper.textLines()[0]).to.be(''); - let noOfLines = helper.textLines().length; - await helper.edit("{enter}") - expect(helper.textLines().length).to.be(noOfLines+1); - }) - }) + const noOfLines = helper.textLines().length; + await helper.edit('{enter}'); + expect(helper.textLines().length).to.be(noOfLines + 1); + }); + }); }); diff --git a/tests/frontend/specs/importexport.js b/tests/frontend/specs/importexport.js index 3466f7cfb..b24622d92 100644 --- a/tests/frontend/specs/importexport.js +++ b/tests/frontend/specs/importexport.js @@ -1,176 +1,162 @@ -describe("import functionality", function(){ - beforeEach(function(cb){ +describe('import functionality', function () { + beforeEach(function (cb) { helper.newPad(cb); // creates a new pad this.timeout(60000); }); - function getinnertext(){ - var inner = helper.padInner$ - if(!inner){ - return "" + function getinnertext() { + const inner = helper.padInner$; + if (!inner) { + return ''; } - var newtext = "" - inner("div").each(function(line,el){ - newtext += el.innerHTML+"\n" - }) - return newtext + let newtext = ''; + inner('div').each((line, el) => { + newtext += `${el.innerHTML}\n`; + }); + return newtext; } - function importrequest(data,importurl,type){ - var success; - var error; - var result = $.ajax({ + function importrequest(data, importurl, type) { + let success; + let error; + const result = $.ajax({ url: importurl, - type: "post", + type: 'post', processData: false, async: false, contentType: 'multipart/form-data; boundary=boundary', accepts: { - text: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + text: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', }, - data: 'Content-Type: multipart/form-data; boundary=--boundary\r\n\r\n--boundary\r\nContent-Disposition: form-data; name="file"; filename="import.'+type+'"\r\nContent-Type: text/plain\r\n\r\n' + data + '\r\n\r\n--boundary', - error: function(res){ - error = res - } - }) - expect(error).to.be(undefined) - return result + data: `Content-Type: multipart/form-data; boundary=--boundary\r\n\r\n--boundary\r\nContent-Disposition: form-data; name="file"; filename="import.${type}"\r\nContent-Type: text/plain\r\n\r\n${data}\r\n\r\n--boundary`, + error(res) { + error = res; + }, + }); + expect(error).to.be(undefined); + return result; } - function exportfunc(link){ - var exportresults = [] + function exportfunc(link) { + const exportresults = []; $.ajaxSetup({ - async:false - }) - $.get(link+"/export/html",function(data){ - var start = data.indexOf("") - var end = data.indexOf("") - var html = data.substr(start+6,end-start-6) - exportresults.push(["html",html]) - }) - $.get(link+"/export/txt",function(data){ - exportresults.push(["txt",data]) - }) - return exportresults + async: false, + }); + $.get(`${link}/export/html`, (data) => { + const start = data.indexOf(''); + const end = data.indexOf(''); + const html = data.substr(start + 6, end - start - 6); + exportresults.push(['html', html]); + }); + $.get(`${link}/export/txt`, (data) => { + exportresults.push(['txt', data]); + }); + return exportresults; } - xit("import a pad with newlines from txt", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var textWithNewLines = 'imported text\nnewline' - importrequest(textWithNewLines,importurl,"txt") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('imported text\nnewline\n
        \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be("imported text
        newline

        ") - expect(results[1][1]).to.be("imported text\nnewline\n\n") - done() - }) - xit("import a pad with newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithNewLines = 'htmltext
        newline' - importrequest(htmlWithNewLines,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('htmltext\nnewline\n
        \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be("htmltext
        newline

        ") - expect(results[1][1]).to.be("htmltext\nnewline\n\n") - done() - }) - xit("import a pad with attributes from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithNewLines = 'htmltext
        newline' - importrequest(htmlWithNewLines,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('htmltext\nnewline\n
        \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('htmltext
        newline

        ') - expect(results[1][1]).to.be('htmltext\nnewline\n\n') - done() - }) - xit("import a pad with bullets from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
        • bullet line 1
        • bullet line 2
          • bullet2 line 1
          • bullet2 line 2
        ' - importrequest(htmlWithBullets,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ + xit('import a pad with newlines from txt', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const textWithNewLines = 'imported text\nnewline'; + importrequest(textWithNewLines, importurl, 'txt'); + helper.waitFor(() => expect(getinnertext()).to.be('imported text\nnewline\n
        \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('imported text
        newline

        '); + expect(results[1][1]).to.be('imported text\nnewline\n\n'); + done(); + }); + xit('import a pad with newlines from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithNewLines = 'htmltext
        newline'; + importrequest(htmlWithNewLines, importurl, 'html'); + helper.waitFor(() => expect(getinnertext()).to.be('htmltext\nnewline\n
        \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('htmltext
        newline

        '); + expect(results[1][1]).to.be('htmltext\nnewline\n\n'); + done(); + }); + xit('import a pad with attributes from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithNewLines = 'htmltext
        newline'; + importrequest(htmlWithNewLines, importurl, 'html'); + helper.waitFor(() => expect(getinnertext()).to.be('htmltext\nnewline\n
        \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('htmltext
        newline

        '); + expect(results[1][1]).to.be('htmltext\nnewline\n\n'); + done(); + }); + xit('import a pad with bullets from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithBullets = '
        • bullet line 1
        • bullet line 2
          • bullet2 line 1
          • bullet2 line 2
        '; + importrequest(htmlWithBullets, importurl, 'html'); + helper.waitFor(() => expect(getinnertext()).to.be('\
        • bullet line 1
        \n\
        • bullet line 2
        \n\
        • bullet2 line 1
        \n\
        • bullet2 line 2
        \n\ -
        \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        • bullet line 1
        • bullet line 2
          • bullet2 line 1
          • bullet2 line 2

        ') - expect(results[1][1]).to.be('\t* bullet line 1\n\t* bullet line 2\n\t\t* bullet2 line 1\n\t\t* bullet2 line 2\n\n') - done() - }) - xit("import a pad with bullets and newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

          • bullet2 line 2
        ' - importrequest(htmlWithBullets,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ +
        \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('
        • bullet line 1
        • bullet line 2
          • bullet2 line 1
          • bullet2 line 2

        '); + expect(results[1][1]).to.be('\t* bullet line 1\n\t* bullet line 2\n\t\t* bullet2 line 1\n\t\t* bullet2 line 2\n\n'); + done(); + }); + xit('import a pad with bullets and newlines from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithBullets = '
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

          • bullet2 line 2
        '; + importrequest(htmlWithBullets, importurl, 'html'); + helper.waitFor(() => expect(getinnertext()).to.be('\
        • bullet line 1
        \n\
        \n\
        • bullet line 2
        \n\
        • bullet2 line 1
        \n\
        \n\
        • bullet2 line 2
        \n\ -
        \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

          • bullet2 line 2

        ') - expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t* bullet2 line 2\n\n') - done() - }) - xit("import a pad with bullets and newlines and attributes from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

              • bullet4 line 2 bisu
              • bullet4 line 2 bs
              • bullet4 line 2 uuis
        ' - importrequest(htmlWithBullets,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ +
        \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

          • bullet2 line 2

        '); + expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t* bullet2 line 2\n\n'); + done(); + }); + xit('import a pad with bullets and newlines and attributes from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithBullets = '
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

              • bullet4 line 2 bisu
              • bullet4 line 2 bs
              • bullet4 line 2 uuis
        '; + importrequest(htmlWithBullets, importurl, 'html'); + helper.waitFor(() => expect(getinnertext()).to.be('\
        • bullet line 1
        \n\
        \n\
        • bullet line 2
        \n\
        • bullet2 line 1
        \n
        \n\
        • bullet4 line 2 bisu
        \n\
        • bullet4 line 2 bs
        \n\
        • bullet4 line 2 uuis
        \n\ -
        \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

              • bullet4 line 2 bisu
              • bullet4 line 2 bs
              • bullet4 line 2 uuis

        ') - expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t\t\t* bullet4 line 2 bisu\n\t\t\t\t* bullet4 line 2 bs\n\t\t\t\t* bullet4 line 2 uuis\n\n') - done() - }) - xit("import a pad with nested bullets from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
        • bullet line 1
        • bullet line 2
          • bullet2 line 1
              • bullet4 line 2
              • bullet4 line 2
              • bullet4 line 2
            • bullet3 line 1
        • bullet2 line 1
        ' - importrequest(htmlWithBullets,importurl,"html") - var oldtext=getinnertext() - helper.waitFor(function(){ - return oldtext != getinnertext() -// return expect(getinnertext()).to.be('\ -//
        • bullet line 1
        \n\ -//
        • bullet line 2
        \n\ -//
        • bullet2 line 1
        \n\ -//
        • bullet4 line 2
        \n\ -//
        • bullet4 line 2
        \n\ -//
        • bullet4 line 2
        \n\ -//
        \n') - }) +
        \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

              • bullet4 line 2 bisu
              • bullet4 line 2 bs
              • bullet4 line 2 uuis

        '); + expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t\t\t* bullet4 line 2 bisu\n\t\t\t\t* bullet4 line 2 bs\n\t\t\t\t* bullet4 line 2 uuis\n\n'); + done(); + }); + xit('import a pad with nested bullets from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithBullets = '
        • bullet line 1
        • bullet line 2
          • bullet2 line 1
              • bullet4 line 2
              • bullet4 line 2
              • bullet4 line 2
            • bullet3 line 1
        • bullet2 line 1
        '; + importrequest(htmlWithBullets, importurl, 'html'); + const oldtext = getinnertext(); + helper.waitFor(() => oldtext != getinnertext(), + // return expect(getinnertext()).to.be('\ + //
        • bullet line 1
        \n\ + //
        • bullet line 2
        \n\ + //
        • bullet2 line 1
        \n\ + //
        • bullet4 line 2
        \n\ + //
        • bullet4 line 2
        \n\ + //
        • bullet4 line 2
        \n\ + //
        \n') + ); - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        • bullet line 1
        • bullet line 2
          • bullet2 line 1
              • bullet4 line 2
              • bullet4 line 2
              • bullet4 line 2
            • bullet3 line 1
        • bullet2 line 1

        ') - expect(results[1][1]).to.be('\t* bullet line 1\n\t* bullet line 2\n\t\t* bullet2 line 1\n\t\t\t\t* bullet4 line 2\n\t\t\t\t* bullet4 line 2\n\t\t\t\t* bullet4 line 2\n\t\t\t* bullet3 line 1\n\t* bullet2 line 1\n\n') - done() - }) - xit("import a pad with 8 levels of bullets and newlines and attributes from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

              • bullet4 line 2 bisu
              • bullet4 line 2 bs
              • bullet4 line 2 uuis
                      • foo
                      • foobar bs
                • foobar
          ' - importrequest(htmlWithBullets,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('
          • bullet line 1
          • bullet line 2
            • bullet2 line 1
                • bullet4 line 2
                • bullet4 line 2
                • bullet4 line 2
              • bullet3 line 1
          • bullet2 line 1

          '); + expect(results[1][1]).to.be('\t* bullet line 1\n\t* bullet line 2\n\t\t* bullet2 line 1\n\t\t\t\t* bullet4 line 2\n\t\t\t\t* bullet4 line 2\n\t\t\t\t* bullet4 line 2\n\t\t\t* bullet3 line 1\n\t* bullet2 line 1\n\n'); + done(); + }); + xit('import a pad with 8 levels of bullets and newlines and attributes from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithBullets = '
          • bullet line 1

          • bullet line 2
            • bullet2 line 1

                • bullet4 line 2 bisu
                • bullet4 line 2 bs
                • bullet4 line 2 uuis
                        • foo
                        • foobar bs
                  • foobar
            '; + importrequest(htmlWithBullets, importurl, 'html'); + helper.waitFor(() => expect(getinnertext()).to.be('\
            • bullet line 1
            \n\
            \n\
            • bullet line 2
            \n\
            • bullet2 line 1
            \n
            \n\ @@ -180,32 +166,31 @@ describe("import functionality", function(){
            • foo
            \n\
            • foobar bs
            \n\
            • foobar
            \n\ -
            \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
            • bullet line 1

            • bullet line 2
              • bullet2 line 1

                  • bullet4 line 2 bisu
                  • bullet4 line 2 bs
                  • bullet4 line 2 uuis
                          • foo
                          • foobar bs
                    • foobar

            ') - expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t\t\t* bullet4 line 2 bisu\n\t\t\t\t* bullet4 line 2 bs\n\t\t\t\t* bullet4 line 2 uuis\n\t\t\t\t\t\t\t\t* foo\n\t\t\t\t\t\t\t\t* foobar bs\n\t\t\t\t\t* foobar\n\n') - done() - }) +
            \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('
            • bullet line 1

            • bullet line 2
              • bullet2 line 1

                  • bullet4 line 2 bisu
                  • bullet4 line 2 bs
                  • bullet4 line 2 uuis
                          • foo
                          • foobar bs
                    • foobar

            '); + expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t\t\t* bullet4 line 2 bisu\n\t\t\t\t* bullet4 line 2 bs\n\t\t\t\t* bullet4 line 2 uuis\n\t\t\t\t\t\t\t\t* foo\n\t\t\t\t\t\t\t\t* foobar bs\n\t\t\t\t\t* foobar\n\n'); + done(); + }); - xit("import a pad with ordered lists from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
            1. number 1 line 1
            1. number 2 line 2
            ' - importrequest(htmlWithBullets,importurl,"html") - -console.error(getinnertext()) + xit('import a pad with ordered lists from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithBullets = '
            1. number 1 line 1
            1. number 2 line 2
            '; + importrequest(htmlWithBullets, importurl, 'html') - + console.error(getinnertext()); expect(getinnertext()).to.be('\
            1. number 1 line 1
            \n\
            1. number 2 line 2
            \n\ -
            \n') - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
            1. number 1 line 1
            1. number 2 line 2
            ') - expect(results[1][1]).to.be('') - done() - }) - xit("import a pad with ordered lists and newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
            1. number 9 line 1

            1. number 10 line 2
              1. number 2 times line 1

              1. number 2 times line 2
            ' - importrequest(htmlWithBullets,importurl,"html") +
            \n'); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('
            1. number 1 line 1
            1. number 2 line 2
            '); + expect(results[1][1]).to.be(''); + done(); + }); + xit('import a pad with ordered lists and newlines from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithBullets = '
            1. number 9 line 1

            1. number 10 line 2
              1. number 2 times line 1

              1. number 2 times line 2
            '; + importrequest(htmlWithBullets, importurl, 'html'); expect(getinnertext()).to.be('\
            1. number 9 line 1
            \n\
            \n\ @@ -213,15 +198,15 @@ describe("import functionality", function(){
            1. number 2 times line 1
            \n\
            \n\
            1. number 2 times line 2
            \n\ -
            \n') - var results = exportfunc(helper.padChrome$.window.location.href) - console.error(results) - done() - }) - xit("import a pad with nested ordered lists and attributes and newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
            1. bold strikethrough italics underline line 1bold

            1. number 10 line 2
              1. number 2 times line 1

              1. number 2 times line 2
            ' - importrequest(htmlWithBullets,importurl,"html") +
            \n'); + const results = exportfunc(helper.padChrome$.window.location.href); + console.error(results); + done(); + }); + xit('import a pad with nested ordered lists and attributes and newlines from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithBullets = '
            1. bold strikethrough italics underline line 1bold

            1. number 10 line 2
              1. number 2 times line 1

              1. number 2 times line 2
            '; + importrequest(htmlWithBullets, importurl, 'html'); expect(getinnertext()).to.be('\
            1. bold strikethrough italics underline line 1bold
            \n\
            \n\ @@ -229,9 +214,9 @@ describe("import functionality", function(){
            1. number 2 times line 1
            \n\
            \n\
            1. number 2 times line 2
            \n\ -
            \n') - var results = exportfunc(helper.padChrome$.window.location.href) - console.error(results) - done() - }) -}) +
            \n'); + const results = exportfunc(helper.padChrome$.window.location.href); + console.error(results); + done(); + }); +}); diff --git a/tests/frontend/specs/importindents.js b/tests/frontend/specs/importindents.js index 284a90f32..6209236df 100644 --- a/tests/frontend/specs/importindents.js +++ b/tests/frontend/specs/importindents.js @@ -1,97 +1,92 @@ -describe("import indents functionality", function(){ - beforeEach(function(cb){ +describe('import indents functionality', function () { + beforeEach(function (cb) { helper.newPad(cb); // creates a new pad this.timeout(60000); }); - function getinnertext(){ - var inner = helper.padInner$ - var newtext = "" - inner("div").each(function(line,el){ - newtext += el.innerHTML+"\n" - }) - return newtext + function getinnertext() { + const inner = helper.padInner$; + let newtext = ''; + inner('div').each((line, el) => { + newtext += `${el.innerHTML}\n`; + }); + return newtext; } - function importrequest(data,importurl,type){ - var success; - var error; - var result = $.ajax({ + function importrequest(data, importurl, type) { + let success; + let error; + const result = $.ajax({ url: importurl, - type: "post", + type: 'post', processData: false, async: false, contentType: 'multipart/form-data; boundary=boundary', accepts: { - text: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + text: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', }, - data: 'Content-Type: multipart/form-data; boundary=--boundary\r\n\r\n--boundary\r\nContent-Disposition: form-data; name="file"; filename="import.'+type+'"\r\nContent-Type: text/plain\r\n\r\n' + data + '\r\n\r\n--boundary', - error: function(res){ - error = res - } - }) - expect(error).to.be(undefined) - return result + data: `Content-Type: multipart/form-data; boundary=--boundary\r\n\r\n--boundary\r\nContent-Disposition: form-data; name="file"; filename="import.${type}"\r\nContent-Type: text/plain\r\n\r\n${data}\r\n\r\n--boundary`, + error(res) { + error = res; + }, + }); + expect(error).to.be(undefined); + return result; } - function exportfunc(link){ - var exportresults = [] + function exportfunc(link) { + const exportresults = []; $.ajaxSetup({ - async:false - }) - $.get(link+"/export/html",function(data){ - var start = data.indexOf("") - var end = data.indexOf("") - var html = data.substr(start+6,end-start-6) - exportresults.push(["html",html]) - }) - $.get(link+"/export/txt",function(data){ - exportresults.push(["txt",data]) - }) - return exportresults + async: false, + }); + $.get(`${link}/export/html`, (data) => { + const start = data.indexOf(''); + const end = data.indexOf(''); + const html = data.substr(start + 6, end - start - 6); + exportresults.push(['html', html]); + }); + $.get(`${link}/export/txt`, (data) => { + exportresults.push(['txt', data]); + }); + return exportresults; } - xit("import a pad with indents from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithIndents = '
            • indent line 1
            • indent line 2
              • indent2 line 1
              • indent2 line 2
            ' - importrequest(htmlWithIndents,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ + xit('import a pad with indents from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithIndents = '
            • indent line 1
            • indent line 2
              • indent2 line 1
              • indent2 line 2
            '; + importrequest(htmlWithIndents, importurl, 'html'); + helper.waitFor(() => expect(getinnertext()).to.be('\
            • indent line 1
            \n\
            • indent line 2
            \n\
            • indent2 line 1
            \n\
            • indent2 line 2
            \n\ -
            \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
            • indent line 1
            • indent line 2
              • indent2 line 1
              • indent2 line 2

            ') - expect(results[1][1]).to.be('\tindent line 1\n\tindent line 2\n\t\tindent2 line 1\n\t\tindent2 line 2\n\n') - done() - }) +
            \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('
            • indent line 1
            • indent line 2
              • indent2 line 1
              • indent2 line 2

            '); + expect(results[1][1]).to.be('\tindent line 1\n\tindent line 2\n\t\tindent2 line 1\n\t\tindent2 line 2\n\n'); + done(); + }); - xit("import a pad with indented lists and newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithIndents = '
            • indent line 1

            • indent 1 line 2
              • indent 2 times line 1

              • indent 2 times line 2
            ' - importrequest(htmlWithIndents,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ + xit('import a pad with indented lists and newlines from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithIndents = '
            • indent line 1

            • indent 1 line 2
              • indent 2 times line 1

              • indent 2 times line 2
            '; + importrequest(htmlWithIndents, importurl, 'html'); + helper.waitFor(() => expect(getinnertext()).to.be('\
            • indent line 1
            \n\
            \n\
            • indent 1 line 2
            \n\
            • indent 2 times line 1
            \n\
            \n\
            • indent 2 times line 2
            \n\ -
            \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
            • indent line 1

            • indent 1 line 2
              • indent 2 times line 1

              • indent 2 times line 2

            ') - expect(results[1][1]).to.be('\tindent line 1\n\n\tindent 1 line 2\n\t\tindent 2 times line 1\n\n\t\tindent 2 times line 2\n\n') - done() - }) - xit("import a pad with 8 levels of indents and newlines and attributes from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithIndents = '
            • indent line 1

            • indent line 2
              • indent2 line 1

                  • indent4 line 2 bisu
                  • indent4 line 2 bs
                  • indent4 line 2 uuis
                          • foo
                          • foobar bs
                    • foobar
              ' - importrequest(htmlWithIndents,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ +
              \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('
              • indent line 1

              • indent 1 line 2
                • indent 2 times line 1

                • indent 2 times line 2

              '); + expect(results[1][1]).to.be('\tindent line 1\n\n\tindent 1 line 2\n\t\tindent 2 times line 1\n\n\t\tindent 2 times line 2\n\n'); + done(); + }); + xit('import a pad with 8 levels of indents and newlines and attributes from html', function (done) { + const importurl = `${helper.padChrome$.window.location.href}/import`; + const htmlWithIndents = '
              • indent line 1

              • indent line 2
                • indent2 line 1

                    • indent4 line 2 bisu
                    • indent4 line 2 bs
                    • indent4 line 2 uuis
                            • foo
                            • foobar bs
                      • foobar
                '; + importrequest(htmlWithIndents, importurl, 'html'); + helper.waitFor(() => expect(getinnertext()).to.be('\
                • indent line 1
                \n\
                \n\
                • indent line 2
                \n\
                • indent2 line 1
                \n
                \n\ @@ -101,11 +96,10 @@ describe("import indents functionality", function(){
                • foo
                \n\
                • foobar bs
                \n\
                • foobar
                \n\ -
                \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
                • indent line 1

                • indent line 2
                  • indent2 line 1

                      • indent4 line 2 bisu
                      • indent4 line 2 bs
                      • indent4 line 2 uuis
                              • foo
                              • foobar bs
                        • foobar

                ') - expect(results[1][1]).to.be('\tindent line 1\n\n\tindent line 2\n\t\tindent2 line 1\n\n\t\t\t\tindent4 line 2 bisu\n\t\t\t\tindent4 line 2 bs\n\t\t\t\tindent4 line 2 uuis\n\t\t\t\t\t\t\t\tfoo\n\t\t\t\t\t\t\t\tfoobar bs\n\t\t\t\t\tfoobar\n\n') - done() - }) -}) +
                \n')); + const results = exportfunc(helper.padChrome$.window.location.href); + expect(results[0][1]).to.be('
                • indent line 1

                • indent line 2
                  • indent2 line 1

                      • indent4 line 2 bisu
                      • indent4 line 2 bs
                      • indent4 line 2 uuis
                              • foo
                              • foobar bs
                        • foobar

                '); + expect(results[1][1]).to.be('\tindent line 1\n\n\tindent line 2\n\t\tindent2 line 1\n\n\t\t\t\tindent4 line 2 bisu\n\t\t\t\tindent4 line 2 bs\n\t\t\t\tindent4 line 2 uuis\n\t\t\t\t\t\t\t\tfoo\n\t\t\t\t\t\t\t\tfoobar bs\n\t\t\t\t\tfoobar\n\n'); + done(); + }); +}); diff --git a/tests/frontend/specs/indentation.js b/tests/frontend/specs/indentation.js index 2173f9e07..f35b7ca00 100644 --- a/tests/frontend/specs/indentation.js +++ b/tests/frontend/specs/indentation.js @@ -1,178 +1,164 @@ -describe("indentation button", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('indentation button', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("indent text with keypress", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('indent text with keypress', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - var e = inner$.Event(helper.evtType); + const e = inner$.Event(helper.evtType); e.keyCode = 9; // tab :| - inner$("#innerdocbody").trigger(e); + inner$('#innerdocbody').trigger(e); - helper.waitFor(function(){ - return inner$("div").first().find("ul li").length === 1; - }).done(done); + helper.waitFor(() => inner$('div').first().find('ul li').length === 1).done(done); }); - it("indent text with button", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('indent text with button', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - var $indentButton = chrome$(".buttonicon-indent"); + const $indentButton = chrome$('.buttonicon-indent'); $indentButton.click(); - helper.waitFor(function(){ - return inner$("div").first().find("ul li").length === 1; - }).done(done); + helper.waitFor(() => inner$('div').first().find('ul li').length === 1).done(done); }); - it("keeps the indent on enter for the new line", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('keeps the indent on enter for the new line', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - var $indentButton = chrome$(".buttonicon-indent"); + const $indentButton = chrome$('.buttonicon-indent'); $indentButton.click(); - //type a bit, make a line break and type again - var $firstTextElement = inner$("div span").first(); + // type a bit, make a line break and type again + const $firstTextElement = inner$('div span').first(); $firstTextElement.sendkeys('line 1'); $firstTextElement.sendkeys('{enter}'); $firstTextElement.sendkeys('line 2'); $firstTextElement.sendkeys('{enter}'); - helper.waitFor(function(){ - return inner$("div span").first().text().indexOf("line 2") === -1; - }).done(function(){ - var $newSecondLine = inner$("div").first().next(); - var hasULElement = $newSecondLine.find("ul li").length === 1; + helper.waitFor(() => inner$('div span').first().text().indexOf('line 2') === -1).done(() => { + const $newSecondLine = inner$('div').first().next(); + const hasULElement = $newSecondLine.find('ul li').length === 1; expect(hasULElement).to.be(true); - expect($newSecondLine.text()).to.be("line 2"); + expect($newSecondLine.text()).to.be('line 2'); done(); }); }); - it("indents text with spaces on enter if previous line ends with ':', '[', '(', or '{'", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it("indents text with spaces on enter if previous line ends with ':', '[', '(', or '{'", function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //type a bit, make a line break and type again - var $firstTextElement = inner$("div").first(); + // type a bit, make a line break and type again + const $firstTextElement = inner$('div').first(); $firstTextElement.sendkeys("line with ':'{enter}"); $firstTextElement.sendkeys("line with '['{enter}"); $firstTextElement.sendkeys("line with '('{enter}"); $firstTextElement.sendkeys("line with '{{}'{enter}"); - helper.waitFor(function(){ + helper.waitFor(() => { // wait for Etherpad to split four lines into separated divs - var $fourthLine = inner$("div").first().next().next().next(); + const $fourthLine = inner$('div').first().next().next().next(); return $fourthLine.text().indexOf("line with '{'") === 0; - }).done(function(){ + }).done(() => { // we validate bottom to top for easier implementation // curly braces - var $lineWithCurlyBraces = inner$("div").first().next().next().next(); + const $lineWithCurlyBraces = inner$('div').first().next().next().next(); $lineWithCurlyBraces.sendkeys('{{}'); pressEnter(); // cannot use sendkeys('{enter}') here, browser does not read the command properly - var $lineAfterCurlyBraces = inner$("div").first().next().next().next().next(); + const $lineAfterCurlyBraces = inner$('div').first().next().next().next().next(); expect($lineAfterCurlyBraces.text()).to.match(/\s{4}/); // tab === 4 spaces // parenthesis - var $lineWithParenthesis = inner$("div").first().next().next(); + const $lineWithParenthesis = inner$('div').first().next().next(); $lineWithParenthesis.sendkeys('('); pressEnter(); - var $lineAfterParenthesis = inner$("div").first().next().next().next(); + const $lineAfterParenthesis = inner$('div').first().next().next().next(); expect($lineAfterParenthesis.text()).to.match(/\s{4}/); // bracket - var $lineWithBracket = inner$("div").first().next(); + const $lineWithBracket = inner$('div').first().next(); $lineWithBracket.sendkeys('['); pressEnter(); - var $lineAfterBracket = inner$("div").first().next().next(); + const $lineAfterBracket = inner$('div').first().next().next(); expect($lineAfterBracket.text()).to.match(/\s{4}/); // colon - var $lineWithColon = inner$("div").first(); + const $lineWithColon = inner$('div').first(); $lineWithColon.sendkeys(':'); pressEnter(); - var $lineAfterColon = inner$("div").first().next(); + const $lineAfterColon = inner$('div').first().next(); expect($lineAfterColon.text()).to.match(/\s{4}/); done(); }); }); - it("appends indentation to the indent of previous line if previous line ends with ':', '[', '(', or '{'", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it("appends indentation to the indent of previous line if previous line ends with ':', '[', '(', or '{'", function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //type a bit, make a line break and type again - var $firstTextElement = inner$("div").first(); + // type a bit, make a line break and type again + const $firstTextElement = inner$('div').first(); $firstTextElement.sendkeys(" line with some indentation and ':'{enter}"); - $firstTextElement.sendkeys("line 2{enter}"); + $firstTextElement.sendkeys('line 2{enter}'); - helper.waitFor(function(){ + helper.waitFor(() => { // wait for Etherpad to split two lines into separated divs - var $secondLine = inner$("div").first().next(); - return $secondLine.text().indexOf("line 2") === 0; - }).done(function(){ - var $lineWithColon = inner$("div").first(); + const $secondLine = inner$('div').first().next(); + return $secondLine.text().indexOf('line 2') === 0; + }).done(() => { + const $lineWithColon = inner$('div').first(); $lineWithColon.sendkeys(':'); pressEnter(); - var $lineAfterColon = inner$("div").first().next(); + const $lineAfterColon = inner$('div').first().next(); expect($lineAfterColon.text()).to.match(/\s{6}/); // previous line indentation + regular tab (4 spaces) done(); }); }); - it("issue #2772 shows '*' when multiple indented lines receive a style and are outdented", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it("issue #2772 shows '*' when multiple indented lines receive a style and are outdented", function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // make sure pad has more than one line - inner$("div").first().sendkeys("First{enter}Second{enter}"); - helper.waitFor(function(){ - return inner$("div").first().text().trim() === "First"; - }).done(function(){ + inner$('div').first().sendkeys('First{enter}Second{enter}'); + helper.waitFor(() => inner$('div').first().text().trim() === 'First').done(() => { // indent first 2 lines - var $lines = inner$("div"); - var $firstLine = $lines.first(); - var $secondLine = $lines.slice(1,2); + const $lines = inner$('div'); + const $firstLine = $lines.first(); + const $secondLine = $lines.slice(1, 2); helper.selectLines($firstLine, $secondLine); - var $indentButton = chrome$(".buttonicon-indent"); + const $indentButton = chrome$('.buttonicon-indent'); $indentButton.click(); - helper.waitFor(function(){ - return inner$("div").first().find("ul li").length === 1; - }).done(function(){ + helper.waitFor(() => inner$('div').first().find('ul li').length === 1).done(() => { // apply bold - var $boldButton = chrome$(".buttonicon-bold"); + const $boldButton = chrome$('.buttonicon-bold'); $boldButton.click(); - helper.waitFor(function(){ - return inner$("div").first().find("b").length === 1; - }).done(function(){ + helper.waitFor(() => inner$('div').first().find('b').length === 1).done(() => { // outdent first 2 lines - var $outdentButton = chrome$(".buttonicon-outdent"); + const $outdentButton = chrome$('.buttonicon-outdent'); $outdentButton.click(); - helper.waitFor(function(){ - return inner$("div").first().find("ul li").length === 0; - }).done(function(){ + helper.waitFor(() => inner$('div').first().find('ul li').length === 0).done(() => { // check if '*' is displayed - var $secondLine = inner$("div").slice(1,2); - expect($secondLine.text().trim()).to.be("Second"); + const $secondLine = inner$('div').slice(1, 2); + expect($secondLine.text().trim()).to.be('Second'); done(); }); @@ -314,12 +300,11 @@ describe("indentation button", function(){ expect(isLI).to.be(true); },1000); });*/ - }); -function pressEnter(){ - var inner$ = helper.padInner$; - var e = inner$.Event(helper.evtType); +function pressEnter() { + const inner$ = helper.padInner$; + const e = inner$.Event(helper.evtType); e.keyCode = 13; // enter :| - inner$("#innerdocbody").trigger(e); + inner$('#innerdocbody').trigger(e); } diff --git a/tests/frontend/specs/italic.js b/tests/frontend/specs/italic.js index 3c62e00e8..3660f71f3 100644 --- a/tests/frontend/specs/italic.js +++ b/tests/frontend/specs/italic.js @@ -1,67 +1,66 @@ -describe("italic some text", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('italic some text', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("makes text italic using button", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text italic using button', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - //get the bold button and click it - var $boldButton = chrome$(".buttonicon-italic"); + // get the bold button and click it + const $boldButton = chrome$('.buttonicon-italic'); $boldButton.click(); - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); + // ace creates a new dom element when you press a button, so just get the first text element again + const $newFirstTextElement = inner$('div').first(); // is there a element now? - var isItalic = $newFirstTextElement.find("i").length === 1; + const isItalic = $newFirstTextElement.find('i').length === 1; - //expect it to be bold + // expect it to be bold expect(isItalic).to.be(true); - //make sure the text hasn't changed + // make sure the text hasn't changed expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); done(); }); - it("makes text italic using keypress", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text italic using keypress', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - var e = inner$.Event(helper.evtType); + const e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 105; // i - inner$("#innerdocbody").trigger(e); + inner$('#innerdocbody').trigger(e); - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); + // ace creates a new dom element when you press a button, so just get the first text element again + const $newFirstTextElement = inner$('div').first(); // is there a element now? - var isItalic = $newFirstTextElement.find("i").length === 1; + const isItalic = $newFirstTextElement.find('i').length === 1; - //expect it to be bold + // expect it to be bold expect(isItalic).to.be(true); - //make sure the text hasn't changed + // make sure the text hasn't changed expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); done(); }); - }); diff --git a/tests/frontend/specs/language.js b/tests/frontend/specs/language.js index 41a19d11c..d29b2407e 100644 --- a/tests/frontend/specs/language.js +++ b/tests/frontend/specs/language.js @@ -1,135 +1,127 @@ function deletecookie(name) { - document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; + document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:01 GMT;`; } -describe("Language select and change", function(){ +describe('Language select and change', function () { // Destroy language cookies - deletecookie("language", null); + deletecookie('language', null); - //create a new pad before each test run - beforeEach(function(cb){ + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); // Destroy language cookies - it("makes text german", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text german', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); + // click on the settings button to make settings visible + const $settingsButton = chrome$('.buttonicon-settings'); $settingsButton.click(); - //click the language button - var $language = chrome$("#languagemenu"); - var $languageoption = $language.find("[value=de]"); + // click the language button + const $language = chrome$('#languagemenu'); + const $languageoption = $language.find('[value=de]'); - //select german - $languageoption.attr('selected','selected'); + // select german + $languageoption.attr('selected', 'selected'); $language.change(); - helper.waitFor(function() { - return chrome$(".buttonicon-bold").parent()[0]["title"] == "Fett (Strg-B)"; - }) - .done(function(){ - //get the value of the bold button - var $boldButton = chrome$(".buttonicon-bold").parent(); + helper.waitFor(() => chrome$('.buttonicon-bold').parent()[0].title == 'Fett (Strg-B)') + .done(() => { + // get the value of the bold button + const $boldButton = chrome$('.buttonicon-bold').parent(); - //get the title of the bold button - var boldButtonTitle = $boldButton[0]["title"]; + // get the title of the bold button + const boldButtonTitle = $boldButton[0].title; - //check if the language is now german - expect(boldButtonTitle).to.be("Fett (Strg-B)"); - done(); - }); + // check if the language is now german + expect(boldButtonTitle).to.be('Fett (Strg-B)'); + done(); + }); }); - it("makes text English", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text English', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); + // click on the settings button to make settings visible + const $settingsButton = chrome$('.buttonicon-settings'); $settingsButton.click(); - //click the language button - var $language = chrome$("#languagemenu"); - //select english - $language.val("en"); + // click the language button + const $language = chrome$('#languagemenu'); + // select english + $language.val('en'); $language.change(); - //get the value of the bold button - var $boldButton = chrome$(".buttonicon-bold").parent(); + // get the value of the bold button + const $boldButton = chrome$('.buttonicon-bold').parent(); - helper.waitFor(function() { return $boldButton[0]["title"] != "Fett (Strg+B)";}) - .done(function(){ + helper.waitFor(() => $boldButton[0].title != 'Fett (Strg+B)') + .done(() => { + // get the value of the bold button + const $boldButton = chrome$('.buttonicon-bold').parent(); - //get the value of the bold button - var $boldButton = chrome$(".buttonicon-bold").parent(); + // get the title of the bold button + const boldButtonTitle = $boldButton[0].title; - //get the title of the bold button - var boldButtonTitle = $boldButton[0]["title"]; - - //check if the language is now English - expect(boldButtonTitle).to.be("Bold (Ctrl+B)"); - done(); - - }); + // check if the language is now English + expect(boldButtonTitle).to.be('Bold (Ctrl+B)'); + done(); + }); }); - it("changes direction when picking an rtl lang", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('changes direction when picking an rtl lang', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); + // click on the settings button to make settings visible + const $settingsButton = chrome$('.buttonicon-settings'); $settingsButton.click(); - //click the language button - var $language = chrome$("#languagemenu"); - var $languageoption = $language.find("[value=ar]"); + // click the language button + const $language = chrome$('#languagemenu'); + const $languageoption = $language.find('[value=ar]'); - //select arabic + // select arabic // $languageoption.attr('selected','selected'); // Breaks the test.. - $language.val("ar"); + $language.val('ar'); $languageoption.change(); - helper.waitFor(function() { - return chrome$("html")[0]["dir"] != 'ltr'; - }) - .done(function(){ - // check if the document's direction was changed - expect(chrome$("html")[0]["dir"]).to.be("rtl"); - done(); - }); + helper.waitFor(() => chrome$('html')[0].dir != 'ltr') + .done(() => { + // check if the document's direction was changed + expect(chrome$('html')[0].dir).to.be('rtl'); + done(); + }); }); - it("changes direction when picking an ltr lang", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('changes direction when picking an ltr lang', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); + // click on the settings button to make settings visible + const $settingsButton = chrome$('.buttonicon-settings'); $settingsButton.click(); - //click the language button - var $language = chrome$("#languagemenu"); - var $languageoption = $language.find("[value=en]"); + // click the language button + const $language = chrome$('#languagemenu'); + const $languageoption = $language.find('[value=en]'); - //select english - //select arabic - $languageoption.attr('selected','selected'); - $language.val("en"); + // select english + // select arabic + $languageoption.attr('selected', 'selected'); + $language.val('en'); $languageoption.change(); - helper.waitFor(function() { - return chrome$("html")[0]["dir"] != 'rtl'; - }) - .done(function(){ - // check if the document's direction was changed - expect(chrome$("html")[0]["dir"]).to.be("ltr"); - done(); - }); + helper.waitFor(() => chrome$('html')[0].dir != 'rtl') + .done(() => { + // check if the document's direction was changed + expect(chrome$('html')[0].dir).to.be('ltr'); + done(); + }); }); }); diff --git a/tests/frontend/specs/multiple_authors_clear_authorship_colors.js b/tests/frontend/specs/multiple_authors_clear_authorship_colors.js index 7611fffa4..f532ea4be 100755 --- a/tests/frontend/specs/multiple_authors_clear_authorship_colors.js +++ b/tests/frontend/specs/multiple_authors_clear_authorship_colors.js @@ -1,18 +1,16 @@ -describe('author of pad edition', function() { +describe('author of pad edition', function () { // author 1 creates a new pad with some content (regular lines and lists) - before(function(done) { - var padId = helper.newPad(function() { + before(function (done) { + var padId = helper.newPad(() => { // make sure pad has at least 3 lines - var $firstLine = helper.padInner$('div').first(); - $firstLine.html("Hello World"); + const $firstLine = helper.padInner$('div').first(); + $firstLine.html('Hello World'); // wait for lines to be processed by Etherpad - helper.waitFor(function() { - return $firstLine.text() === 'Hello World'; - }).done(function() { + helper.waitFor(() => $firstLine.text() === 'Hello World').done(() => { // Reload pad, to make changes as a second user. Need a timeout here to make sure // all changes were saved before reloading - setTimeout(function() { + setTimeout(() => { // Expire cookie, so author is changed after reloading the pad. // See https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#Example_4_Reset_the_previous_cookie helper.padChrome$.document.cookie = 'token=foo;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'; @@ -25,27 +23,27 @@ describe('author of pad edition', function() { }); // author 2 makes some changes on the pad - it('Clears Authorship by second user', function(done) { + it('Clears Authorship by second user', function (done) { clearAuthorship(done); }); - var clearAuthorship = function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var clearAuthorship = function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // override the confirm dialogue functioon - helper.padChrome$.window.confirm = function(){ + helper.padChrome$.window.confirm = function () { return true; - } + }; - //get the clear authorship colors button and click it - var $clearauthorshipcolorsButton = chrome$(".buttonicon-clearauthorship"); + // get the clear authorship colors button and click it + const $clearauthorshipcolorsButton = chrome$('.buttonicon-clearauthorship'); $clearauthorshipcolorsButton.click(); // does the first divs span include an author class? - var hasAuthorClass = inner$("div span").first().attr("class").indexOf("author") !== -1; + const hasAuthorClass = inner$('div span').first().attr('class').indexOf('author') !== -1; - expect(hasAuthorClass).to.be(false) + expect(hasAuthorClass).to.be(false); done(); - } + }; }); diff --git a/tests/frontend/specs/ordered_list.js b/tests/frontend/specs/ordered_list.js index 4f81c4564..a932335e8 100644 --- a/tests/frontend/specs/ordered_list.js +++ b/tests/frontend/specs/ordered_list.js @@ -1,204 +1,180 @@ -describe("assign ordered list", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('assign ordered list', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("inserts ordered list text", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('inserts ordered list text', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist"); + const $insertorderedlistButton = chrome$('.buttonicon-insertorderedlist'); $insertorderedlistButton.click(); - helper.waitFor(function(){ - return inner$("div").first().find("ol li").length === 1; - }).done(done); + helper.waitFor(() => inner$('div').first().find('ol li').length === 1).done(done); }); - context('when user presses Ctrl+Shift+N', function() { - context('and pad shortcut is enabled', function() { - beforeEach(function() { + context('when user presses Ctrl+Shift+N', function () { + context('and pad shortcut is enabled', function () { + beforeEach(function () { makeSureShortcutIsEnabled('cmdShiftN'); triggerCtrlShiftShortcut('N'); }); - it('inserts unordered list', function(done) { - helper.waitFor(function() { - return helper.padInner$('div').first().find('ol li').length === 1; - }).done(done); + it('inserts unordered list', function (done) { + helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1).done(done); }); }); - context('and pad shortcut is disabled', function() { - beforeEach(function() { + context('and pad shortcut is disabled', function () { + beforeEach(function () { makeSureShortcutIsDisabled('cmdShiftN'); triggerCtrlShiftShortcut('N'); }); - it('does not insert unordered list', function(done) { - helper.waitFor(function() { - return helper.padInner$('div').first().find('ol li').length === 1; - }).done(function() { - expect().fail(function() { return 'Unordered list inserted, should ignore shortcut' }); - }).fail(function() { + it('does not insert unordered list', function (done) { + helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1).done(() => { + expect().fail(() => 'Unordered list inserted, should ignore shortcut'); + }).fail(() => { done(); }); }); }); }); - context('when user presses Ctrl+Shift+1', function() { - context('and pad shortcut is enabled', function() { - beforeEach(function() { + context('when user presses Ctrl+Shift+1', function () { + context('and pad shortcut is enabled', function () { + beforeEach(function () { makeSureShortcutIsEnabled('cmdShift1'); triggerCtrlShiftShortcut('1'); }); - it('inserts unordered list', function(done) { - helper.waitFor(function() { - return helper.padInner$('div').first().find('ol li').length === 1; - }).done(done); + it('inserts unordered list', function (done) { + helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1).done(done); }); }); - context('and pad shortcut is disabled', function() { - beforeEach(function() { + context('and pad shortcut is disabled', function () { + beforeEach(function () { makeSureShortcutIsDisabled('cmdShift1'); triggerCtrlShiftShortcut('1'); }); - it('does not insert unordered list', function(done) { - helper.waitFor(function() { - return helper.padInner$('div').first().find('ol li').length === 1; - }).done(function() { - expect().fail(function() { return 'Unordered list inserted, should ignore shortcut' }); - }).fail(function() { + it('does not insert unordered list', function (done) { + helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1).done(() => { + expect().fail(() => 'Unordered list inserted, should ignore shortcut'); + }).fail(() => { done(); }); }); }); }); - xit("issue #1125 keeps the numbered list on enter for the new line - EMULATES PASTING INTO A PAD", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + xit('issue #1125 keeps the numbered list on enter for the new line - EMULATES PASTING INTO A PAD', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist"); + const $insertorderedlistButton = chrome$('.buttonicon-insertorderedlist'); $insertorderedlistButton.click(); - //type a bit, make a line break and type again - var $firstTextElement = inner$("div span").first(); + // type a bit, make a line break and type again + const $firstTextElement = inner$('div span').first(); $firstTextElement.sendkeys('line 1'); $firstTextElement.sendkeys('{enter}'); $firstTextElement.sendkeys('line 2'); $firstTextElement.sendkeys('{enter}'); - helper.waitFor(function(){ - return inner$("div span").first().text().indexOf("line 2") === -1; - }).done(function(){ - var $newSecondLine = inner$("div").first().next(); - var hasOLElement = $newSecondLine.find("ol li").length === 1; + helper.waitFor(() => inner$('div span').first().text().indexOf('line 2') === -1).done(() => { + const $newSecondLine = inner$('div').first().next(); + const hasOLElement = $newSecondLine.find('ol li').length === 1; expect(hasOLElement).to.be(true); - expect($newSecondLine.text()).to.be("line 2"); - var hasLineNumber = $newSecondLine.find("ol").attr("start") === 2; + expect($newSecondLine.text()).to.be('line 2'); + const hasLineNumber = $newSecondLine.find('ol').attr('start') === 2; expect(hasLineNumber).to.be(true); // This doesn't work because pasting in content doesn't work done(); }); }); - var triggerCtrlShiftShortcut = function(shortcutChar) { - var inner$ = helper.padInner$; - var e = inner$.Event(helper.evtType); + var triggerCtrlShiftShortcut = function (shortcutChar) { + const inner$ = helper.padInner$; + const e = inner$.Event(helper.evtType); e.ctrlKey = true; e.shiftKey = true; e.which = shortcutChar.toString().charCodeAt(0); - inner$("#innerdocbody").trigger(e); - } + inner$('#innerdocbody').trigger(e); + }; - var makeSureShortcutIsDisabled = function(shortcut) { + var makeSureShortcutIsDisabled = function (shortcut) { helper.padChrome$.window.clientVars.padShortcutEnabled[shortcut] = false; - } - var makeSureShortcutIsEnabled = function(shortcut) { + }; + var makeSureShortcutIsEnabled = function (shortcut) { helper.padChrome$.window.clientVars.padShortcutEnabled[shortcut] = true; - } - + }; }); -describe("Pressing Tab in an OL increases and decreases indentation", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('Pressing Tab in an OL increases and decreases indentation', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("indent and de-indent list item with keypress", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('indent and de-indent list item with keypress', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist"); + const $insertorderedlistButton = chrome$('.buttonicon-insertorderedlist'); $insertorderedlistButton.click(); - var e = inner$.Event(helper.evtType); + const e = inner$.Event(helper.evtType); e.keyCode = 9; // tab - inner$("#innerdocbody").trigger(e); + inner$('#innerdocbody').trigger(e); - expect(inner$("div").first().find(".list-number2").length === 1).to.be(true); + expect(inner$('div').first().find('.list-number2').length === 1).to.be(true); e.shiftKey = true; // shift e.keyCode = 9; // tab - inner$("#innerdocbody").trigger(e); - - helper.waitFor(function(){ - return inner$("div").first().find(".list-number1").length === 1; - }).done(done); + inner$('#innerdocbody').trigger(e); + helper.waitFor(() => inner$('div').first().find('.list-number1').length === 1).done(done); }); - - }); -describe("Pressing indent/outdent button in an OL increases and decreases indentation and bullet / ol formatting", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('Pressing indent/outdent button in an OL increases and decreases indentation and bullet / ol formatting', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("indent and de-indent list item with indent button", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('indent and de-indent list item with indent button', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist"); + const $insertorderedlistButton = chrome$('.buttonicon-insertorderedlist'); $insertorderedlistButton.click(); - var $indentButton = chrome$(".buttonicon-indent"); + const $indentButton = chrome$('.buttonicon-indent'); $indentButton.click(); // make it indented twice - expect(inner$("div").first().find(".list-number2").length === 1).to.be(true); + expect(inner$('div').first().find('.list-number2').length === 1).to.be(true); - var $outdentButton = chrome$(".buttonicon-outdent"); + const $outdentButton = chrome$('.buttonicon-outdent'); $outdentButton.click(); // make it deindented to 1 - helper.waitFor(function(){ - return inner$("div").first().find(".list-number1").length === 1; - }).done(done); - + helper.waitFor(() => inner$('div').first().find('.list-number1').length === 1).done(done); }); - - }); - diff --git a/tests/frontend/specs/pad_modal.js b/tests/frontend/specs/pad_modal.js index 877381737..1711e38b8 100644 --- a/tests/frontend/specs/pad_modal.js +++ b/tests/frontend/specs/pad_modal.js @@ -1,36 +1,34 @@ -describe('Pad modal', function() { - context('when modal is a "force reconnect" message', function() { - var MODAL_SELECTOR = '#connectivity'; +describe('Pad modal', function () { + context('when modal is a "force reconnect" message', function () { + const MODAL_SELECTOR = '#connectivity'; - beforeEach(function(done) { - helper.newPad(function() { + beforeEach(function (done) { + helper.newPad(() => { // force a "slowcommit" error helper.padChrome$.window.pad.handleChannelStateChange('DISCONNECTED', 'slowcommit'); // wait for modal to be displayed - var $modal = helper.padChrome$(MODAL_SELECTOR); - helper.waitFor(function() { - return $modal.hasClass('popup-show'); - }, 50000).done(done); + const $modal = helper.padChrome$(MODAL_SELECTOR); + helper.waitFor(() => $modal.hasClass('popup-show'), 50000).done(done); }); this.timeout(60000); }); - it('disables editor', function(done) { + it('disables editor', function (done) { expect(isEditorDisabled()).to.be(true); done(); }); - context('and user clicks on editor', function() { - beforeEach(function() { + context('and user clicks on editor', function () { + beforeEach(function () { clickOnPadInner(); }); - it('does not close the modal', function(done) { - var $modal = helper.padChrome$(MODAL_SELECTOR); - var modalIsVisible = $modal.hasClass('popup-show'); + it('does not close the modal', function (done) { + const $modal = helper.padChrome$(MODAL_SELECTOR); + const modalIsVisible = $modal.hasClass('popup-show'); expect(modalIsVisible).to.be(true); @@ -38,14 +36,14 @@ describe('Pad modal', function() { }); }); - context('and user clicks on pad outer', function() { - beforeEach(function() { + context('and user clicks on pad outer', function () { + beforeEach(function () { clickOnPadOuter(); }); - it('does not close the modal', function(done) { - var $modal = helper.padChrome$(MODAL_SELECTOR); - var modalIsVisible = $modal.hasClass('popup-show'); + it('does not close the modal', function (done) { + const $modal = helper.padChrome$(MODAL_SELECTOR); + const modalIsVisible = $modal.hasClass('popup-show'); expect(modalIsVisible).to.be(true); @@ -55,79 +53,77 @@ describe('Pad modal', function() { }); // we use "settings" here, but other modals have the same behaviour - context('when modal is not an error message', function() { - var MODAL_SELECTOR = '#settings'; + context('when modal is not an error message', function () { + const MODAL_SELECTOR = '#settings'; - beforeEach(function(done) { - helper.newPad(function() { + beforeEach(function (done) { + helper.newPad(() => { openSettingsAndWaitForModalToBeVisible(done); }); this.timeout(60000); }); // This test breaks safari testing -/* + /* it('does not disable editor', function(done) { expect(isEditorDisabled()).to.be(false); done(); }); */ - context('and user clicks on editor', function() { - beforeEach(function() { + context('and user clicks on editor', function () { + beforeEach(function () { clickOnPadInner(); }); - it('closes the modal', function(done) { + it('closes the modal', function (done) { expect(isModalOpened(MODAL_SELECTOR)).to.be(false); done(); }); }); - context('and user clicks on pad outer', function() { - beforeEach(function() { + context('and user clicks on pad outer', function () { + beforeEach(function () { clickOnPadOuter(); }); - it('closes the modal', function(done) { + it('closes the modal', function (done) { expect(isModalOpened(MODAL_SELECTOR)).to.be(false); done(); }); }); }); - var clickOnPadInner = function() { - var $editor = helper.padInner$('#innerdocbody'); + var clickOnPadInner = function () { + const $editor = helper.padInner$('#innerdocbody'); $editor.click(); - } + }; - var clickOnPadOuter = function() { - var $lineNumbersColumn = helper.padOuter$('#sidedivinner'); + var clickOnPadOuter = function () { + const $lineNumbersColumn = helper.padOuter$('#sidedivinner'); $lineNumbersColumn.click(); - } + }; - var openSettingsAndWaitForModalToBeVisible = function(done) { + var openSettingsAndWaitForModalToBeVisible = function (done) { helper.padChrome$('.buttonicon-settings').click(); // wait for modal to be displayed - var modalSelector = '#settings'; - helper.waitFor(function() { - return isModalOpened(modalSelector); - }, 10000).done(done); - } + const modalSelector = '#settings'; + helper.waitFor(() => isModalOpened(modalSelector), 10000).done(done); + }; - var isEditorDisabled = function() { - var editorDocument = helper.padOuter$("iframe[name='ace_inner']").get(0).contentDocument; - var editorBody = editorDocument.getElementById('innerdocbody'); + var isEditorDisabled = function () { + const editorDocument = helper.padOuter$("iframe[name='ace_inner']").get(0).contentDocument; + const editorBody = editorDocument.getElementById('innerdocbody'); - var editorIsDisabled = editorBody.contentEditable === 'false' // IE/Safari - || editorDocument.designMode === 'off'; // other browsers + const editorIsDisabled = editorBody.contentEditable === 'false' || // IE/Safari + editorDocument.designMode === 'off'; // other browsers return editorIsDisabled; - } + }; - var isModalOpened = function(modalSelector) { - var $modal = helper.padChrome$(modalSelector); + var isModalOpened = function (modalSelector) { + const $modal = helper.padChrome$(modalSelector); return $modal.hasClass('popup-show'); - } + }; }); diff --git a/tests/frontend/specs/redo.js b/tests/frontend/specs/redo.js index be85d44c3..58d5b6c12 100644 --- a/tests/frontend/specs/redo.js +++ b/tests/frontend/specs/redo.js @@ -1,68 +1,63 @@ -describe("undo button then redo button", function(){ - beforeEach(function(cb){ +describe('undo button then redo button', function () { + beforeEach(function (cb) { helper.newPad(cb); // creates a new pad this.timeout(60000); }); - it("redo some typing with button", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('redo some typing with button', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value - var newString = "Foo"; + const $firstTextElement = inner$('div span').first(); + const originalValue = $firstTextElement.text(); // get the original value + const newString = 'Foo'; $firstTextElement.sendkeys(newString); // send line 1 to the pad - var modifiedValue = $firstTextElement.text(); // get the modified value + const modifiedValue = $firstTextElement.text(); // get the modified value expect(modifiedValue).not.to.be(originalValue); // expect the value to change // get undo and redo buttons - var $undoButton = chrome$(".buttonicon-undo"); - var $redoButton = chrome$(".buttonicon-redo"); + const $undoButton = chrome$('.buttonicon-undo'); + const $redoButton = chrome$('.buttonicon-redo'); // click the buttons $undoButton.click(); // removes foo $redoButton.click(); // resends foo - helper.waitFor(function(){ - return inner$("div span").first().text() === newString; - }).done(function(){ - var finalValue = inner$("div").first().text(); + helper.waitFor(() => inner$('div span').first().text() === newString).done(() => { + const finalValue = inner$('div').first().text(); expect(finalValue).to.be(modifiedValue); // expect the value to change done(); }); }); - it("redo some typing with keypress", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('redo some typing with keypress', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value - var newString = "Foo"; + const $firstTextElement = inner$('div span').first(); + const originalValue = $firstTextElement.text(); // get the original value + const newString = 'Foo'; $firstTextElement.sendkeys(newString); // send line 1 to the pad - var modifiedValue = $firstTextElement.text(); // get the modified value + const modifiedValue = $firstTextElement.text(); // get the modified value expect(modifiedValue).not.to.be(originalValue); // expect the value to change var e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 90; // z - inner$("#innerdocbody").trigger(e); + inner$('#innerdocbody').trigger(e); var e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 121; // y - inner$("#innerdocbody").trigger(e); + inner$('#innerdocbody').trigger(e); - helper.waitFor(function(){ - return inner$("div span").first().text() === newString; - }).done(function(){ - var finalValue = inner$("div").first().text(); + helper.waitFor(() => inner$('div span').first().text() === newString).done(() => { + const finalValue = inner$('div').first().text(); expect(finalValue).to.be(modifiedValue); // expect the value to change done(); }); }); }); - diff --git a/tests/frontend/specs/responsiveness.js b/tests/frontend/specs/responsiveness.js index 802ab1c92..1c3a0c65b 100644 --- a/tests/frontend/specs/responsiveness.js +++ b/tests/frontend/specs/responsiveness.js @@ -13,9 +13,9 @@ // Adapted from John McLear's original test case. -xdescribe('Responsiveness of Editor', function() { +xdescribe('Responsiveness of Editor', function () { // create a new pad before each test run - beforeEach(function(cb) { + beforeEach(function (cb) { helper.newPad(cb); this.timeout(6000); }); @@ -23,67 +23,62 @@ xdescribe('Responsiveness of Editor', function() { // And the test needs to be fixed to work in Firefox 52 on Windows 7. I am not sure why it fails on this specific platform // The errors show this.timeout... then crash the browser but I am sure something is actually causing the stack trace and // I just need to narrow down what, offers to help accepted. - it('Fast response to keypress in pad with large amount of contents', function(done) { - - //skip on Windows Firefox 52.0 - if(window.bowser && window.bowser.windows && window.bowser.firefox && window.bowser.version == "52.0") { + it('Fast response to keypress in pad with large amount of contents', function (done) { + // skip on Windows Firefox 52.0 + if (window.bowser && window.bowser.windows && window.bowser.firefox && window.bowser.version == '52.0') { this.skip(); } - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - var chars = '0000000000'; // row of placeholder chars - var amount = 200000; //number of blocks of chars we will insert - var length = (amount * (chars.length) +1); // include a counter for each space - var text = ''; // the text we're gonna insert + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; + const chars = '0000000000'; // row of placeholder chars + const amount = 200000; // number of blocks of chars we will insert + const length = (amount * (chars.length) + 1); // include a counter for each space + let text = ''; // the text we're gonna insert this.timeout(amount * 150); // Changed from 100 to 150 to allow Mac OSX Safari to be slow. // get keys to send - var keyMultiplier = 10; // multiplier * 10 == total number of key events - var keysToSend = ''; - for(var i=0; i <= keyMultiplier; i++) { + const keyMultiplier = 10; // multiplier * 10 == total number of key events + let keysToSend = ''; + for (var i = 0; i <= keyMultiplier; i++) { keysToSend += chars; } - var textElement = inner$('div'); + const textElement = inner$('div'); textElement.sendkeys('{selectall}'); // select all textElement.sendkeys('{del}'); // clear the pad text - for(var i=0; i <= amount; i++) { - text = text + chars + ' '; // add the chars and space to the text contents + for (var i = 0; i <= amount; i++) { + text = `${text + chars} `; // add the chars and space to the text contents } inner$('div').first().text(text); // Put the text contents into the pad - helper.waitFor(function(){ // Wait for the new contents to be on the pad - return inner$('div').text().length > length; - }).done(function(){ - - expect( inner$('div').text().length ).to.be.greaterThan( length ); // has the text changed? - var start = Date.now(); // get the start time + helper.waitFor(() => // Wait for the new contents to be on the pad + inner$('div').text().length > length, + ).done(() => { + expect(inner$('div').text().length).to.be.greaterThan(length); // has the text changed? + const start = Date.now(); // get the start time // send some new text to the screen (ensure all 3 key events are sent) - var el = inner$('div').first(); - for(var i = 0; i < keysToSend.length; ++i) { + const el = inner$('div').first(); + for (let i = 0; i < keysToSend.length; ++i) { var x = keysToSend.charCodeAt(i); - ['keyup', 'keypress', 'keydown'].forEach(function(type) { - var e = $.Event(type); + ['keyup', 'keypress', 'keydown'].forEach((type) => { + const e = $.Event(type); e.keyCode = x; el.trigger(e); }); } - helper.waitFor(function(){ // Wait for the ability to process - var el = inner$('body'); - if(el[0].textContent.length > amount) return true; - }).done(function(){ - var end = Date.now(); // get the current time - var delay = end - start; // get the delay as the current time minus the start time + helper.waitFor(() => { // Wait for the ability to process + const el = inner$('body'); + if (el[0].textContent.length > amount) return true; + }).done(() => { + const end = Date.now(); // get the current time + const delay = end - start; // get the delay as the current time minus the start time expect(delay).to.be.below(600); done(); }, 5000); - }, 10000); }); - }); - diff --git a/tests/frontend/specs/select_formatting_buttons.js b/tests/frontend/specs/select_formatting_buttons.js index 9bc6f1017..52595a044 100644 --- a/tests/frontend/specs/select_formatting_buttons.js +++ b/tests/frontend/specs/select_formatting_buttons.js @@ -1,105 +1,101 @@ -describe("select formatting buttons when selection has style applied", function(){ - var STYLES = ['italic', 'bold', 'underline', 'strikethrough']; - var SHORTCUT_KEYS = ['I', 'B', 'U', '5']; // italic, bold, underline, strikethrough - var FIRST_LINE = 0; +describe('select formatting buttons when selection has style applied', function () { + const STYLES = ['italic', 'bold', 'underline', 'strikethrough']; + const SHORTCUT_KEYS = ['I', 'B', 'U', '5']; // italic, bold, underline, strikethrough + const FIRST_LINE = 0; - before(function(cb){ + before(function (cb) { helper.newPad(cb); this.timeout(60000); }); - var applyStyleOnLine = function(style, line) { - var chrome$ = helper.padChrome$; + const applyStyleOnLine = function (style, line) { + const chrome$ = helper.padChrome$; selectLine(line); - var $formattingButton = chrome$('.buttonicon-' + style); + const $formattingButton = chrome$(`.buttonicon-${style}`); $formattingButton.click(); - } + }; - var isButtonSelected = function(style) { - var chrome$ = helper.padChrome$; - var $formattingButton = chrome$('.buttonicon-' + style); - return $formattingButton.parent().hasClass('selected'); - } + const isButtonSelected = function (style) { + const chrome$ = helper.padChrome$; + const $formattingButton = chrome$(`.buttonicon-${style}`); + return $formattingButton.parent().hasClass('selected'); + }; - var selectLine = function(lineNumber, offsetStart, offsetEnd) { - var inner$ = helper.padInner$; - var $line = inner$("div").eq(lineNumber); + var selectLine = function (lineNumber, offsetStart, offsetEnd) { + const inner$ = helper.padInner$; + const $line = inner$('div').eq(lineNumber); helper.selectLines($line, $line, offsetStart, offsetEnd); - } + }; - var placeCaretOnLine = function(lineNumber) { - var inner$ = helper.padInner$; - var $line = inner$("div").eq(lineNumber); + const placeCaretOnLine = function (lineNumber) { + const inner$ = helper.padInner$; + const $line = inner$('div').eq(lineNumber); $line.sendkeys('{leftarrow}'); - } + }; - var undo = function() { - var $undoButton = helper.padChrome$(".buttonicon-undo"); + const undo = function () { + const $undoButton = helper.padChrome$('.buttonicon-undo'); $undoButton.click(); - } + }; - var testIfFormattingButtonIsDeselected = function(style) { - it('deselects the ' + style + ' button', function(done) { - helper.waitFor(function(){ - return isButtonSelected(style) === false; - }).done(done) + const testIfFormattingButtonIsDeselected = function (style) { + it(`deselects the ${style} button`, function (done) { + helper.waitFor(() => isButtonSelected(style) === false).done(done); }); - } + }; - var testIfFormattingButtonIsSelected = function(style) { - it('selects the ' + style + ' button', function(done) { - helper.waitFor(function(){ - return isButtonSelected(style); - }).done(done) + const testIfFormattingButtonIsSelected = function (style) { + it(`selects the ${style} button`, function (done) { + helper.waitFor(() => isButtonSelected(style)).done(done); }); - } + }; - var applyStyleOnLineAndSelectIt = function(line, style, cb) { + const applyStyleOnLineAndSelectIt = function (line, style, cb) { applyStyleOnLineOnFullLineAndRemoveSelection(line, style, selectLine, cb); - } + }; - var applyStyleOnLineAndPlaceCaretOnit = function(line, style, cb) { + const applyStyleOnLineAndPlaceCaretOnit = function (line, style, cb) { applyStyleOnLineOnFullLineAndRemoveSelection(line, style, placeCaretOnLine, cb); - } + }; - var applyStyleOnLineOnFullLineAndRemoveSelection = function(line, style, selectTarget, cb) { + var applyStyleOnLineOnFullLineAndRemoveSelection = function (line, style, selectTarget, cb) { // see if line html has changed - var inner$ = helper.padInner$; - var oldLineHTML = inner$.find("div")[line]; + const inner$ = helper.padInner$; + const oldLineHTML = inner$.find('div')[line]; applyStyleOnLine(style, line); - helper.waitFor(function(){ - var lineHTML = inner$.find("div")[line]; + helper.waitFor(() => { + const lineHTML = inner$.find('div')[line]; return lineHTML !== oldLineHTML; }); - // remove selection from previous line + // remove selection from previous line selectLine(line + 1); - //setTimeout(function() { - // select the text or place the caret on a position that - // has the formatting text applied previously - selectTarget(line); - cb(); - //}, 1000); - } + // setTimeout(function() { + // select the text or place the caret on a position that + // has the formatting text applied previously + selectTarget(line); + cb(); + // }, 1000); + }; - var pressFormattingShortcutOnSelection = function(key) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + const pressFormattingShortcutOnSelection = function (key) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - var e = inner$.Event(helper.evtType); + const e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = key.charCodeAt(0); // I, U, B, 5 - inner$("#innerdocbody").trigger(e); - } + inner$('#innerdocbody').trigger(e); + }; - STYLES.forEach(function(style){ - context('when selection is in a text with ' + style + ' applied', function(){ + STYLES.forEach((style) => { + context(`when selection is in a text with ${style} applied`, function () { before(function (done) { this.timeout(4000); applyStyleOnLineAndSelectIt(FIRST_LINE, style, done); @@ -112,7 +108,7 @@ describe("select formatting buttons when selection has style applied", function( testIfFormattingButtonIsSelected(style); }); - context('when caret is in a position with ' + style + ' applied', function(){ + context(`when caret is in a position with ${style} applied`, function () { before(function (done) { this.timeout(4000); applyStyleOnLineAndPlaceCaretOnit(FIRST_LINE, style, done); @@ -122,12 +118,12 @@ describe("select formatting buttons when selection has style applied", function( undo(); }); - testIfFormattingButtonIsSelected(style) + testIfFormattingButtonIsSelected(style); }); }); - context('when user applies a style and the selection does not change', function() { - var style = STYLES[0]; // italic + context('when user applies a style and the selection does not change', function () { + const style = STYLES[0]; // italic before(function () { applyStyleOnLine(style, FIRST_LINE); }); @@ -143,16 +139,16 @@ describe("select formatting buttons when selection has style applied", function( }); }); - SHORTCUT_KEYS.forEach(function(key, index){ - var styleOfTheShortcut = STYLES[index]; // italic, bold, ... - context('when user presses CMD + ' + key, function() { + SHORTCUT_KEYS.forEach((key, index) => { + const styleOfTheShortcut = STYLES[index]; // italic, bold, ... + context(`when user presses CMD + ${key}`, function () { before(function () { pressFormattingShortcutOnSelection(key); }); testIfFormattingButtonIsSelected(styleOfTheShortcut); - context('and user presses CMD + ' + key + ' again', function() { + context(`and user presses CMD + ${key} again`, function () { before(function () { pressFormattingShortcutOnSelection(key); }); diff --git a/tests/frontend/specs/strikethrough.js b/tests/frontend/specs/strikethrough.js index dc37b36f4..d8feae3be 100644 --- a/tests/frontend/specs/strikethrough.js +++ b/tests/frontend/specs/strikethrough.js @@ -1,34 +1,34 @@ -describe("strikethrough button", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('strikethrough button', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("makes text strikethrough", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('makes text strikethrough', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - //get the strikethrough button and click it - var $strikethroughButton = chrome$(".buttonicon-strikethrough"); + // get the strikethrough button and click it + const $strikethroughButton = chrome$('.buttonicon-strikethrough'); $strikethroughButton.click(); - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); + // ace creates a new dom element when you press a button, so just get the first text element again + const $newFirstTextElement = inner$('div').first(); // is there a element now? - var isstrikethrough = $newFirstTextElement.find("s").length === 1; + const isstrikethrough = $newFirstTextElement.find('s').length === 1; - //expect it to be strikethrough + // expect it to be strikethrough expect(isstrikethrough).to.be(true); - //make sure the text hasn't changed + // make sure the text hasn't changed expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); done(); diff --git a/tests/frontend/specs/timeslider.js b/tests/frontend/specs/timeslider.js index bca80ba49..f0d74b1ef 100644 --- a/tests/frontend/specs/timeslider.js +++ b/tests/frontend/specs/timeslider.js @@ -1,47 +1,42 @@ -//deactivated, we need a nice way to get the timeslider, this is ugly -xdescribe("timeslider button takes you to the timeslider of a pad", function(){ - beforeEach(function(cb){ +// deactivated, we need a nice way to get the timeslider, this is ugly +xdescribe('timeslider button takes you to the timeslider of a pad', function () { + beforeEach(function (cb) { helper.newPad(cb); // creates a new pad this.timeout(60000); }); - it("timeslider contained in URL", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('timeslider contained in URL', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value - var newValue = "Testing"+originalValue; - $firstTextElement.sendkeys("Testing"); // send line 1 to the pad + const $firstTextElement = inner$('div span').first(); + const originalValue = $firstTextElement.text(); // get the original value + const newValue = `Testing${originalValue}`; + $firstTextElement.sendkeys('Testing'); // send line 1 to the pad - var modifiedValue = $firstTextElement.text(); // get the modified value + const modifiedValue = $firstTextElement.text(); // get the modified value expect(modifiedValue).not.to.be(originalValue); // expect the value to change - helper.waitFor(function(){ - return modifiedValue !== originalValue; // The value has changed so we can.. - }).done(function(){ - - var $timesliderButton = chrome$("#timesliderlink"); + helper.waitFor(() => modifiedValue !== originalValue, // The value has changed so we can.. + ).done(() => { + const $timesliderButton = chrome$('#timesliderlink'); $timesliderButton.click(); // So click the timeslider link - helper.waitFor(function(){ - var iFrameURL = chrome$.window.location.href; - if(iFrameURL){ - return iFrameURL.indexOf("timeslider") !== -1; - }else{ + helper.waitFor(() => { + const iFrameURL = chrome$.window.location.href; + if (iFrameURL) { + return iFrameURL.indexOf('timeslider') !== -1; + } else { return false; // the URL hasnt been set yet } - }).done(function(){ + }).done(() => { // click the buttons - var iFrameURL = chrome$.window.location.href; // get the url - var inTimeslider = iFrameURL.indexOf("timeslider") !== -1; + const iFrameURL = chrome$.window.location.href; // get the url + const inTimeslider = iFrameURL.indexOf('timeslider') !== -1; expect(inTimeslider).to.be(true); // expect the value to change done(); }); - - }); }); }); - diff --git a/tests/frontend/specs/timeslider_follow.js b/tests/frontend/specs/timeslider_follow.js index cf03a4db6..55502d869 100644 --- a/tests/frontend/specs/timeslider_follow.js +++ b/tests/frontend/specs/timeslider_follow.js @@ -1,32 +1,32 @@ -describe("timeslider follow", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('timeslider follow', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); }); - it("content as it's added to timeslider", async function() { + it("content as it's added to timeslider", async function () { // send 6 revisions - let revs = 6; - let message = 'a\n\n\n\n\n\n\n\n\n\n'; - let newLines = message.split('\n').length - for (let i=0;i helper.contentWindow().location.hash === '#0'); - let originalTop = helper.contentWindow().$('#innerdocbody').offset(); + const originalTop = helper.contentWindow().$('#innerdocbody').offset(); // set to follow contents as it arrives - helper.contentWindow().$('#options-followContents').prop("checked", true); + helper.contentWindow().$('#options-followContents').prop('checked', true); helper.contentWindow().$('#playpause_button_icon').click(); let newTop; - return helper.waitForPromise(function(){ + return helper.waitForPromise(() => { newTop = helper.contentWindow().$('#innerdocbody').offset(); return newTop.top < originalTop.top; - }) + }); }); /** @@ -35,31 +35,28 @@ describe("timeslider follow", function(){ * the change is applied. * */ - it("only to lines that exist in the current pad view, see #4389", async function(){ + it('only to lines that exist in the current pad view, see #4389', async function () { // Select everything and clear via delete key - let e = helper.padInner$.Event(helper.evtType); - e.keyCode = 8; //delete key - let lines = helper.linesDiv(); + const e = helper.padInner$.Event(helper.evtType); + e.keyCode = 8; // delete key + const lines = helper.linesDiv(); helper.selectLines(lines[0], lines[lines.length - 1]); // select all lines // probably unnecessary, but wait for the selection to be Range not Caret - await helper.waitForPromise(function(){ - return !helper.padInner$.document.getSelection().isCollapsed; - //only supported in FF57+ - //return helper.padInner$.document.getSelection().type === 'Range'; - }) + await helper.waitForPromise(() => !helper.padInner$.document.getSelection().isCollapsed, + // only supported in FF57+ + // return helper.padInner$.document.getSelection().type === 'Range'; + ); helper.padInner$('#innerdocbody').trigger(e); - await helper.waitForPromise(function(){ - return helper.commits.length === 1; - }) - await helper.edit("Test line\n\n") - await helper.edit("Another test line", 3) + await helper.waitForPromise(() => helper.commits.length === 1); + await helper.edit('Test line\n\n'); + await helper.edit('Another test line', 3); await helper.gotoTimeslider(); // set to follow contents as it arrives - helper.contentWindow().$('#options-followContents').prop("checked", true); + helper.contentWindow().$('#options-followContents').prop('checked', true); - let oldYPosition = helper.contentWindow().$("#editorcontainerbox")[0].scrollTop; + const oldYPosition = helper.contentWindow().$('#editorcontainerbox')[0].scrollTop; expect(oldYPosition).to.be(0); /** @@ -71,50 +68,37 @@ describe("timeslider follow", function(){ // line 3 changed helper.contentWindow().$('#leftstep').click(); - await helper.waitForPromise(function(){ - return hasFollowedToLine(3); - }) + await helper.waitForPromise(() => hasFollowedToLine(3)); // line 1 is the first line that changed helper.contentWindow().$('#leftstep').click(); - await helper.waitForPromise(function(){ - return hasFollowedToLine(1); - }) + await helper.waitForPromise(() => hasFollowedToLine(1)); // line 1 changed helper.contentWindow().$('#leftstep').click(); - await helper.waitForPromise(function(){ - return hasFollowedToLine(1); - }) + await helper.waitForPromise(() => hasFollowedToLine(1)); // line 1 changed helper.contentWindow().$('#rightstep').click(); - await helper.waitForPromise(function(){ - return hasFollowedToLine(1); - }) + await helper.waitForPromise(() => hasFollowedToLine(1)); // line 1 is the first line that changed helper.contentWindow().$('#rightstep').click(); - await helper.waitForPromise(function(){ - return hasFollowedToLine(1); - }) + await helper.waitForPromise(() => hasFollowedToLine(1)); // line 3 changed helper.contentWindow().$('#rightstep').click(); - return helper.waitForPromise(function(){ - return hasFollowedToLine(3); - }) - }) + return helper.waitForPromise(() => hasFollowedToLine(3)); + }); }); /** - * @param {number} lineNum + * @param {number} lineNum * @returns {boolean} scrolled to the lineOffset? */ function hasFollowedToLine(lineNum) { - let scrollPosition = helper.contentWindow().$("#editorcontainerbox")[0].scrollTop; - let lineOffset = helper.contentWindow().$('#innerdocbody').find(`div:nth-child(${lineNum})`)[0].offsetTop; + const scrollPosition = helper.contentWindow().$('#editorcontainerbox')[0].scrollTop; + const lineOffset = helper.contentWindow().$('#innerdocbody').find(`div:nth-child(${lineNum})`)[0].offsetTop; return Math.abs(scrollPosition - lineOffset) < 1; } - diff --git a/tests/frontend/specs/timeslider_labels.js b/tests/frontend/specs/timeslider_labels.js index 44ead144b..c7a4aca5a 100644 --- a/tests/frontend/specs/timeslider_labels.js +++ b/tests/frontend/specs/timeslider_labels.js @@ -1,37 +1,37 @@ -describe("timeslider", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('timeslider', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); }); /** * @todo test authorsList */ - it("Shows a date and time in the timeslider and make sure it doesn't include NaN", async function() { + it("Shows a date and time in the timeslider and make sure it doesn't include NaN", async function () { // make some changes to produce 3 revisions - let revs = 3; + const revs = 3; - for(let i=0; i < revs; i++) { + for (let i = 0; i < revs; i++) { await helper.edit('a\n'); } await helper.gotoTimeslider(revs); - await helper.waitForPromise(function(){return helper.contentWindow().location.hash === '#'+revs}) + await helper.waitForPromise(() => helper.contentWindow().location.hash === `#${revs}`); // the datetime of last edit - let timerTimeLast = new Date(helper.timesliderTimerTime()).getTime(); + const timerTimeLast = new Date(helper.timesliderTimerTime()).getTime(); // the day of this revision, e.g. August 12, 2020 (stripped the string "Saved") - let dateLast = new Date(helper.revisionDateElem().substr(6)).getTime(); + const dateLast = new Date(helper.revisionDateElem().substr(6)).getTime(); // the label/revision, ie Version 3 - let labelLast = helper.revisionLabelElem().text(); + const labelLast = helper.revisionLabelElem().text(); // the datetime should be a date - expect( Number.isNaN(timerTimeLast)).to.eql(false); + expect(Number.isNaN(timerTimeLast)).to.eql(false); // the Date object of the day should not be NaN - expect( Number.isNaN(dateLast) ).to.eql(false) + expect(Number.isNaN(dateLast)).to.eql(false); // the label should be Version `Number` expect(labelLast).to.be(`Version ${revs}`); @@ -40,23 +40,23 @@ describe("timeslider", function(){ helper.sliderClick(1); // the datetime of last edit - let timerTime = new Date(helper.timesliderTimerTime()).getTime(); + const timerTime = new Date(helper.timesliderTimerTime()).getTime(); // the day of this revision, e.g. August 12, 2020 - let date = new Date(helper.revisionDateElem().substr(6)).getTime(); + const date = new Date(helper.revisionDateElem().substr(6)).getTime(); // the label/revision, e.g. Version 0 - let label = helper.revisionLabelElem().text(); + const label = helper.revisionLabelElem().text(); // the datetime should be a date - expect( Number.isNaN(timerTime)).to.eql(false); + expect(Number.isNaN(timerTime)).to.eql(false); // the last revision should be newer or have the same time expect(timerTimeLast).to.not.be.lessThan(timerTime); // the Date object of the day should not be NaN - expect( Number.isNaN(date) ).to.eql(false) + expect(Number.isNaN(date)).to.eql(false); // the label should be Version 0 - expect( label ).to.be('Version 0'); + expect(label).to.be('Version 0'); }); }); diff --git a/tests/frontend/specs/timeslider_numeric_padID.js b/tests/frontend/specs/timeslider_numeric_padID.js index 1276b86a5..53eb4a29c 100644 --- a/tests/frontend/specs/timeslider_numeric_padID.js +++ b/tests/frontend/specs/timeslider_numeric_padID.js @@ -1,29 +1,29 @@ -describe("timeslider", function(){ - var padId = 735773577357+(Math.round(Math.random()*1000)); +describe('timeslider', function () { + const padId = 735773577357 + (Math.round(Math.random() * 1000)); - //create a new pad before each test run - beforeEach(function(cb){ + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb, padId); }); - it("Makes sure the export URIs are as expected when the padID is numeric", async function() { + it('Makes sure the export URIs are as expected when the padID is numeric', async function () { await helper.edit('a\n'); await helper.gotoTimeslider(1); // ensure we are on revision 1 - await helper.waitForPromise(function(){return helper.contentWindow().location.hash === '#1'}) + await helper.waitForPromise(() => helper.contentWindow().location.hash === '#1'); // expect URI to be similar to // http://192.168.1.48:9001/p/2/1/export/html // http://192.168.1.48:9001/p/735773577399/1/export/html - let rev1ExportLink = helper.contentWindow().$('#exporthtmla').attr('href'); + const rev1ExportLink = helper.contentWindow().$('#exporthtmla').attr('href'); expect(rev1ExportLink).to.contain('/1/export/html'); // Click somewhere left on the timeslider to go to revision 0 helper.sliderClick(30); - let rev0ExportLink = helper.contentWindow().$('#exporthtmla').attr('href'); + const rev0ExportLink = helper.contentWindow().$('#exporthtmla').attr('href'); expect(rev0ExportLink).to.contain('/0/export/html'); }); }); diff --git a/tests/frontend/specs/timeslider_revisions.js b/tests/frontend/specs/timeslider_revisions.js index 8fa7f5514..fbfbb3615 100644 --- a/tests/frontend/specs/timeslider_revisions.js +++ b/tests/frontend/specs/timeslider_revisions.js @@ -1,42 +1,42 @@ -describe("timeslider", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('timeslider', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("loads adds a hundred revisions", function(done) { // passes - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('loads adds a hundred revisions', function (done) { // passes + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // make some changes to produce 100 revisions - var timePerRev = 900 - , revs = 99; - this.timeout(revs*timePerRev+10000); - for(var i=0; i < revs; i++) { - setTimeout(function() { + const timePerRev = 900; + const revs = 99; + this.timeout(revs * timePerRev + 10000); + for (let i = 0; i < revs; i++) { + setTimeout(() => { // enter 'a' in the first text element - inner$("div").first().sendkeys('a'); - }, timePerRev*i); + inner$('div').first().sendkeys('a'); + }, timePerRev * i); } chrome$('.buttonicon-savedRevision').click(); - setTimeout(function() { + setTimeout(() => { // go to timeslider - $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider'); + $('#iframe-container iframe').attr('src', `${$('#iframe-container iframe').attr('src')}/timeslider`); - setTimeout(function() { - var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; - var $sliderBar = timeslider$('#ui-slider-bar'); + setTimeout(() => { + const timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; + const $sliderBar = timeslider$('#ui-slider-bar'); - var latestContents = timeslider$('#innerdocbody').text(); + const latestContents = timeslider$('#innerdocbody').text(); // Click somewhere on the timeslider - var e = new jQuery.Event('mousedown'); + let e = new jQuery.Event('mousedown'); // sets y co-ordinate of the pad slider modal. - var base = (timeslider$('#ui-slider-bar').offset().top - 24) + const base = (timeslider$('#ui-slider-bar').offset().top - 24); e.clientX = e.pageX = 150; - e.clientY = e.pageY = base+5; + e.clientY = e.pageY = base + 5; $sliderBar.trigger(e); e = new jQuery.Event('mousedown'); @@ -46,134 +46,127 @@ describe("timeslider", function(){ e = new jQuery.Event('mousedown'); e.clientX = e.pageX = 150; - e.clientY = e.pageY = base-5; + e.clientY = e.pageY = base - 5; $sliderBar.trigger(e); - $sliderBar.trigger('mouseup') + $sliderBar.trigger('mouseup'); - setTimeout(function() { - //make sure the text has changed - expect( timeslider$('#innerdocbody').text() ).not.to.eql( latestContents ); - var starIsVisible = timeslider$('.star').is(":visible"); - expect( starIsVisible ).to.eql( true ); + setTimeout(() => { + // make sure the text has changed + expect(timeslider$('#innerdocbody').text()).not.to.eql(latestContents); + const starIsVisible = timeslider$('.star').is(':visible'); + expect(starIsVisible).to.eql(true); done(); }, 1000); - }, 6000); - }, revs*timePerRev); + }, revs * timePerRev); }); // Disabled as jquery trigger no longer works properly - xit("changes the url when clicking on the timeslider", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + xit('changes the url when clicking on the timeslider', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // make some changes to produce 7 revisions - var timePerRev = 1000 - , revs = 20; - this.timeout(revs*timePerRev+10000); - for(var i=0; i < revs; i++) { - setTimeout(function() { + const timePerRev = 1000; + const revs = 20; + this.timeout(revs * timePerRev + 10000); + for (let i = 0; i < revs; i++) { + setTimeout(() => { // enter 'a' in the first text element - inner$("div").first().sendkeys('a'); - }, timePerRev*i); + inner$('div').first().sendkeys('a'); + }, timePerRev * i); } - setTimeout(function() { + setTimeout(() => { // go to timeslider - $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider'); + $('#iframe-container iframe').attr('src', `${$('#iframe-container iframe').attr('src')}/timeslider`); - setTimeout(function() { - var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; - var $sliderBar = timeslider$('#ui-slider-bar'); + setTimeout(() => { + const timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; + const $sliderBar = timeslider$('#ui-slider-bar'); - var latestContents = timeslider$('#innerdocbody').text(); - var oldUrl = $('#iframe-container iframe')[0].contentWindow.location.hash; + const latestContents = timeslider$('#innerdocbody').text(); + const oldUrl = $('#iframe-container iframe')[0].contentWindow.location.hash; // Click somewhere on the timeslider - var e = new jQuery.Event('mousedown'); + const e = new jQuery.Event('mousedown'); e.clientX = e.pageX = 150; e.clientY = e.pageY = 60; $sliderBar.trigger(e); - helper.waitFor(function(){ - return $('#iframe-container iframe')[0].contentWindow.location.hash != oldUrl; - }, 6000).always(function(){ - expect( $('#iframe-container iframe')[0].contentWindow.location.hash ).not.to.eql( oldUrl ); + helper.waitFor(() => $('#iframe-container iframe')[0].contentWindow.location.hash != oldUrl, 6000).always(() => { + expect($('#iframe-container iframe')[0].contentWindow.location.hash).not.to.eql(oldUrl); done(); }); }, 6000); - }, revs*timePerRev); + }, revs * timePerRev); }); - it("jumps to a revision given in the url", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('jumps to a revision given in the url', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; this.timeout(40000); // wait for the text to be loaded - helper.waitFor(function(){ - return inner$('body').text().length != 0; - }, 10000).always(function() { - var newLines = inner$('body div').length; - var oldLength = inner$('body').text().length + newLines / 2; - expect( oldLength ).to.not.eql( 0 ); - inner$("div").first().sendkeys('a'); - var timeslider$; + helper.waitFor(() => inner$('body').text().length != 0, 10000).always(() => { + const newLines = inner$('body div').length; + const oldLength = inner$('body').text().length + newLines / 2; + expect(oldLength).to.not.eql(0); + inner$('div').first().sendkeys('a'); + let timeslider$; // wait for our additional revision to be added - helper.waitFor(function(){ + helper.waitFor(() => { // newLines takes the new lines into account which are strippen when using // inner$('body').text(), one
                is used for one line in ACE. - var lenOkay = inner$('body').text().length + newLines / 2 != oldLength; + const lenOkay = inner$('body').text().length + newLines / 2 != oldLength; // this waits for the color to be added to our , which means that the revision // was accepted by the server. - var colorOkay = inner$('span').first().attr('class').indexOf("author-") == 0; + const colorOkay = inner$('span').first().attr('class').indexOf('author-') == 0; return lenOkay && colorOkay; - }, 10000).always(function() { + }, 10000).always(() => { // go to timeslider with a specific revision set - $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider#0'); + $('#iframe-container iframe').attr('src', `${$('#iframe-container iframe').attr('src')}/timeslider#0`); // wait for the timeslider to be loaded - helper.waitFor(function(){ + helper.waitFor(() => { try { timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; - } catch(e){} - if(timeslider$){ + } catch (e) {} + if (timeslider$) { return timeslider$('#innerdocbody').text().length == oldLength; } - }, 10000).always(function(){ - expect( timeslider$('#innerdocbody').text().length ).to.eql( oldLength ); + }, 10000).always(() => { + expect(timeslider$('#innerdocbody').text().length).to.eql(oldLength); done(); }); }); }); }); - it("checks the export url", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('checks the export url', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; this.timeout(11000); - inner$("div").first().sendkeys('a'); + inner$('div').first().sendkeys('a'); - setTimeout(function() { + setTimeout(() => { // go to timeslider - $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider#0'); - var timeslider$; - var exportLink; + $('#iframe-container iframe').attr('src', `${$('#iframe-container iframe').attr('src')}/timeslider#0`); + let timeslider$; + let exportLink; - helper.waitFor(function(){ - try{ + helper.waitFor(() => { + try { timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; - }catch(e){} - if(!timeslider$) - return false; + } catch (e) {} + if (!timeslider$) return false; exportLink = timeslider$('#exportplaina').attr('href'); - if(!exportLink) - return false; - return exportLink.substr(exportLink.length - 12) == "0/export/txt"; - }, 6000).always(function(){ - expect( exportLink.substr(exportLink.length - 12) ).to.eql( "0/export/txt" ); + if (!exportLink) return false; + return exportLink.substr(exportLink.length - 12) == '0/export/txt'; + }, 6000).always(() => { + expect(exportLink.substr(exportLink.length - 12)).to.eql('0/export/txt'); done(); }); }, 2500); diff --git a/tests/frontend/specs/undo.js b/tests/frontend/specs/undo.js index 172a2b81e..0c94f2230 100644 --- a/tests/frontend/specs/undo.js +++ b/tests/frontend/specs/undo.js @@ -1,61 +1,54 @@ -describe("undo button", function(){ - beforeEach(function(cb){ +describe('undo button', function () { + beforeEach(function (cb) { helper.newPad(cb); // creates a new pad this.timeout(60000); }); - it("undo some typing by clicking undo button", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('undo some typing by clicking undo button', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value + const $firstTextElement = inner$('div span').first(); + const originalValue = $firstTextElement.text(); // get the original value - $firstTextElement.sendkeys("foo"); // send line 1 to the pad - var modifiedValue = $firstTextElement.text(); // get the modified value + $firstTextElement.sendkeys('foo'); // send line 1 to the pad + const modifiedValue = $firstTextElement.text(); // get the modified value expect(modifiedValue).not.to.be(originalValue); // expect the value to change // get clear authorship button as a variable - var $undoButton = chrome$(".buttonicon-undo"); + const $undoButton = chrome$('.buttonicon-undo'); // click the button $undoButton.click(); - helper.waitFor(function(){ - return inner$("div span").first().text() === originalValue; - }).done(function(){ - var finalValue = inner$("div span").first().text(); + helper.waitFor(() => inner$('div span').first().text() === originalValue).done(() => { + const finalValue = inner$('div span').first().text(); expect(finalValue).to.be(originalValue); // expect the value to change done(); }); }); - it("undo some typing using a keypress", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('undo some typing using a keypress', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value + const $firstTextElement = inner$('div span').first(); + const originalValue = $firstTextElement.text(); // get the original value - $firstTextElement.sendkeys("foo"); // send line 1 to the pad - var modifiedValue = $firstTextElement.text(); // get the modified value + $firstTextElement.sendkeys('foo'); // send line 1 to the pad + const modifiedValue = $firstTextElement.text(); // get the modified value expect(modifiedValue).not.to.be(originalValue); // expect the value to change - var e = inner$.Event(helper.evtType); + const e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 90; // z - inner$("#innerdocbody").trigger(e); + inner$('#innerdocbody').trigger(e); - helper.waitFor(function(){ - return inner$("div span").first().text() === originalValue; - }).done(function(){ - var finalValue = inner$("div span").first().text(); + helper.waitFor(() => inner$('div span').first().text() === originalValue).done(() => { + const finalValue = inner$('div span').first().text(); expect(finalValue).to.be(originalValue); // expect the value to change done(); }); }); - - }); - diff --git a/tests/frontend/specs/unordered_list.js b/tests/frontend/specs/unordered_list.js index 2af843d61..4cbdabfac 100644 --- a/tests/frontend/specs/unordered_list.js +++ b/tests/frontend/specs/unordered_list.js @@ -1,177 +1,162 @@ -describe("assign unordered list", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('assign unordered list', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("insert unordered list text then removes by outdent", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - var originalText = inner$("div").first().text(); + it('insert unordered list text then removes by outdent', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; + const originalText = inner$('div').first().text(); - var $insertunorderedlistButton = chrome$(".buttonicon-insertunorderedlist"); + const $insertunorderedlistButton = chrome$('.buttonicon-insertunorderedlist'); $insertunorderedlistButton.click(); - helper.waitFor(function(){ - var newText = inner$("div").first().text(); - if(newText === originalText){ - return inner$("div").first().find("ul li").length === 1; + helper.waitFor(() => { + const newText = inner$('div').first().text(); + if (newText === originalText) { + return inner$('div').first().find('ul li').length === 1; } - }).done(function(){ - + }).done(() => { // remove indentation by bullet and ensure text string remains the same - chrome$(".buttonicon-outdent").click(); - helper.waitFor(function(){ - var newText = inner$("div").first().text(); + chrome$('.buttonicon-outdent').click(); + helper.waitFor(() => { + const newText = inner$('div').first().text(); return (newText === originalText); - }).done(function(){ + }).done(() => { done(); }); - }); }); - }); -describe("unassign unordered list", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('unassign unordered list', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("insert unordered list text then remove by clicking list again", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - var originalText = inner$("div").first().text(); + it('insert unordered list text then remove by clicking list again', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; + const originalText = inner$('div').first().text(); - var $insertunorderedlistButton = chrome$(".buttonicon-insertunorderedlist"); + const $insertunorderedlistButton = chrome$('.buttonicon-insertunorderedlist'); $insertunorderedlistButton.click(); - helper.waitFor(function(){ - var newText = inner$("div").first().text(); - if(newText === originalText){ - return inner$("div").first().find("ul li").length === 1; + helper.waitFor(() => { + const newText = inner$('div').first().text(); + if (newText === originalText) { + return inner$('div').first().find('ul li').length === 1; } - }).done(function(){ - + }).done(() => { // remove indentation by bullet and ensure text string remains the same $insertunorderedlistButton.click(); - helper.waitFor(function(){ - var isList = inner$("div").find("ul").length === 1; + helper.waitFor(() => { + const isList = inner$('div').find('ul').length === 1; // sohuldn't be list return (isList === false); - }).done(function(){ + }).done(() => { done(); }); - }); }); }); -describe("keep unordered list on enter key", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('keep unordered list on enter key', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("Keeps the unordered list on enter for the new line", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('Keeps the unordered list on enter for the new line', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - var $insertorderedlistButton = chrome$(".buttonicon-insertunorderedlist"); + const $insertorderedlistButton = chrome$('.buttonicon-insertunorderedlist'); $insertorderedlistButton.click(); - //type a bit, make a line break and type again - var $firstTextElement = inner$("div span").first(); + // type a bit, make a line break and type again + const $firstTextElement = inner$('div span').first(); $firstTextElement.sendkeys('line 1'); $firstTextElement.sendkeys('{enter}'); $firstTextElement.sendkeys('line 2'); $firstTextElement.sendkeys('{enter}'); - helper.waitFor(function(){ - return inner$("div span").first().text().indexOf("line 2") === -1; - }).done(function(){ - var $newSecondLine = inner$("div").first().next(); - var hasULElement = $newSecondLine.find("ul li").length === 1; + helper.waitFor(() => inner$('div span').first().text().indexOf('line 2') === -1).done(() => { + const $newSecondLine = inner$('div').first().next(); + const hasULElement = $newSecondLine.find('ul li').length === 1; expect(hasULElement).to.be(true); - expect($newSecondLine.text()).to.be("line 2"); + expect($newSecondLine.text()).to.be('line 2'); done(); }); }); - }); -describe("Pressing Tab in an UL increases and decreases indentation", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('Pressing Tab in an UL increases and decreases indentation', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("indent and de-indent list item with keypress", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('indent and de-indent list item with keypress', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - var $insertorderedlistButton = chrome$(".buttonicon-insertunorderedlist"); + const $insertorderedlistButton = chrome$('.buttonicon-insertunorderedlist'); $insertorderedlistButton.click(); - var e = inner$.Event(helper.evtType); + const e = inner$.Event(helper.evtType); e.keyCode = 9; // tab - inner$("#innerdocbody").trigger(e); + inner$('#innerdocbody').trigger(e); - expect(inner$("div").first().find(".list-bullet2").length === 1).to.be(true); + expect(inner$('div').first().find('.list-bullet2').length === 1).to.be(true); e.shiftKey = true; // shift e.keyCode = 9; // tab - inner$("#innerdocbody").trigger(e); - - helper.waitFor(function(){ - return inner$("div").first().find(".list-bullet1").length === 1; - }).done(done); + inner$('#innerdocbody').trigger(e); + helper.waitFor(() => inner$('div').first().find('.list-bullet1').length === 1).done(done); }); - }); -describe("Pressing indent/outdent button in an UL increases and decreases indentation and bullet / ol formatting", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('Pressing indent/outdent button in an UL increases and decreases indentation and bullet / ol formatting', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("indent and de-indent list item with indent button", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('indent and de-indent list item with indent button', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const $firstTextElement = inner$('div').first(); - //select this text element + // select this text element $firstTextElement.sendkeys('{selectall}'); - var $insertunorderedlistButton = chrome$(".buttonicon-insertunorderedlist"); + const $insertunorderedlistButton = chrome$('.buttonicon-insertunorderedlist'); $insertunorderedlistButton.click(); - var $indentButton = chrome$(".buttonicon-indent"); + const $indentButton = chrome$('.buttonicon-indent'); $indentButton.click(); // make it indented twice - expect(inner$("div").first().find(".list-bullet2").length === 1).to.be(true); - var $outdentButton = chrome$(".buttonicon-outdent"); + expect(inner$('div').first().find('.list-bullet2').length === 1).to.be(true); + const $outdentButton = chrome$('.buttonicon-outdent'); $outdentButton.click(); // make it deindented to 1 - helper.waitFor(function(){ - return inner$("div").first().find(".list-bullet1").length === 1; - }).done(done); + helper.waitFor(() => inner$('div').first().find('.list-bullet1').length === 1).done(done); }); }); - diff --git a/tests/frontend/specs/urls_become_clickable.js b/tests/frontend/specs/urls_become_clickable.js index 7f5e30679..422a287f9 100644 --- a/tests/frontend/specs/urls_become_clickable.js +++ b/tests/frontend/specs/urls_become_clickable.js @@ -1,56 +1,54 @@ -describe("urls", function(){ - //create a new pad before each test run - beforeEach(function(cb){ +describe('urls', function () { + // create a new pad before each test run + beforeEach(function (cb) { helper.newPad(cb); this.timeout(60000); }); - it("when you enter an url, it becomes clickable", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('when you enter an url, it becomes clickable', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var firstTextElement = inner$("div").first(); + // get the first text element out of the inner iframe + const firstTextElement = inner$('div').first(); // simulate key presses to delete content firstTextElement.sendkeys('{selectall}'); // select all firstTextElement.sendkeys('{del}'); // clear the first line firstTextElement.sendkeys('https://etherpad.org'); // insert a URL - helper.waitFor(function(){ - return inner$("div").first().find("a").length === 1; - }, 2000).done(done); + helper.waitFor(() => inner$('div').first().find('a').length === 1, 2000).done(done); }); - it("when you enter a url containing a !, it becomes clickable and contains the whole URL", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('when you enter a url containing a !, it becomes clickable and contains the whole URL', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var firstTextElement = inner$("div").first(); - var url = "https://etherpad.org/!foo"; + // get the first text element out of the inner iframe + const firstTextElement = inner$('div').first(); + const url = 'https://etherpad.org/!foo'; // simulate key presses to delete content firstTextElement.sendkeys('{selectall}'); // select all firstTextElement.sendkeys('{del}'); // clear the first line firstTextElement.sendkeys(url); // insert a URL - helper.waitFor(function(){ - if(inner$("div").first().find("a").length === 1){ // if it contains an A link - if(inner$("div").first().find("a")[0].href === url){ + helper.waitFor(() => { + if (inner$('div').first().find('a').length === 1) { // if it contains an A link + if (inner$('div').first().find('a')[0].href === url) { return true; } - }; + } }, 2000).done(done); }); - it("when you enter a url followed by a ], the ] is not included in the URL", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + it('when you enter a url followed by a ], the ] is not included in the URL', function (done) { + const inner$ = helper.padInner$; + const chrome$ = helper.padChrome$; - //get the first text element out of the inner iframe - var firstTextElement = inner$("div").first(); - var url = "https://etherpad.org/"; + // get the first text element out of the inner iframe + const firstTextElement = inner$('div').first(); + const url = 'https://etherpad.org/'; // simulate key presses to delete content firstTextElement.sendkeys('{selectall}'); // select all @@ -58,13 +56,12 @@ describe("urls", function(){ firstTextElement.sendkeys(url); // insert a URL firstTextElement.sendkeys(']'); // put a ] after it - helper.waitFor(function(){ - if(inner$("div").first().find("a").length === 1){ // if it contains an A link - if(inner$("div").first().find("a")[0].href === url){ + helper.waitFor(() => { + if (inner$('div').first().find('a').length === 1) { // if it contains an A link + if (inner$('div').first().find('a')[0].href === url) { return true; } - }; + } }, 2000).done(done); }); - }); diff --git a/tests/frontend/specs/xxauto_reconnect.js b/tests/frontend/specs/xxauto_reconnect.js index e2d2df36a..574616ce5 100644 --- a/tests/frontend/specs/xxauto_reconnect.js +++ b/tests/frontend/specs/xxauto_reconnect.js @@ -1,48 +1,46 @@ -describe('Automatic pad reload on Force Reconnect message', function() { - var padId, $originalPadFrame; +describe('Automatic pad reload on Force Reconnect message', function () { + let padId, $originalPadFrame; - beforeEach(function(done) { - padId = helper.newPad(function() { + beforeEach(function (done) { + padId = helper.newPad(() => { // enable userdup error to have timer to force reconnect - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + const $errorMessageModal = helper.padChrome$('#connectivity .userdup'); $errorMessageModal.addClass('with_reconnect_timer'); // make sure there's a timeout set, otherwise automatic reconnect won't be enabled helper.padChrome$.window.clientVars.automaticReconnectionTimeout = 2; // open same pad on another iframe, to force userdup error - var $otherIframeWithSamePad = $(''); + const $otherIframeWithSamePad = $(``); $originalPadFrame = $('#iframe-container iframe'); $otherIframeWithSamePad.insertAfter($originalPadFrame); // wait for modal to be displayed - helper.waitFor(function() { - return $errorMessageModal.is(':visible'); - }, 50000).done(done); + helper.waitFor(() => $errorMessageModal.is(':visible'), 50000).done(done); }); this.timeout(60000); }); - it('displays a count down timer to automatically reconnect', function(done) { - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); - var $countDownTimer = $errorMessageModal.find('.reconnecttimer'); + it('displays a count down timer to automatically reconnect', function (done) { + const $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + const $countDownTimer = $errorMessageModal.find('.reconnecttimer'); expect($countDownTimer.is(':visible')).to.be(true); done(); }); - context('and user clicks on Cancel', function() { - beforeEach(function() { - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + context('and user clicks on Cancel', function () { + beforeEach(function () { + const $errorMessageModal = helper.padChrome$('#connectivity .userdup'); $errorMessageModal.find('#cancelreconnect').click(); }); - it('does not show Cancel button nor timer anymore', function(done) { - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); - var $countDownTimer = $errorMessageModal.find('.reconnecttimer'); - var $cancelButton = $errorMessageModal.find('#cancelreconnect'); + it('does not show Cancel button nor timer anymore', function (done) { + const $errorMessageModal = helper.padChrome$('#connectivity .userdup'); + const $countDownTimer = $errorMessageModal.find('.reconnecttimer'); + const $cancelButton = $errorMessageModal.find('#cancelreconnect'); expect($countDownTimer.is(':visible')).to.be(false); expect($cancelButton.is(':visible')).to.be(false); @@ -51,19 +49,17 @@ describe('Automatic pad reload on Force Reconnect message', function() { }); }); - context('and user does not click on Cancel until timer expires', function() { - var padWasReloaded = false; + context('and user does not click on Cancel until timer expires', function () { + let padWasReloaded = false; - beforeEach(function() { - $originalPadFrame.one('load', function() { + beforeEach(function () { + $originalPadFrame.one('load', () => { padWasReloaded = true; }); }); - it('reloads the pad', function(done) { - helper.waitFor(function() { - return padWasReloaded; - }, 5000).done(done); + it('reloads the pad', function (done) { + helper.waitFor(() => padWasReloaded, 5000).done(done); this.timeout(5000); }); diff --git a/tests/frontend/travis/remote_runner.js b/tests/frontend/travis/remote_runner.js index 0907b7c22..b2c9f3a00 100644 --- a/tests/frontend/travis/remote_runner.js +++ b/tests/frontend/travis/remote_runner.js @@ -1,13 +1,13 @@ -var srcFolder = "../../../src/node_modules/"; -var wd = require(srcFolder + "wd"); -var async = require(srcFolder + "async"); +var srcFolder = '../../../src/node_modules/'; +var wd = require(`${srcFolder}wd`); +var async = require(`${srcFolder}async`); var config = { - host: "ondemand.saucelabs.com" - , port: 80 - , username: process.env.SAUCE_USER - , accessKey: process.env.SAUCE_ACCESS_KEY -} + host: 'ondemand.saucelabs.com', + port: 80, + username: process.env.SAUCE_USER, + accessKey: process.env.SAUCE_ACCESS_KEY, +}; var allTestsPassed = true; // overwrite the default exit code @@ -20,111 +20,108 @@ process.on('exit', (code) => { } }) -var sauceTestWorker = async.queue(function (testSettings, callback) { - var browser = wd.promiseChainRemote(config.host, config.port, config.username, config.accessKey); - var name = process.env.GIT_HASH + " - " + testSettings.browserName + " " + testSettings.version + ", " + testSettings.platform; +var sauceTestWorker = async.queue((testSettings, callback) => { + const browser = wd.promiseChainRemote(config.host, config.port, config.username, config.accessKey); + const name = `${process.env.GIT_HASH} - ${testSettings.browserName} ${testSettings.version}, ${testSettings.platform}`; testSettings.name = name; - testSettings["public"] = true; - testSettings["build"] = process.env.GIT_HASH; - testSettings["extendedDebugging"] = true; // console.json can be downloaded via saucelabs, don't know how to print them into output of the tests - testSettings["tunnelIdentifier"] = process.env.TRAVIS_JOB_NUMBER; + testSettings.public = true; + testSettings.build = process.env.GIT_HASH; + testSettings.extendedDebugging = true; // console.json can be downloaded via saucelabs, don't know how to print them into output of the tests + testSettings.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER; - browser.init(testSettings).get("http://localhost:9001/tests/frontend/", function(){ - var url = "https://saucelabs.com/jobs/" + browser.sessionID; - console.log("Remote sauce test '" + name + "' started! " + url); + browser.init(testSettings).get('http://localhost:9001/tests/frontend/', () => { + const url = `https://saucelabs.com/jobs/${browser.sessionID}`; + console.log(`Remote sauce test '${name}' started! ${url}`); - //tear down the test excecution - var stopSauce = function(success,timesup){ - clearInterval(getStatusInterval); - clearTimeout(timeout); + // tear down the test excecution + const stopSauce = function (success, timesup) { + clearInterval(getStatusInterval); + clearTimeout(timeout); - browser.quit(function(){ - if(!success){ - allTestsPassed = false; - } + browser.quit(() => { + if (!success) { + allTestsPassed = false; + } - // if stopSauce is called via timeout (in contrast to via getStatusInterval) than the log of up to the last - // five seconds may not be available here. It's an error anyway, so don't care about it. - printLog(logIndex); + // if stopSauce is called via timeout (in contrast to via getStatusInterval) than the log of up to the last + // five seconds may not be available here. It's an error anyway, so don't care about it. + printLog(logIndex); - if (timesup) { - console.log("[" + testSettings.browserName + " " + testSettings.platform + (testSettings.version === "" ? '' : (" " + testSettings.version)) + "] \x1B[31mFAILED\x1B[39m allowed test duration exceeded"); - } - console.log("Remote sauce test '" + name + "' finished! " + url); + if (timesup) { + console.log(`[${testSettings.browserName} ${testSettings.platform}${testSettings.version === '' ? '' : (` ${testSettings.version}`)}] \x1B[31mFAILED\x1B[39m allowed test duration exceeded`); + } + console.log(`Remote sauce test '${name}' finished! ${url}`); - callback(); - }); - } + callback(); + }); + }; - /** + /** * timeout if a test hangs or the job exceeds 14.5 minutes * It's necessary because if travis kills the saucelabs session due to inactivity, we don't get any output * @todo this should be configured in testSettings, see https://wiki.saucelabs.com/display/DOCS/Test+Configuration+Options#TestConfigurationOptions-Timeouts */ - var timeout = setTimeout(function(){ - stopSauce(false,true); - }, 870000); // travis timeout is 15 minutes, set this to a slightly lower value + var timeout = setTimeout(() => { + stopSauce(false, true); + }, 870000); // travis timeout is 15 minutes, set this to a slightly lower value - var knownConsoleText = ""; - // how many characters of the log have been sent to travis - let logIndex = 0; - var getStatusInterval = setInterval(function(){ - browser.eval("$('#console').text()", function(err, consoleText){ - if(!consoleText || err){ - return; - } - knownConsoleText = consoleText; + let knownConsoleText = ''; + // how many characters of the log have been sent to travis + let logIndex = 0; + var getStatusInterval = setInterval(() => { + browser.eval("$('#console').text()", (err, consoleText) => { + if (!consoleText || err) { + return; + } + knownConsoleText = consoleText; - if(knownConsoleText.indexOf("FINISHED") > 0){ - let match = knownConsoleText.match(/FINISHED.*([0-9]+) tests passed, ([0-9]+) tests failed/); - // finished without failures - if (match[2] && match[2] == '0'){ - stopSauce(true); + if (knownConsoleText.indexOf('FINISHED') > 0) { + const match = knownConsoleText.match(/FINISHED.*([0-9]+) tests passed, ([0-9]+) tests failed/); + // finished without failures + if (match[2] && match[2] == '0') { + stopSauce(true); // finished but some tests did not return or some tests failed - } else { - stopSauce(false); - } } else { - // not finished yet - printLog(logIndex); - logIndex = knownConsoleText.length; + stopSauce(false); } - }); - }, 5000); + } else { + // not finished yet + printLog(logIndex); + logIndex = knownConsoleText.length; + } + }); + }, 5000); - /** + /** * Replaces color codes in the test runners log, appends * browser name, platform etc. to every line and prints them. * * @param {number} index offset from where to start */ - function printLog(index){ - let testResult = knownConsoleText.substring(index).replace(/\[red\]/g,'\x1B[31m').replace(/\[yellow\]/g,'\x1B[33m') - .replace(/\[green\]/g,'\x1B[32m').replace(/\[clear\]/g, '\x1B[39m'); - testResult = testResult.split("\\n").map(function(line){ - return "[" + testSettings.browserName + " " + testSettings.platform + (testSettings.version === "" ? '' : (" " + testSettings.version)) + "] " + line; - }).join("\n"); + function printLog(index) { + let testResult = knownConsoleText.substring(index).replace(/\[red\]/g, '\x1B[31m').replace(/\[yellow\]/g, '\x1B[33m') + .replace(/\[green\]/g, '\x1B[32m').replace(/\[clear\]/g, '\x1B[39m'); + testResult = testResult.split('\\n').map((line) => `[${testSettings.browserName} ${testSettings.platform}${testSettings.version === '' ? '' : (` ${testSettings.version}`)}] ${line}`).join('\n'); - console.log(testResult); - } - }); - -}, 6); //run 6 tests in parrallel + console.log(testResult); + } + }); +}, 6); // run 6 tests in parrallel // 1) Firefox on Linux sauceTestWorker.push({ - 'platform' : 'Windows 7' - , 'browserName' : 'firefox' - , 'version' : '52.0' + platform: 'Windows 7', + browserName: 'firefox', + version: '52.0', }); // 2) Chrome on Linux sauceTestWorker.push({ - 'platform' : 'Windows 7' - , 'browserName' : 'chrome' - , 'version' : '55.0' - , 'args' : ['--use-fake-device-for-media-stream'] + platform: 'Windows 7', + browserName: 'chrome', + version: '55.0', + args: ['--use-fake-device-for-media-stream'], }); /* @@ -138,9 +135,9 @@ sauceTestWorker.push({ // 4) Safari on OSX 10.14 sauceTestWorker.push({ - 'platform' : 'OS X 10.15' - , 'browserName' : 'safari' - , 'version' : '13.1' + platform: 'OS X 10.15', + browserName: 'safari', + version: '13.1', }); // IE 10 doesn't appear to be working anyway /* @@ -153,17 +150,17 @@ sauceTestWorker.push({ */ // 5) Edge on Win 10 sauceTestWorker.push({ - 'platform' : 'Windows 10' - , 'browserName' : 'microsoftedge' - , 'version' : '83.0' + platform: 'Windows 10', + browserName: 'microsoftedge', + version: '83.0', }); // 6) Firefox on Win 7 sauceTestWorker.push({ - 'platform' : 'Windows 7' - , 'browserName' : 'firefox' - , 'version' : '78.0' + platform: 'Windows 7', + browserName: 'firefox', + version: '78.0', }); -sauceTestWorker.drain(function() { +sauceTestWorker.drain(() => { process.exit(allTestsPassed ? 0 : 1); }); diff --git a/tests/ratelimit/send_changesets.js b/tests/ratelimit/send_changesets.js index cf0377cae..b0d994c8c 100644 --- a/tests/ratelimit/send_changesets.js +++ b/tests/ratelimit/send_changesets.js @@ -1,25 +1,24 @@ -try{ - var etherpad = require("../../src/node_modules/etherpad-cli-client"); - //ugly +try { + var etherpad = require('../../src/node_modules/etherpad-cli-client'); + // ugly } catch { - var etherpad = require("etherpad-cli-client") + var etherpad = require('etherpad-cli-client'); } -var pad = etherpad.connect(process.argv[2]); -pad.on("connected", function(){ - - setTimeout(function(){ - setInterval(function(){ - pad.append("1"); +const pad = etherpad.connect(process.argv[2]); +pad.on('connected', () => { + setTimeout(() => { + setInterval(() => { + pad.append('1'); }, process.argv[3]); - },500); // wait because CLIENT_READY message is included in ratelimit + }, 500); // wait because CLIENT_READY message is included in ratelimit - setTimeout(function(){ + setTimeout(() => { process.exit(0); - },11000) + }, 11000); }); // in case of disconnect exit code 1 -pad.on("message", function(message){ - if(message.disconnect == 'rateLimited'){ +pad.on('message', (message) => { + if (message.disconnect == 'rateLimited') { process.exit(1); } -}) +});