diff --git a/.eslintignore b/.eslintignore index c56157704..9d2449b36 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,2 @@ scripts/ -tests/ lib/ diff --git a/.eslintrc.json b/.eslintrc.json index e3f7dd7bb..2df51e665 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -13,6 +13,7 @@ "rules": { "array-bracket-spacing": "off", "computed-property-spacing": "off", + "es-x/no-array-prototype-includes": "off", "indent": "off", "jsdoc/require-param": "off", "jsdoc/require-returns": "off", @@ -38,9 +39,9 @@ "selector": "MemberExpression > Identifier[name=\"fail\"]" } ], + "unicorn/prefer-includes": "error", "camelcase": ["warn", {"properties": "never"}], - "es-x/no-array-prototype-includes": "warn", "es-x/no-object-values": "warn", "mediawiki/class-doc": "warn", "new-cap": "warn", diff --git a/modules/twinklebatchdelete.js b/modules/twinklebatchdelete.js index ab7beafa9..b83d1a4d9 100644 --- a/modules/twinklebatchdelete.js +++ b/modules/twinklebatchdelete.js @@ -305,7 +305,7 @@ Twinkle.batchdelete.callback.toggleSubpages = function twDbatchToggleSubpages(e) const pageTitle = mw.Title.newFromText(pageName); // No need to look for subpages in main/file/mediawiki space - if ([0, 6, 8].indexOf(pageTitle.namespace) > -1) { + if ([0, 6, 8].includes(pageTitle.namespace)) { subpageLister.workerSuccess(); return; } diff --git a/modules/twinkleconfig.js b/modules/twinkleconfig.js index d428ff0b3..06b405c18 100644 --- a/modules/twinkleconfig.js +++ b/modules/twinkleconfig.js @@ -753,12 +753,12 @@ Twinkle.config.init = function twinkleconfigInit() { check.setAttribute('type', 'checkbox'); check.setAttribute('id', pref.name + '_' + itemkey); check.setAttribute('name', pref.name + '_' + itemkey); - if (gotPref && gotPref.indexOf(itemkey) !== -1) { + if (gotPref && gotPref.includes(itemkey)) { check.setAttribute('checked', 'checked'); } // cater for legacy integer array values for unlinkNamespaces (this can be removed a few years down the track...) if (pref.name === 'unlinkNamespaces') { - if (gotPref && gotPref.indexOf(parseInt(itemkey, 10)) !== -1) { + if (gotPref && gotPref.includes(parseInt(itemkey, 10))) { check.setAttribute('checked', 'checked'); } } @@ -896,7 +896,7 @@ Twinkle.config.init = function twinkleconfigInit() { box.appendChild(document.createTextNode(', or by editing this page.')); $(box).insertAfter($('#contentSub')); - } else if (['monobook', 'vector', 'vector-2022', 'cologneblue', 'modern', 'timeless', 'minerva', 'common'].indexOf(scriptPageName) !== -1) { + } else if (['monobook', 'vector', 'vector-2022', 'cologneblue', 'modern', 'timeless', 'minerva', 'common'].includes(scriptPageName)) { // place "Looking for Twinkle options?" notice box.setAttribute('class', 'config-userskin-box'); @@ -1119,7 +1119,7 @@ Twinkle.config.resetPref = function twinkleconfigResetPref(pref) { case 'set': $.each(pref.setValues, (itemkey) => { if (document.getElementById(pref.name + '_' + itemkey)) { - document.getElementById(pref.name + '_' + itemkey).checked = Twinkle.defaultConfig[pref.name].indexOf(itemkey) !== -1; + document.getElementById(pref.name + '_' + itemkey).checked = Twinkle.defaultConfig[pref.name].includes(itemkey); } }); break; diff --git a/modules/twinkleimage.js b/modules/twinkleimage.js index 546faf533..05dfb8b03 100644 --- a/modules/twinkleimage.js +++ b/modules/twinkleimage.js @@ -133,7 +133,7 @@ Twinkle.image.callback.evaluate = function twinkleimageCallbackEvaluate(event) { throw new Error('Twinkle.image.callback.evaluate: unknown criterion'); } - const lognomination = Twinkle.getPref('logSpeedyNominations') && Twinkle.getPref('noLogOnSpeedyNomination').indexOf(csdcrit.toLowerCase()) === -1; + const lognomination = Twinkle.getPref('logSpeedyNominations') && !Twinkle.getPref('noLogOnSpeedyNomination').includes(csdcrit.toLowerCase()); const templatename = input.derivative ? 'dw ' + input.type : input.type; const params = $.extend({ diff --git a/modules/twinklerollback.js b/modules/twinklerollback.js index 23bde47b5..2fa927acb 100644 --- a/modules/twinklerollback.js +++ b/modules/twinklerollback.js @@ -192,9 +192,9 @@ Twinkle.rollback.addLinks = { if (mw.config.exists('wgRelevantUserName') || isRange) { // Get the username these contributions are for let username = mw.config.get('wgRelevantUserName'); - if (Twinkle.getPref('showRollbackLinks').indexOf('contribs') !== -1 || - (mw.config.get('wgUserName') !== username && Twinkle.getPref('showRollbackLinks').indexOf('others') !== -1) || - (mw.config.get('wgUserName') === username && Twinkle.getPref('showRollbackLinks').indexOf('mine') !== -1)) { + if (Twinkle.getPref('showRollbackLinks').includes('contribs') || + (mw.config.get('wgUserName') !== username && Twinkle.getPref('showRollbackLinks').includes('others')) || + (mw.config.get('wgUserName') === username && Twinkle.getPref('showRollbackLinks').includes('mine'))) { const $list = $('#mw-content-text').find('ul li:has(span.mw-uctop):has(.mw-changeslist-diff)'); $list.each((key, current) => { @@ -218,7 +218,7 @@ Twinkle.rollback.addLinks = { }, recentchanges: function() { - if (Twinkle.getPref('showRollbackLinks').indexOf('recent') !== -1) { + if (Twinkle.getPref('showRollbackLinks').includes('recent')) { // Latest and revertable (not page creations, logs, categorizations, etc.) let $list = $('.mw-changeslist .mw-changeslist-last.mw-changeslist-src-mw-edit'); // Exclude top-level header if "group changes" preference is used @@ -238,7 +238,7 @@ Twinkle.rollback.addLinks = { }, history: function() { - if (Twinkle.getPref('showRollbackLinks').indexOf('history') !== -1) { + if (Twinkle.getPref('showRollbackLinks').includes('history')) { // All revs const histList = $('#pagehistory li').toArray(); @@ -286,7 +286,7 @@ Twinkle.rollback.addLinks = { extraParams += xtitle === 'otitle' ? mw.config.get('wgDiffOldId') : mw.config.get('wgDiffNewId'); const href = $talkLink.attr('href'); - if (href.indexOf('?') === -1) { + if (!href.includes('?')) { $talkLink.attr('href', href + '?' + extraParams); } else { $talkLink.attr('href', href + '&' + extraParams); @@ -311,7 +311,7 @@ Twinkle.rollback.addLinks = { // Not latest revision, add [restore this revision] link to newer revision const newTitle = document.getElementById('mw-diff-ntitle1').parentNode; newTitle.insertBefore(Twinkle.rollback.linkBuilder.restoreThisRevisionLink('wgDiffNewId'), newTitle.firstChild); - } else if (Twinkle.getPref('showRollbackLinks').indexOf('diff') !== -1 && mw.config.get('wgDiffOldId') && (mw.config.get('wgDiffOldId') !== mw.config.get('wgDiffNewId') || document.getElementById('differences-prevlink'))) { + } else if (Twinkle.getPref('showRollbackLinks').includes('diff') && mw.config.get('wgDiffOldId') && (mw.config.get('wgDiffOldId') !== mw.config.get('wgDiffNewId') || document.getElementById('differences-prevlink'))) { // Normally .mw-userlink is a link, but if the // username is hidden, it will be a span with // .history-deleted as well. When a sysop views the @@ -459,11 +459,11 @@ Twinkle.rollback.callbacks = { undoafter: revertToRevID, basetimestamp: touched, starttimestamp: loadtimestamp, - minor: Twinkle.getPref('markRevertedPagesAsMinor').indexOf('torev') !== -1 ? true : undefined, + minor: Twinkle.getPref('markRevertedPagesAsMinor').includes('torev') ? true : undefined, format: 'json' }; // Handle watching, possible expiry - if (Twinkle.getPref('watchRevertedPages').indexOf('torev') !== -1) { + if (Twinkle.getPref('watchRevertedPages').includes('torev')) { const watchOrExpiry = Twinkle.getPref('watchRevertedExpiry'); if (!watchOrExpiry || watchOrExpiry === 'no') { @@ -541,7 +541,7 @@ Twinkle.rollback.callbacks = { } else if (params.type === 'vand' && // Okay to test on user since it will either fail or sysop will correctly access it // Besides, none of the trusted bots are going to be revdel'd - Twinkle.rollback.trustedBots.indexOf(top.user) !== -1 && revs.length > 1 && + Twinkle.rollback.trustedBots.includes(top.user) && revs.length > 1 && revs[1].revid === params.revid) { Morebits.Status.info('Info', [ 'Latest revision was made by ', Morebits.htmlNode('strong', lastuser), ', a trusted bot, and the revision before was made by our vandal, so we will proceed with the revert.' ]); index = 2; @@ -557,7 +557,7 @@ Twinkle.rollback.callbacks = { userNorm = params.user || Twinkle.rollback.hiddenName; } - if (Twinkle.rollback.trustedBots.indexOf(params.user) !== -1) { + if (Twinkle.rollback.trustedBots.includes(params.user)) { switch (params.type) { case 'vand': Morebits.Status.info('Info', [ 'Vandalism revert was chosen on ', Morebits.htmlNode('strong', userNorm), '. As this is a trusted bot, we assume you wanted to revert vandalism made by the previous user instead.' ]); @@ -685,7 +685,7 @@ Twinkle.rollback.callbacks = { } // Decide whether to notify the user on success - if (!Twinkle.rollback.skipTalk && Twinkle.getPref('openTalkPage').indexOf(params.type) !== -1 && + if (!Twinkle.rollback.skipTalk && Twinkle.getPref('openTalkPage').includes(params.type) && !params.userHidden && mw.config.get('wgUserName') !== params.user) { params.notifyUser = true; // Pass along to the warn module @@ -712,11 +712,11 @@ Twinkle.rollback.callbacks = { undoafter: params.goodid, basetimestamp: touched, starttimestamp: loadtimestamp, - minor: Twinkle.getPref('markRevertedPagesAsMinor').indexOf(params.type) !== -1 ? true : undefined, + minor: Twinkle.getPref('markRevertedPagesAsMinor').includes(params.type) ? true : undefined, format: 'json' }; // Handle watching, possible expiry - if (Twinkle.getPref('watchRevertedPages').indexOf(params.type) !== -1) { + if (Twinkle.getPref('watchRevertedPages').includes(params.type)) { const watchOrExpiry = Twinkle.getPref('watchRevertedExpiry'); if (!watchOrExpiry || watchOrExpiry === 'no') { diff --git a/modules/twinklespeedy.js b/modules/twinklespeedy.js index dcdd2d9f5..a55224ad8 100644 --- a/modules/twinklespeedy.js +++ b/modules/twinklespeedy.js @@ -441,10 +441,10 @@ Twinkle.speedy.generateCsdList = function twinklespeedyGenerateCsdList(list, mod return null; } - if (criterion.showInNamespaces && criterion.showInNamespaces.indexOf(pageNamespace) < 0) { + if (criterion.showInNamespaces && !criterion.showInNamespaces.includes(pageNamespace)) { return null; } - if (criterion.hideInNamespaces && criterion.hideInNamespaces.indexOf(pageNamespace) > -1) { + if (criterion.hideInNamespaces && criterion.hideInNamespaces.includes(pageNamespace)) { return null; } @@ -728,7 +728,7 @@ Twinkle.speedy.userList = [ tooltip: 'User requested deletion of their own user page or user-subpage. User pages that are blanked by the user may also be deleted under this criterion.', subgroup: - mw.config.get('wgNamespaceNumber') === 3 && mw.config.get('wgTitle').indexOf('/') === -1 ? { + mw.config.get('wgNamespaceNumber') === 3 && !mw.config.get('wgTitle').includes('/') ? { name: 'userreq_rationale', parameter: '2', type: 'input', @@ -1283,12 +1283,12 @@ Twinkle.speedy.callbacks = { params.utparams = buildData[1]; // Set the correct value for |ts= parameter in {{db-g13}} - if (params.normalizeds.indexOf('g13') !== -1) { + if (params.normalizeds.includes('g13')) { code = code.replace('$TIMESTAMP', pageobj.getLastEditTime()); } // Tag if possible, post on talk if not - if (pageobj.canEdit() && ['wikitext', 'Scribunto', 'javascript', 'css', 'sanitized-css'].indexOf(pageobj.getContentModel()) !== -1 && mw.config.get('wgNamespaceNumber') !== 710 /* TimedText */) { + if (pageobj.canEdit() && ['wikitext', 'Scribunto', 'javascript', 'css', 'sanitized-css'].includes(pageobj.getContentModel()) && mw.config.get('wgNamespaceNumber') !== 710 /* TimedText */) { let text = pageobj.getPageText(); statelem.status('Checking for tags on the page...'); @@ -1326,11 +1326,11 @@ Twinkle.speedy.callbacks = { if (mw.config.get('wgPageContentModel') === 'Scribunto') { // Scribunto isn't parsed like wikitext, so CSD templates on modules need special handling to work let equals = ''; - while (code.indexOf(']' + equals + ']') !== -1) { + while (code.includes(']' + equals + ']')) { equals += '='; } code = "require('Module:Module wikitext')._addText([" + equals + '[' + code + ']' + equals + ']);'; - } else if (['javascript', 'css', 'sanitized-css'].indexOf(mw.config.get('wgPageContentModel')) !== -1) { + } else if (['javascript', 'css', 'sanitized-css'].includes(mw.config.get('wgPageContentModel'))) { // Likewise for JS/CSS pages code = '/* ' + code + ' */'; } @@ -1351,7 +1351,7 @@ Twinkle.speedy.callbacks = { } // Blank attack pages - if (params.normalizeds.indexOf('g10') !== -1) { + if (params.normalizeds.includes('g10')) { text = code; } else { // Insert tag after short description or any hatnotes @@ -1778,18 +1778,18 @@ Twinkle.speedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSy // analyse each criterion to determine whether to watch the page, prompt for summary, or notify the creator let watchPage, promptForSummary; normalizeds.forEach((norm) => { - if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) { + if (Twinkle.getPref('watchSpeedyPages').includes(norm)) { watchPage = Twinkle.getPref('watchSpeedyExpiry'); } - if (Twinkle.getPref('promptForSpeedyDeletionSummary').indexOf(norm) !== -1) { + if (Twinkle.getPref('promptForSpeedyDeletionSummary').includes(norm)) { promptForSummary = true; } }); - const warnusertalk = form.warnusertalk.checked && normalizeds.some((norm, index) => Twinkle.getPref('warnUserOnSpeedyDelete').indexOf(norm) !== -1 && + const warnusertalk = form.warnusertalk.checked && normalizeds.some((norm, index) => Twinkle.getPref('warnUserOnSpeedyDelete').includes(norm) && !(norm === 'g6' && values[index] !== 'copypaste')); - const welcomeuser = warnusertalk && normalizeds.some((norm) => Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(norm) !== -1); + const welcomeuser = warnusertalk && normalizeds.some((norm) => Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').includes(norm)); const params = { values: values, @@ -1831,12 +1831,12 @@ Twinkle.speedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUse const normalizeds = values.map((value) => Twinkle.speedy.normalizeHash[value]); // analyse each criterion to determine whether to watch the page/notify the creator - const watchPage = normalizeds.some((csdCriteria) => Twinkle.getPref('watchSpeedyPages').indexOf(csdCriteria) !== -1) && Twinkle.getPref('watchSpeedyExpiry'); + const watchPage = normalizeds.some((csdCriteria) => Twinkle.getPref('watchSpeedyPages').includes(csdCriteria)) && Twinkle.getPref('watchSpeedyExpiry'); - const notifyuser = form.notify.checked && normalizeds.some((norm, index) => Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(norm) !== -1 && + const notifyuser = form.notify.checked && normalizeds.some((norm, index) => Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').includes(norm) && !(norm === 'g6' && values[index] !== 'copypaste')); - const welcomeuser = notifyuser && normalizeds.some((norm) => Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(norm) !== -1); - const csdlog = Twinkle.getPref('logSpeedyNominations') && normalizeds.some((norm) => Twinkle.getPref('noLogOnSpeedyNomination').indexOf(norm) === -1); + const welcomeuser = notifyuser && normalizeds.some((norm) => Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').includes(norm)); + const csdlog = Twinkle.getPref('logSpeedyNominations') && normalizeds.some((norm) => !Twinkle.getPref('noLogOnSpeedyNomination').includes(norm)); const params = { values: values, diff --git a/modules/twinkleunlink.js b/modules/twinkleunlink.js index c531b97b0..2436c4749 100644 --- a/modules/twinkleunlink.js +++ b/modules/twinkleunlink.js @@ -122,8 +122,8 @@ Twinkle.unlink.callback.evaluate = function twinkleunlinkCallbackEvaluate(event) const wikipedia_page = new Morebits.wiki.Page(pageName, 'Unlinking in page "' + pageName + '"'); wikipedia_page.setBotEdit(true); // unlink considered a floody operation wikipedia_page.setCallbackParameters($.extend({ - doBacklinks: input.backlinks.indexOf(pageName) !== -1, - doImageusage: input.imageusage.indexOf(pageName) !== -1 + doBacklinks: input.backlinks.includes(pageName), + doImageusage: input.imageusage.includes(pageName) }, params)); wikipedia_page.load(Twinkle.unlink.callbacks.unlinkBacklinks); }); diff --git a/morebits.js b/morebits.js index 8d0269ba0..e0285e7a5 100644 --- a/morebits.js +++ b/morebits.js @@ -131,7 +131,7 @@ Morebits.l10n = { * @return {boolean} */ Morebits.userIsInGroup = function (group) { - return mw.config.get('wgUserGroups').indexOf(group) !== -1; + return mw.config.get('wgUserGroups').includes(group); }; /** * Hardcodes whether the user is a sysop, used a lot. @@ -269,7 +269,7 @@ Morebits.namespaceRegex = function(namespaces) { const aliases = []; let regex; $.each(mw.config.get('wgNamespaceIds'), (name, number) => { - if (namespaces.indexOf(number) !== -1) { + if (namespaces.includes(number)) { // Namespaces are completely agnostic as to case, // and a regex string is more useful/compatible than a RegExp object, // so we accept any casing for any letter. @@ -1557,7 +1557,7 @@ Morebits.string = { * @return {boolean} */ isInfinity: function morebitsStringIsInfinity(expiry) { - return ['indefinite', 'infinity', 'infinite', 'never'].indexOf(expiry) !== -1; + return ['indefinite', 'infinity', 'infinite', 'never'].includes(expiry); }, /** @@ -1653,7 +1653,7 @@ Morebits.select2 = { const result = originalMatcher(params, data); if (result && params.term && - data.text.toUpperCase().indexOf(params.term.toUpperCase()) !== -1) { + data.text.toUpperCase().includes(params.term.toUpperCase())) { result.children = data.children; } return result; @@ -2284,7 +2284,7 @@ Morebits.wiki.api = function(currentAction, query, onSuccess, statusElement, onE this.query = query; this.query.assert = 'user'; // Enforce newer error formats, preferring html - if (!query.errorformat || ['wikitext', 'plaintext'].indexOf(query.errorformat) === -1) { + if (!query.errorformat || !['wikitext', 'plaintext'].includes(query.errorformat)) { this.query.errorformat = 'html'; } // Explicitly use the wiki's content language to minimize confusion, @@ -2305,12 +2305,12 @@ Morebits.wiki.api = function(currentAction, query, onSuccess, statusElement, onE this.query.format = 'xml'; } else if (query.format === 'json' && !query.formatversion) { this.query.formatversion = '2'; - } else if (['xml', 'json'].indexOf(query.format) === -1) { + } else if (!['xml', 'json'].includes(query.format)) { this.statelem.error('Invalid API format: only xml and json are supported.'); } // Ignore tags for queries and most common unsupported actions, produces warnings - if (query.action && ['query', 'review', 'stabilize', 'pagetriageaction', 'watch'].indexOf(query.action) !== -1) { + if (query.action && ['query', 'review', 'stabilize', 'pagetriageaction', 'watch'].includes(query.action)) { delete query.tags; } else if (!query.tags && morebitsWikiChangeTag) { query.tags = morebitsWikiChangeTag; @@ -2900,7 +2900,7 @@ Morebits.wiki.page = function(pageName, status) { break; } - if (['recreate', 'createonly', 'nocreate'].indexOf(ctx.createOption) !== -1) { + if (['recreate', 'createonly', 'nocreate'].includes(ctx.createOption)) { query[ctx.createOption] = ''; } @@ -3432,7 +3432,7 @@ Morebits.wiki.page = function(pageName, status) { /** @return {boolean} whether or not you can edit the page */ this.canEdit = function() { - return !!ctx.testActions && ctx.testActions.indexOf('edit') !== -1; + return !!ctx.testActions && ctx.testActions.includes('edit'); }; /** @@ -3594,7 +3594,7 @@ Morebits.wiki.page = function(pageName, status) { */ this.triage = function() { // Fall back to patrol if not a valid triage namespace - if (mw.config.get('pageTriageNamespaces').indexOf(new mw.Title(ctx.pageName).getNamespaceId()) === -1) { + if (!mw.config.get('pageTriageNamespaces').includes(new mw.Title(ctx.pageName).getNamespaceId())) { this.patrol(); } else { if (!Morebits.userIsSysop && !Morebits.userIsInGroup('patroller')) { @@ -3778,7 +3778,7 @@ Morebits.wiki.page = function(pageName, status) { // wgRestrictionEdit is null on non-existent pages, // so this neatly handles nonexistent pages const editRestriction = mw.config.get('wgRestrictionEdit'); - if (!editRestriction || editRestriction.indexOf('sysop') !== -1) { + if (!editRestriction || editRestriction.includes('sysop')) { return false; } } @@ -4231,7 +4231,7 @@ Morebits.wiki.page = function(pageName, status) { const missing = response.pages[0].missing; // No undelete as an existing page could have deleted revisions - const actionMissing = missing && ['delete', 'stabilize', 'move'].indexOf(action) !== -1; + const actionMissing = missing && ['delete', 'stabilize', 'move'].includes(action); const protectMissing = action === 'protect' && missing && (ctx.protectEdit || ctx.protectMove); const saltMissing = action === 'protect' && !missing && ctx.protectCreate; @@ -4944,7 +4944,7 @@ Morebits.wikitext.page.prototype = { // For most namespaces, unlink both [[User:Test]] and [[:User:Test]] // For files and categories, only unlink [[:Category:Test]]. Do not unlink [[Category:Test]] - const isFileOrCategory = [6, 14].indexOf(namespaceID) !== -1; + const isFileOrCategory = [6, 14].includes(namespaceID); const colon = isFileOrCategory ? ':' : ':?'; const simple_link_regex = new RegExp('\\[\\[' + colon + '(' + link_regex_string + ')\\]\\]', 'g'); diff --git a/tests/.eslintrc.json b/tests/.eslintrc.json new file mode 100644 index 000000000..3e27609f3 --- /dev/null +++ b/tests/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "extends": [ + "wikimedia/server" + ], + "env": { + "jest": true + }, + "globals": { + "assert": "readonly", + "document": "readonly", + "jQuery": "readonly", + "Morebits": "readonly", + "mw": "readonly", + "Twinkle": "readonly", + "window": "readonly" + }, + "root": true, + "rules": { + "array-bracket-spacing": "off", + "computed-property-spacing": "off", + "no-shadow": "off", + "object-curly-spacing": "off", + "space-in-parens": "off" + } +} diff --git a/tests/jest.setup.js b/tests/jest.setup.js index 3b1780b03..cdbf0b532 100644 --- a/tests/jest.setup.js +++ b/tests/jest.setup.js @@ -1,7 +1,9 @@ +'use strict'; + // Tweak some mw.configs as needed by tests mw.config.set({ wgPageName: 'Macbeth,_King_of_Scotland', - wgUserGroups: ['interface-admin', 'sysop', '*', 'user', 'autoconfirmed'], + wgUserGroups: ['interface-admin', 'sysop', '*', 'user', 'autoconfirmed'] }); require('../morebits.js'); @@ -16,9 +18,9 @@ assert.true = function (arg, message) { if (arg !== true) { throw new Error(message); } -} +}; assert.false = function (arg, message) { if (arg !== false) { throw new Error(message); } -} +}; diff --git a/tests/morebits.array.js b/tests/morebits.array.js index c64b9d8a9..b8c29542c 100644 --- a/tests/morebits.array.js +++ b/tests/morebits.array.js @@ -1,3 +1,5 @@ +'use strict'; + describe('Morebits.array', () => { test('chunk', () => { assert.deepEqual(Morebits.array.chunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3), [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]], '10 over 3'); diff --git a/tests/morebits.batchOperation.js b/tests/morebits.batchOperation.js index 38ec8e6b4..9fa045008 100644 --- a/tests/morebits.batchOperation.js +++ b/tests/morebits.batchOperation.js @@ -1,15 +1,17 @@ +'use strict'; + describe('Morebits.batchOperation', () => { test('Contruction', () => { - assert.true(new Morebits.batchOperation() instanceof Morebits.batchOperation, 'Correct instance'); + assert.true(new Morebits.BatchOperation() instanceof Morebits.batchOperation, 'Correct instance'); }); - var batch = new Morebits.batchOperation(); - var pageList = ['Macbeth', 'Hamlet', 'Romeo and Juliet', 'Much Ado About Nothing', 'Tempest']; + const batch = new Morebits.BatchOperation(); + const pageList = ['Macbeth', 'Hamlet', 'Romeo and Juliet', 'Much Ado About Nothing', 'Tempest']; batch.setPageList(pageList); - var chunkLength = 2; + const chunkLength = 2; batch.setOption('chunkSize', chunkLength); test('Run', () => { - var all = ''; - var runFunc = function (page) { + let all = ''; + const runFunc = function (page) { all += page; batch.workerSuccess(); }; @@ -18,8 +20,8 @@ describe('Morebits.batchOperation', () => { }); // Will leave a run hanging, who cares? test('Chunksize', () => { - var list = []; - var runFunc = function (page) { + const list = []; + const runFunc = function (page) { list.push(page); }; batch.run(runFunc); diff --git a/tests/morebits.createHtml.js b/tests/morebits.createHtml.js index d6e2a97c5..07be8fe88 100644 --- a/tests/morebits.createHtml.js +++ b/tests/morebits.createHtml.js @@ -1,3 +1,5 @@ +'use strict'; + describe('Morebits.createHtml', () => { test('createHtml', () => { @@ -23,17 +25,17 @@ describe('Morebits.createHtml', () => { test('renderWikilinks', () => { assert.strictEqual( Morebits.createHtml.renderWikilinks('[[Main Page]]'), - `Main Page`, + 'Main Page', 'simple link' ); assert.strictEqual( Morebits.createHtml.renderWikilinks('surrounding text [[Main Page|the main page]]'), - `surrounding text the main page`, + 'surrounding text the main page', 'link with display text' ); assert.strictEqual( Morebits.createHtml.renderWikilinks('surrounding text [["Weird Al" Yankovic]]'), - `surrounding text "Weird Al" Yankovic`, + 'surrounding text "Weird Al" Yankovic', // jsdom in node turns " in title attribute into " whereas Chrome seems turns it into " // but it works either way 'link with double quote' @@ -41,7 +43,7 @@ describe('Morebits.createHtml', () => { assert.strictEqual( Morebits.createHtml.renderWikilinks('[[CODE]] [[Yankovic]]'), - `[[CODE]] Yankovic`, + '[[CODE]] Yankovic', 'wikilink in tag' ); }); diff --git a/tests/morebits.date.js b/tests/morebits.date.js index 6b7a2ef87..13f419ed3 100644 --- a/tests/morebits.date.js +++ b/tests/morebits.date.js @@ -1,24 +1,26 @@ +'use strict'; + describe('Morebits.date', () => { - var now = Date.now(); - var ts_mw = '16:26, 7 November 2020 (UTC)', ts_iso = '2020-11-07T16:26:00.000Z', naive = 20201107162600; + const now = Date.now(); + const timestampMediaWiki = '16:26, 7 November 2020 (UTC)', timestampIso = '2020-11-07T16:26:00.000Z', naive = 20201107162600; test('Construction', () => { // getTime and toISOString imply testing of inherited methods // Allow off-by-one values in milliseconds for not-quite-simultaneous date contructions - expect(Math.abs(new Morebits.date().getTime() - new Date().getTime())).toBeLessThanOrEqual(1); + expect(Math.abs(new Morebits.Date().getTime() - Date.now())).toBeLessThanOrEqual(1); - assert.strictEqual(new Morebits.date(now).getTime(), new Date(now).getTime(), 'Constructor from timestring'); - assert.strictEqual(new Morebits.date(2020, 11, 7, 16, 26).getTime(), new Date(2020, 11, 7, 16, 26).getTime(), 'Constructor from parts'); - assert.strictEqual(new Morebits.date(ts_mw).toISOString(), ts_iso, 'enWiki timestamp format'); - assert.strictEqual(new Morebits.date(naive).toISOString(), ts_iso, 'MediaWiki 14-digit number'); - assert.strictEqual(new Morebits.date(naive.toString()).toISOString(), ts_iso, 'MediaWiki 14-digit string'); - assert.strictEqual(new Morebits.date(parseInt(naive / 10, 10)).toISOString(), new Date(parseInt(naive / 10, 10)).toISOString(), 'native 13 digit'); - assert.strictEqual(new Morebits.date(naive * 10).toISOString(), new Date(naive * 10).toISOString(), 'native 15 digit'); + assert.strictEqual(new Morebits.Date(now).getTime(), new Date(now).getTime(), 'Constructor from timestring'); + assert.strictEqual(new Morebits.Date(2020, 11, 7, 16, 26).getTime(), new Date(2020, 11, 7, 16, 26).getTime(), 'Constructor from parts'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).toISOString(), timestampIso, 'enWiki timestamp format'); + assert.strictEqual(new Morebits.Date(naive).toISOString(), timestampIso, 'MediaWiki 14-digit number'); + assert.strictEqual(new Morebits.Date(naive.toString()).toISOString(), timestampIso, 'MediaWiki 14-digit string'); + assert.strictEqual(new Morebits.Date(parseInt(naive / 10, 10)).toISOString(), new Date(parseInt(naive / 10, 10)).toISOString(), 'native 13 digit'); + assert.strictEqual(new Morebits.Date(naive * 10).toISOString(), new Date(naive * 10).toISOString(), 'native 15 digit'); }); - var date = new Morebits.date(ts_mw); + const date = new Morebits.Date(timestampMediaWiki); test('Methods', () => { assert.true(date.isValid(), 'Valid'); // Logs a message; not a failure, but annoying - assert.false(new Morebits.date('no').isValid(), 'Invalid'); + assert.false(new Morebits.Date('no').isValid(), 'Invalid'); // Ideally we would test the differences between UTC and non-UTC dates assert.strictEqual(date.getUTCDayName(), 'Saturday', 'getUTCDayName'); @@ -26,7 +28,7 @@ describe('Morebits.date', () => { assert.strictEqual(date.getUTCMonthName(), 'November', 'getUTCMonthName'); assert.strictEqual(date.getUTCMonthNameAbbrev(), 'Nov', 'getUTCMonthNameAbbrev'); - assert.true(new Morebits.date(now).isAfter(date), 'isAfter'); + assert.true(new Morebits.Date(now).isAfter(date), 'isAfter'); assert.true(date.isBefore(new Date(now)), 'isBefore'); }); test('RegEx headers', () => { @@ -41,25 +43,25 @@ describe('Morebits.date', () => { assert.false(date.monthHeaderRegex().test('==December 2020=='), 'Wrong month'); }); test('add/subtract', () => { - assert.strictEqual(new Morebits.date(ts_mw).add(1, 'day').toISOString(), '2020-11-08T16:26:00.000Z', 'Add 1 day'); - assert.strictEqual(new Morebits.date(ts_mw).add(1, 'DaY').toISOString(), '2020-11-08T16:26:00.000Z', 'Loudly add 1 day'); - assert.strictEqual(new Morebits.date(ts_mw).add('1', 'day').toISOString(), '2020-11-08T16:26:00.000Z', "Add 1 day but it's a string"); - assert.strictEqual(new Morebits.date(ts_mw).subtract(1, 'day').toISOString(), '2020-11-06T16:26:00.000Z', 'Subtract 1 day'); - assert.strictEqual(new Morebits.date(ts_mw).add(2, 'weeks').toISOString(), '2020-11-21T16:26:00.000Z', 'Add 2 weeks'); - assert.strictEqual(new Morebits.date(ts_mw).add(2, 'weeks').subtract(2, 'weeks').toISOString(), ts_iso, '2 weeks roundtrip'); // Note, this intentionally twice-crosses a US DST + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add(1, 'day').toISOString(), '2020-11-08T16:26:00.000Z', 'Add 1 day'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add(1, 'DaY').toISOString(), '2020-11-08T16:26:00.000Z', 'Loudly add 1 day'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add('1', 'day').toISOString(), '2020-11-08T16:26:00.000Z', "Add 1 day but it's a string"); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).subtract(1, 'day').toISOString(), '2020-11-06T16:26:00.000Z', 'Subtract 1 day'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add(2, 'weeks').toISOString(), '2020-11-21T16:26:00.000Z', 'Add 2 weeks'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add(2, 'weeks').subtract(2, 'weeks').toISOString(), timestampIso, '2 weeks roundtrip'); // Note, this intentionally twice-crosses a US DST - assert.strictEqual(new Morebits.date(ts_mw).add(1, 'second').toISOString(), '2020-11-07T16:26:01.000Z', 'Add 1 second'); - assert.strictEqual(new Morebits.date(ts_mw).add(1, 'minute').toISOString(), '2020-11-07T16:27:00.000Z', 'Add 1 minute'); - assert.strictEqual(new Morebits.date(ts_mw).add(1, 'hour').toISOString(), '2020-11-07T17:26:00.000Z', 'Add 1 hour'); - assert.strictEqual(new Morebits.date(ts_mw).add(1, 'month').toISOString(), '2020-12-07T16:26:00.000Z', 'Add 1 month'); - assert.strictEqual(new Morebits.date(ts_mw).add(1, 'year').toISOString(), '2021-11-07T16:26:00.000Z', 'Add 1 year'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add(1, 'second').toISOString(), '2020-11-07T16:26:01.000Z', 'Add 1 second'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add(1, 'minute').toISOString(), '2020-11-07T16:27:00.000Z', 'Add 1 minute'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add(1, 'hour').toISOString(), '2020-11-07T17:26:00.000Z', 'Add 1 hour'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add(1, 'month').toISOString(), '2020-12-07T16:26:00.000Z', 'Add 1 month'); + assert.strictEqual(new Morebits.Date(timestampMediaWiki).add(1, 'year').toISOString(), '2021-11-07T16:26:00.000Z', 'Add 1 year'); - assert.throws(() => new Morebits.date(ts_mw).add('forty-two'), 'throws: non-number provided'); - assert.throws(() => new Morebits.date(ts_mw).add(1), 'throws: no unit'); - assert.throws(() => new Morebits.date(ts_mw).subtract(1, 'dayo'), 'throws: bad unit'); + assert.throws(() => new Morebits.Date(timestampMediaWiki).add('forty-two'), 'throws: non-number provided'); + assert.throws(() => new Morebits.Date(timestampMediaWiki).add(1), 'throws: no unit'); + assert.throws(() => new Morebits.Date(timestampMediaWiki).subtract(1, 'dayo'), 'throws: bad unit'); }); test('Formats', () => { - assert.strictEqual(new Morebits.date(now).format('YYYY-MM-DDTHH:mm:ss.SSSZ', 'utc'), new Date(now).toISOString(), 'ISO format'); + assert.strictEqual(new Morebits.Date(now).format('YYYY-MM-DDTHH:mm:ss.SSSZ', 'utc'), new Date(now).toISOString(), 'ISO format'); assert.strictEqual(date.format('dddd D MMMM YY h:mA', 'utc'), 'Saturday 7 November 20 4:26PM', 'Some weirder stuff'); assert.strictEqual(date.format('MMt[h month], [d]a[y] D, h [o\'clock] A', 'utc'), '11th month, day 7, 4 o\'clock PM', 'Format escapes'); assert.strictEqual(date.format('dddd D MMMM YY h:mA', 600), 'Sunday 8 November 20 2:26AM', 'non-UTC formatting'); @@ -68,7 +70,7 @@ describe('Morebits.date', () => { test('Calendar', () => { assert.strictEqual(date.calendar('utc'), '2020-11-07', 'Old calendar'); assert.strictEqual(date.calendar(600), '2020-11-08', 'Old non-UTC'); - assert.strictEqual(new Morebits.date(now).calendar('utc'), 'Today at ' + new Morebits.date(now).format('h:mm A', 'utc'), 'New calendar'); - assert.strictEqual(new Morebits.date(now).subtract(1, 'day').calendar('utc'), 'Yesterday at ' + new Morebits.date(now).format('h:mm A', 'utc'), 'Close calendar'); + assert.strictEqual(new Morebits.Date(now).calendar('utc'), 'Today at ' + new Morebits.Date(now).format('h:mm A', 'utc'), 'New calendar'); + assert.strictEqual(new Morebits.Date(now).subtract(1, 'day').calendar('utc'), 'Yesterday at ' + new Morebits.Date(now).format('h:mm A', 'utc'), 'Close calendar'); }); }); diff --git a/tests/morebits.ip.js b/tests/morebits.ip.js index 06e5b5516..d4f2da800 100644 --- a/tests/morebits.ip.js +++ b/tests/morebits.ip.js @@ -1,3 +1,5 @@ +'use strict'; + describe('Morebits.ip', () => { test('sanitizeIPv6', () => { assert.strictEqual(Morebits.ip.sanitizeIPv6('2001:0db8:0010:0000:0000:0000:0000:0001'), '2001:DB8:10:0:0:0:0:1', 'Shorten IPv6'); diff --git a/tests/morebits.js b/tests/morebits.js index 741eb212a..eb03a660f 100644 --- a/tests/morebits.js +++ b/tests/morebits.js @@ -1,3 +1,5 @@ +'use strict'; + describe('constants', () => { test('userIsSysop', () => { assert.true(Morebits.userIsSysop, 'Is sysop'); @@ -18,7 +20,7 @@ describe('methods', () => { assert.strictEqual(Morebits.pageNameRegex(''), '', 'Empty'); assert.strictEqual(Morebits.pageNameRegex('a'), '[Aa]', 'Single character'); assert.strictEqual(Morebits.pageNameRegex('#'), '#', 'Single same-case'); - assert.strictEqual(Morebits.pageNameRegex('*$, \{}(a) |.?+-^ [ ]'), '\\*\\$,[_ ]\\{\\}\\(a\\)[_ ]\\|\\.\\?\\+\\-\\^\[_ ]\\[[_ ]\\]', 'Special characters'); + assert.strictEqual(Morebits.pageNameRegex('*$, {}(a) |.?+-^ [ ]'), '\\*\\$,[_ ]\\{\\}\\(a\\)[_ ]\\|\\.\\?\\+\\-\\^[_ ]\\[[_ ]\\]', 'Special characters'); }); test('namespaceRegex', () => { assert.strictEqual(Morebits.namespaceRegex([6]), '(?:[Ff][Ii][Ll][Ee]|[Ii][Mm][Aa][Gg][Ee])', 'Files'); diff --git a/tests/morebits.quickForm.js b/tests/morebits.quickForm.js index 42b7817aa..c3f2d5e4e 100644 --- a/tests/morebits.quickForm.js +++ b/tests/morebits.quickForm.js @@ -1,77 +1,83 @@ -/** Simple helper to render a quickform element */ +'use strict'; + +/** + * Simple helper to render a quickform element + * + * @param data + */ function renderElement(data) { - return new Morebits.quickForm.element(data).render(); + return new Morebits.QuickForm.Element(data).render(); } -describe("quickform", () => { - let inputConfig = { - type: "input", - label: "Label", - name: "inputname", - value: "prefilled value", +describe('quickform', () => { + const inputConfig = { + type: 'input', + label: 'Label', + name: 'inputname', + value: 'prefilled value' }; - let selectConfig = { - type: "select", - label: "Select label", - name: "selectname", + const selectConfig = { + type: 'select', + label: 'Select label', + name: 'selectname', list: [ - { label: "select label 1", value: "selectvalue1" }, - { label: "select label 2", value: "selectvalue2" }, - ], + { label: 'select label 1', value: 'selectvalue1' }, + { label: 'select label 2', value: 'selectvalue2' } + ] }; - let checkboxListConfig = { - type: "checkbox", - name: "checkboxlist1", + const checkboxListConfig = { + type: 'checkbox', + name: 'checkboxlist1', list: [ - { label: "checkbox 1", value: "checkval1" }, - { label: "checkbox 2", value: "checkval2", checked: true }, - ], + { label: 'checkbox 1', value: 'checkval1' }, + { label: 'checkbox 2', value: 'checkval2', checked: true } + ] }; - let checkboxesConfig = { - type: "checkbox", + const checkboxesConfig = { + type: 'checkbox', list: [ { - label: "checkbox 1", - value: "checkval1", - name: "checkname1", - checked: true, + label: 'checkbox 1', + value: 'checkval1', + name: 'checkname1', + checked: true }, - { label: "checkbox 2", value: "checkval2", name: "checkname2" }, - ], + { label: 'checkbox 2', value: 'checkval2', name: 'checkname2' } + ] }; - let radiosConfig = { - type: "radio", - name: "radiolist1", + const radiosConfig = { + type: 'radio', + name: 'radiolist1', list: [ { - label: "radio 1", - value: "radioval1", - name: "radioname1", + label: 'radio 1', + value: 'radioval1', + name: 'radioname1' }, { - label: "radio 2", - value: "radioval2", - name: "radioname2", - checked: true, - }, - ], + label: 'radio 2', + value: 'radioval2', + name: 'radioname2', + checked: true + } + ] }; - let textareaConfig = { - type: "textarea", - name: "textareaname1", - value: "textarea prefilled value", - cols: 4, + const textareaConfig = { + type: 'textarea', + name: 'textareaname1', + value: 'textarea prefilled value', + cols: 4 }; - let submitConfig = { - type: "submit", + const submitConfig = { + type: 'submit' }; - let buttonConfig = { - type: "button", - label: "button label", + const buttonConfig = { + type: 'button', + label: 'button label' }; - let getRenderedForm = () => { - let form = new Morebits.quickForm(function () {}); + const getRenderedForm = () => { + const form = new Morebits.QuickForm(() => {}); form.append(inputConfig); form.append(checkboxesConfig); form.append(checkboxListConfig); @@ -80,42 +86,42 @@ describe("quickform", () => { form.append(submitConfig); form.append(buttonConfig); return form.render(); - } + }; - test("input element", () => { + test('input element', () => { expect(renderElement(inputConfig)).toMatchSnapshot(); }); - test("select element", () => { + test('select element', () => { expect(renderElement(selectConfig)).toMatchSnapshot(); }); - test("checkbox elements", () => { + test('checkbox elements', () => { expect(renderElement(checkboxListConfig)).toMatchSnapshot(); }); - test("checkbox elements (with data-single attribute)", () => { + test('checkbox elements (with data-single attribute)', () => { expect(renderElement(checkboxesConfig)).toMatchSnapshot(); }); - test("radio elements", () => { + test('radio elements', () => { expect(renderElement(radiosConfig)).toMatchSnapshot(); }); - test("textarea element", () => { + test('textarea element', () => { expect(renderElement(textareaConfig)).toMatchSnapshot(); }); - test("submit", () => { + test('submit', () => { expect(renderElement(submitConfig)).toMatchSnapshot(); }); - test("getInputData", () => { + test('getInputData', () => { expect(Morebits.quickForm.getInputData(getRenderedForm())).toMatchSnapshot(); }); - test("getElements", () => { - let form = getRenderedForm(); + test('getElements', () => { + const form = getRenderedForm(); expect(Morebits.quickForm.getElements(form, 'checkboxlist1')).toMatchSnapshot(); }); diff --git a/tests/morebits.string.js b/tests/morebits.string.js index 43505b9c7..bce71c9b9 100644 --- a/tests/morebits.string.js +++ b/tests/morebits.string.js @@ -1,27 +1,29 @@ +'use strict'; + describe('Morebits.string', () => { test('escapeRegExp', () => { assert.strictEqual(Morebits.string.escapeRegExp('Four score and seven years ago'), 'Four[_ ]score[_ ]and[_ ]seven[_ ]years[_ ]ago', 'Spaces'); assert.strictEqual(Morebits.string.escapeRegExp('Four_score_and_seven_years_ago'), 'Four[_ ]score[_ ]and[_ ]seven[_ ]years[_ ]ago', 'Underscores'); }); test('formatReasonForLog', () => { - var reason = 'They were wrong'; + const reason = 'They were wrong'; assert.strictEqual(Morebits.string.formatReasonForLog(reason), reason, 'Simple, unchanged'); - var more = 'Really wrong'; + const more = 'Really wrong'; assert.strictEqual(Morebits.string.formatReasonForLog(reason + '\n' + more), reason + '{{pb}}' + more, '\n -> {{pb}}'); assert.strictEqual(Morebits.string.formatReasonForLog('#' + reason + '\n' + more), '##' + reason + '{{pb}}' + more, 'Prepend extra #'); assert.strictEqual(Morebits.string.formatReasonForLog('*' + reason + '\n' + more), '#*' + reason + '{{pb}}' + more, 'Prepend extra #'); }); test('formatReasonText', () => { - var reason = 'They were correct'; + let reason = 'They were correct'; assert.strictEqual(Morebits.string.formatReasonText(reason), reason, 'Simple, unchanged'); assert.strictEqual(Morebits.string.formatReasonText(reason, true), reason + ' ~~~~', 'Simple'); - var more = 'Technically correct'; + const more = 'Technically correct'; assert.strictEqual(Morebits.string.formatReasonText(reason + '|' + more), reason + '{{subst:!}}' + more, 'Replace pipe'); assert.strictEqual(Morebits.string.formatReasonText(reason + '|' + more, true), reason + '{{subst:!}}' + more + ' ~~~~', 'Replace pipe'); reason += 'The {{best|kind|of}} correct: '; assert.strictEqual(Morebits.string.formatReasonText(reason + more), reason + more, 'No replace in nowiki'); assert.strictEqual(Morebits.string.formatReasonText(), '', 'Empty'); - var alreadySigned = 'already signed ~~~~'; + const alreadySigned = 'already signed ~~~~'; assert.strictEqual(Morebits.string.formatReasonText(alreadySigned, true), alreadySigned, 'No sig duplication'); assert.strictEqual(Morebits.string.formatReasonText('alreadySigned~~~~ ', true), 'alreadySigned~~~~', 'trims and avoids duplicating sig'); assert.strictEqual(Morebits.string.formatReasonText('Wow', true), 'Wow ~~~~', '3-letter reason'); @@ -38,13 +40,13 @@ describe('Morebits.string', () => { assert.false(Morebits.string.isInfinity('2020-04-17T09:31:00.000Z'), 'ISO string'); }); test('safeReplace', () => { - var string = '{{subst:board|thread=$SECTION|but=$NOTTHIS}} ~~~~'; + const string = '{{subst:board|thread=$SECTION|but=$NOTTHIS}} ~~~~'; assert.strictEqual(Morebits.string.safeReplace(string, '$SECTIONAL', 'thread$'), string, 'No replacement'); assert.strictEqual(Morebits.string.safeReplace(string, '$SECTION', 'thread$'), '{{subst:board|thread=thread$|but=$NOTTHIS}} ~~~~', 'Replacement'); }); test('splitWeightedByKeys', () => { - var split = ['{{thisis|one|template}}', '{{another|one}}', '[[heresalink]]', '[[thislink|ispiped]]']; - var text = split.join(' also '); + const split = ['{{thisis|one|template}}', '{{another|one}}', '[[heresalink]]', '[[thislink|ispiped]]']; + const text = split.join(' also '); assert.deepEqual(Morebits.string.splitWeightedByKeys(text, '{{', '}}'), split.slice(0, 2), 'Templates'); assert.deepEqual(Morebits.string.splitWeightedByKeys(text, '[[', ']]'), split.slice(2), 'Links'); assert.deepEqual(Morebits.string.splitWeightedByKeys(text, '{{', '}}', split[0]), [split[1]], 'Skiplist, non-array'); diff --git a/tests/morebits.taskManager.js b/tests/morebits.taskManager.js index e3d8e48bf..bcd03db49 100644 --- a/tests/morebits.taskManager.js +++ b/tests/morebits.taskManager.js @@ -1,13 +1,15 @@ +'use strict'; + describe('Morebits.taskManager', () => { test('Contruction', () => { - var tm = new Morebits.taskManager(); + const tm = new Morebits.TaskManager(); assert.true(tm instanceof Morebits.taskManager, 'Correct instance'); }); // Helper to generate functions as well as testing output in proper order; // verifySteps not used because it would require some extra duplication - var data = {}; - var generateFuncs = () => { + const data = {}; + const generateFuncs = () => { data.out = []; ['one', 'two', 'three', 'four'].forEach((step) => { data[step] = () => { @@ -19,7 +21,7 @@ describe('Morebits.taskManager', () => { test('Simple', () => { generateFuncs(); - var simple = new Morebits.taskManager(); + const simple = new Morebits.TaskManager(); simple.add(data.one, []); simple.add(data.two, [data.one]); simple.add(data.three, [data.two]); @@ -30,7 +32,7 @@ describe('Morebits.taskManager', () => { }); test('Complex', () => { generateFuncs(); - var complex = new Morebits.taskManager(); + const complex = new Morebits.TaskManager(); complex.add(data.one, [data.two]); complex.add(data.two, [data.three, data.four]); complex.add(data.three, []); diff --git a/tests/morebits.unbinder.js b/tests/morebits.unbinder.js index fa3419557..4c4cd6644 100644 --- a/tests/morebits.unbinder.js +++ b/tests/morebits.unbinder.js @@ -1,19 +1,21 @@ +'use strict'; + describe('Morebits.unbinder', () => { test('Construction', () => { - assert.throws(() => new Morebits.unbinder(), 'throws: no string'); - assert.throws(() => new Morebits.unbinder([42]), 'throws: not a string'); - var u = new Morebits.unbinder('Hello world'); + assert.throws(() => new Morebits.Unbinder(), 'throws: no string'); + assert.throws(() => new Morebits.Unbinder([42]), 'throws: not a string'); + const u = new Morebits.Unbinder('Hello world'); assert.true(u instanceof Morebits.unbinder, 'Correct instance'); assert.throws(() => u.unbind(), 'throws: Missing prefix'); assert.throws(() => u.unbind('w'), 'throws: Missing postfix'); }); test('Run', () => { - var u = new Morebits.unbinder('Hello world world'); + let u = new Morebits.Unbinder('Hello world world'); u.unbind(''); u.content = u.content.replace(/world/g, 'earth'); assert.strictEqual(u.rebind(), 'Hello earth earth', 'Simple replace'); - u = new Morebits.unbinder('Hello world world [link link] [[link|link]]'); + u = new Morebits.Unbinder('Hello world world [link link] [[link|link]]'); assert.true(u instanceof Morebits.unbinder, 'Correct instance'); u.unbind(''); u.unbind('\\[\\[', '\\]\\]'); diff --git a/tests/morebits.wikitext.js b/tests/morebits.wikitext.js index c1942878d..a6e5a3b45 100644 --- a/tests/morebits.wikitext.js +++ b/tests/morebits.wikitext.js @@ -1,15 +1,17 @@ +'use strict'; + describe('Morebits.wikitext', () => { test('parseTemplate', () => { // Function to help build a template from a sample object - var makeTemplate = function (data) { - var template = '{{' + data.name; - Object.keys(data.parameters).forEach(function (key) { + const makeTemplate = function (data) { + let template = '{{' + data.name; + Object.keys(data.parameters).forEach((key) => { template += '|' + key + '=' + data.parameters[key]; }); return template + '}}'; }; - var simple = { + const simple = { name: 'prod', parameters: { reason: 'because', @@ -19,7 +21,7 @@ describe('Morebits.wikitext', () => { }; assert.deepEqual(Morebits.wikitext.parseTemplate('Template: ' + makeTemplate(simple) + ' in text', 10), simple, 'Basic parameters'); - var involved = { + const involved = { name: 'Proposed deletion/dated', parameters: { concern: 'Text (paren) then [[piped|link]] and [[WP:WP/LINK]] {{{plural|with|a|template}}} then question?', @@ -31,10 +33,10 @@ describe('Morebits.wikitext', () => { assert.deepEqual(Morebits.wikitext.parseTemplate(makeTemplate(involved)), involved, 'Involved parameters'); // Try a variety of whitespace options - var whitespace = '{{' + involved.name + ' |concern = ' + involved.parameters.concern + ' | timestamp =' + involved.parameters.timestamp + '| nom= ' + involved.parameters.nom + '|help = ' + involved.parameters.help + ' }}'; + const whitespace = '{{' + involved.name + ' |concern = ' + involved.parameters.concern + ' | timestamp =' + involved.parameters.timestamp + '| nom= ' + involved.parameters.nom + '|help = ' + involved.parameters.help + ' }}'; assert.deepEqual(Morebits.wikitext.parseTemplate(whitespace), involved, 'Involved parameters with whitespace'); - var unnamed = { + const unnamed = { name: 'db-meta', parameters: { criterion: 'G13', @@ -43,10 +45,10 @@ describe('Morebits.wikitext', () => { 2: 'extra' } }; - var unnamedTemplate = '{{' + unnamed.name + '|criterion=' + unnamed.parameters.criterion + '||' + unnamed.parameters['1'] + '| middle =|2= ' + unnamed.parameters['2'] + '|}}'; + const unnamedTemplate = '{{' + unnamed.name + '|criterion=' + unnamed.parameters.criterion + '||' + unnamed.parameters['1'] + '| middle =|2= ' + unnamed.parameters['2'] + '|}}'; assert.deepEqual(Morebits.wikitext.parseTemplate(unnamedTemplate), unnamed, 'Unnamed and empty parameters'); - var multiLevel = { + const multiLevel = { name: 'toplevel', parameters: { named: '{{namedtop}}', @@ -56,7 +58,7 @@ describe('Morebits.wikitext', () => { } }; assert.deepEqual(Morebits.wikitext.parseTemplate(makeTemplate(multiLevel)), multiLevel, 'Multiple levels'); - var parser = { + const parser = { name: 'toplevel', parameters: { named: '{{namedtop}}', @@ -67,7 +69,7 @@ describe('Morebits.wikitext', () => { }; assert.deepEqual(Morebits.wikitext.parseTemplate(makeTemplate(parser)), parser, 'Parser function'); - var internal = { + const internal = { name: 'internal', parameters: { named: 'parameter {{tq|with an internal}} template', @@ -80,18 +82,18 @@ describe('Morebits.wikitext', () => { }); test('Morebits.wikitext.page', () => { - var text = '{{short description}}{{about}}[[File:Fee.svg]]O, [[Juliet|she]] doth {{plural|teach}} the torches to burn bright!'; - var page = new Morebits.wikitext.page(text); + const text = '{{short description}}{{about}}[[File:Fee.svg]]O, [[Juliet|she]] doth {{plural|teach}} the torches to burn bright!'; + const page = new Morebits.wikitext.Page(text); assert.true(page instanceof Morebits.wikitext.page, 'Correct instance'); assert.strictEqual(page.getText(), text, 'Got text'); // Throws - assert.throws(() => new Morebits.wikitext.page(text).insertAfterTemplates(), 'throws: no tag'); - assert.throws(() => new Morebits.wikitext.page(text).insertAfterTemplates('tag'), 'throws: no regex'); + assert.throws(() => new Morebits.wikitext.Page(text).insertAfterTemplates(), 'throws: no tag'); + assert.throws(() => new Morebits.wikitext.Page(text).insertAfterTemplates('tag'), 'throws: no regex'); // Define all the tests individually, with the appropriate method, // input, expected output, and (spreaded) parameters. - var tests = [ + const tests = [ { name: 'simple', method: 'removeLink', @@ -354,7 +356,7 @@ describe('Morebits.wikitext', () => { ]; tests.forEach((test) => { - var page = new Morebits.wikitext.page(test.input); + const page = new Morebits.wikitext.Page(test.input); assert.strictEqual(page[test.method](...test.params).getText(), test.expected, test.method + ' - ' + test.name); }); }); diff --git a/twinkle.js b/twinkle.js index c6041c408..4e9e012c0 100644 --- a/twinkle.js +++ b/twinkle.js @@ -375,7 +375,7 @@ Twinkle.load = function () { activeSpecialPageList = activeSpecialPageList.concat([ 'DeletedContributions', 'Prefixindex' ]); } if (mw.config.get('wgNamespaceNumber') === -1 && - activeSpecialPageList.indexOf(mw.config.get('wgCanonicalSpecialPageName')) === -1) { + !activeSpecialPageList.includes(mw.config.get('wgCanonicalSpecialPageName'))) { return; } @@ -392,7 +392,7 @@ Twinkle.load = function () { // Redefine addInitCallback so that any modules being loaded now on are directly // initialised rather than added to initCallbacks array Twinkle.addInitCallback = function(func, name) { - if (!name || Twinkle.disabledModules.indexOf(name) === -1) { + if (!name || !Twinkle.disabledModules.includes(name)) { func(); } };