$( '.dbRadio' ).on( 'click', function () {
var $checked = $( '.dbRadio:checked' ),
$wrapper = $( document.getElementById( $checked.attr( 'rel' ) ) );
+ // eslint-disable-next-line no-jquery/no-sizzle
if ( $wrapper.is( ':hidden' ) ) {
// FIXME: Use CSS transition
// eslint-disable-next-line no-jquery/no-animate-toggle
}
},
"eslint-config-wikimedia": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.12.0.tgz",
- "integrity": "sha512-ZkmGLvwmoEacj55t8Z6VH6wUu4/XTlgkSCerHkj+VU4tmyCD4mlzvTeSaPzOEDmZTVWUoiKnB6mvUx06l7uIbw==",
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.13.0.tgz",
+ "integrity": "sha512-l64xMCgPE949H9rfhC0Ir+UaNAh685CE6xSnWkMU5yNryNTdL91lW8KcMFgMqmmH0Q+Jq+7DIdfGaVld6nQ80w==",
"dev": true,
"requires": {
"eslint": "^5.16.0",
"eslint-plugin-json": "^1.4.0",
- "eslint-plugin-no-jquery": "^2.0.0",
+ "eslint-plugin-no-jquery": "^2.1.0",
"eslint-plugin-qunit": "^4.0.0"
},
"dependencies": {
}
},
"eslint-plugin-no-jquery": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.0.0.tgz",
- "integrity": "sha512-aFy3fMBlc630/qeasjocb9uIqmwoyOmmTQiBaDs70Aryqi9uPH0EZLPtIOshDMcGeAkyyAkcc+WuIw6bRsoLuw==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.1.0.tgz",
+ "integrity": "sha512-5sr5tOJRfuRviyAvFTe/mr80TXWxTteD/JHRuJtDN8q/bxAh16eSKoKLAevLC7wZCRN2iwnEfhQPQV4rp/gYtg==",
"dev": true
},
"eslint-plugin-qunit": {
"dev": true
},
"vscode-json-languageservice": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.2.1.tgz",
- "integrity": "sha512-ee9MJ70/xR55ywvm0bZsDLhA800HCRE27AYgMNTU14RSg20Y+ngHdQnUt6OmiTXrQDI/7sne6QUOtHIN0hPQYA==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.3.0.tgz",
+ "integrity": "sha512-upq1PhwDItazdtRJ/R7uU0Fgrf9iaYa1xLK4WFLExR0DgbPojd0YgMpfyknVyXGlxsg3fJQ0H7J++QeByXHh9w==",
"dev": true,
"requires": {
- "jsonc-parser": "^2.0.2",
- "vscode-languageserver-types": "^3.13.0",
- "vscode-nls": "^4.0.0",
- "vscode-uri": "^1.0.6"
+ "jsonc-parser": "^2.1.0",
+ "vscode-languageserver-types": "^3.15.0-next.2",
+ "vscode-nls": "^4.1.1",
+ "vscode-uri": "^2.0.1"
}
},
"vscode-languageserver-types": {
- "version": "3.14.0",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz",
- "integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==",
+ "version": "3.15.0-next.2",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz",
+ "integrity": "sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ==",
"dev": true
},
"vscode-nls": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.0.tgz",
- "integrity": "sha512-zKsFWVzL1wlCezgaI3XiN42IT8DIPM1Qr+G+RBhiU3U0bJCdC8pPELakRCtuVT4wF3gBZjBrUDQ8mowL7hmgwA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.1.tgz",
+ "integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==",
"dev": true
},
"vscode-uri": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz",
- "integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.0.2.tgz",
+ "integrity": "sha512-VebpIxm9tG0fG2sBOhnsSPzDYuNUPP1UQW4K3mwthlca4e4f3d6HKq3HkITC2OPFomOaB7pHTSjcpdFWjfYTzg==",
"dev": true
},
"wdio-dot-reporter": {
"selenium-test": "wdio ./tests/selenium/wdio.conf.js"
},
"devDependencies": {
- "eslint-config-wikimedia": "0.12.0",
+ "eslint-config-wikimedia": "0.13.0",
"grunt": "1.0.4",
"grunt-banana-checker": "0.7.0",
"grunt-contrib-copy": "1.0.0",
// eslint-disable-next-line no-jquery/no-map-util
return $.map( node.childNodes, function ( elem ) {
if ( elem.nodeType === Node.ELEMENT_NODE ) {
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $( elem ).hasClass( 'reference' ) ) {
return null;
}
while ( i < l ) {
// if this is a child row, continue to the next row (as buildCache())
+ // eslint-disable-next-line no-jquery/no-class-state
if ( rows[ rowIndex ] && !$( rows[ rowIndex ] ).hasClass( config.cssChildRow ) ) {
if ( rowIndex !== lastRowIndex ) {
lastRowIndex = rowIndex;
// if this is a child row, add it to the last row's children and
// continue to the next row
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $row.hasClass( config.cssChildRow ) ) {
cache.row[ cache.row.length - 1 ] = cache.row[ cache.row.length - 1 ].add( $row );
// go to the next for loop
$cell = $( this );
columns = [];
+ // eslint-disable-next-line no-jquery/no-class-state
if ( !$cell.hasClass( config.unsortableClass ) ) {
$cell
.addClass( config.cssHeader )
$row = $rows.eq( i );
// if this is a child row, continue to the next row (as buildCache())
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $row.hasClass( config.cssChildRow ) ) {
// go to the next for loop
continue;
sideMargin = 'marginLeft';
}
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $element.hasClass( 'jquery-confirmable-element' ) ) {
$wrapper = $element.closest( '.jquery-confirmable-wrapper' );
$interface = $wrapper.find( '.jquery-confirmable-interface' );
if ( options.wasCollapsed !== undefined ) {
wasCollapsed = options.wasCollapsed;
} else {
+ // eslint-disable-next-line no-jquery/no-class-state
wasCollapsed = $collapsible.hasClass( 'mw-collapsed' );
}
} );
// Initial state
+ // eslint-disable-next-line no-jquery/no-class-state
if ( options.collapsed || $collapsible.hasClass( 'mw-collapsed' ) ) {
// One toggler can hook to multiple elements, and one element can have
// multiple togglers. This is the sanest way to handle that.
context.data.prevText = '';
} else if (
val !== context.data.prevText ||
+ // eslint-disable-next-line no-jquery/no-sizzle
!context.data.$container.is( ':visible' )
) {
context.data.prevText = val;
*/
function keypress( e, context, key ) {
var selected,
+ // eslint-disable-next-line no-jquery/no-sizzle
wasVisible = context.data.$container.is( ':visible' ),
preventDefault = false;
$copyAction = $copyForm.find( '> [name="action"]' );
// Remove action=historysubmit and ids[..]=..
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $historySubmitter.hasClass( 'mw-history-compareselectedversions-button' ) ) {
$copyAction.remove();
$copyForm.find( 'input[name^="ids["]:checked' ).prop( 'checked', false );
// Remove diff=&oldid=, change action=historysubmit to revisiondelete, remove revisiondelete
- } else if ( $historySubmitter.hasClass( 'mw-history-revisiondelete-button' ) ||
- $historySubmitter.hasClass( 'mw-history-editchangetags-button' ) ) {
+ } else if (
+ // eslint-disable-next-line no-jquery/no-class-state
+ $historySubmitter.hasClass( 'mw-history-revisiondelete-button' ) ||
+ // eslint-disable-next-line no-jquery/no-class-state
+ $historySubmitter.hasClass( 'mw-history-editchangetags-button' )
+ ) {
$copyRadios.remove();
$copyAction.val( $historySubmitter.attr( 'name' ) );
+ // eslint-disable-next-line no-jquery/no-sizzle
$copyForm.find( ':submit' ).remove();
}
e.type === 'click' ||
e.type === 'keypress' && e.which === 13
) {
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $table.hasClass( 'collapsed' ) ) {
// From collapsed to expanded. Button will now collapse.
$( this ).text( collapseText );
// From expanded to collapsed. Button will now expand.
$( this ).text( expandText );
}
+ // eslint-disable-next-line no-jquery/no-class-state
$table.toggleClass( 'collapsed' );
}
} );
};
if (
$oldErrorBox !== $errorBox &&
+ // eslint-disable-next-line no-jquery/no-class-state
( $oldErrorBox.hasClass( 'error' ) || $oldErrorBox.hasClass( 'warning' ) )
) {
// eslint-disable-next-line no-jquery/no-slide
var $element = $( this ),
deleteButton;
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $element.hasClass( 'oo-ui-widget' ) ) {
deleteButton = OO.ui.infuse( $element );
deleteButton.on( 'click', function () {
deleteButton.$element.closest( 'li.mw-htmlform-cloner-li' ).remove();
} );
} else {
+ // eslint-disable-next-line no-jquery/no-sizzle
$element.filter( ':input' ).on( 'click', function ( e ) {
e.preventDefault();
$( this ).closest( 'li.mw-htmlform-cloner-li' ).remove();
}
} );
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $createElement.hasClass( 'oo-ui-widget' ) ) {
createButton = OO.ui.infuse( $createElement );
createButton.on( 'click', function () {
appendToCloner( createButton.$element );
} );
} else {
+ // eslint-disable-next-line no-jquery/no-sizzle
$createElement.filter( ':input' ).on( 'click', function ( e ) {
e.preventDefault();
$link = $( this );
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $link.hasClass( 'loading' ) ) {
return;
}
// Collect the relevant classes from the first nested child
firstChildClasses = activeHighlightClasses.filter( function ( className ) {
+ // eslint-disable-next-line no-jquery/no-class-state
return $table.find( 'tr:nth-child(2)' ).hasClass( className );
} );
// Filter the non-head rows and see if they all have the same classes
$this = $( this );
classesInThisRow = activeHighlightClasses.filter( function ( className ) {
+ // eslint-disable-next-line no-jquery/no-class-state
return $this.hasClass( className );
} );
FilterTagMultiselectWidget.prototype.emphasize = function () {
if (
+ // eslint-disable-next-line no-jquery/no-class-state
!this.$handle.hasClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-animate' )
) {
this.$handle
.text( query );
}
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $el.parent().hasClass( 'mw-searchSuggest-link' ) ) {
$el.parent().attr( 'href', formData.baseHref + $.param( formData.linkParams ) + '&fulltext=1' );
} else {
function updateImportSubprojectList() {
var $projectField = $( '#mw-import-table-interwiki #interwiki' ),
$subprojectField = $projectField.parent().find( '#subproject' ),
+ // eslint-disable-next-line no-jquery/no-sizzle
$selected = $projectField.find( ':selected' ),
oldValue = $subprojectField.val(),
option, options;
// (This function could be changed to infuse and check OOUI widgets, but that would only make it
// slower and more complicated. It works fine to treat them as HTML elements.)
function isPrefsChanged() {
+ // eslint-disable-next-line no-jquery/no-sizzle
var inputs = $( '#mw-prefs-form :input[name]' ),
input, $input, inputType,
index, optIndex,
mw.loader.load( 'mediawiki.notification' );
// Use the class to determine whether to watch or unwatch
+ // eslint-disable-next-line no-jquery/no-class-state
if ( !$subjectLink.hasClass( 'mw-watched-item' ) ) {
$link.text( mw.msg( 'watching' ) );
promise = api.watch( title ).done( function () {
// Depending on whether we are watching or unwatching, for each entry of the page (and its associated page i.e. Talk),
// change the text, tooltip, and non-JS href of the (un)watch button, and update the styling of the watchlist entry.
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $unwatchLink.hasClass( 'mw-unwatch-link' ) ) {
api.unwatch( pageTitle )
.done( function () {
// Hide/show the table of contents element
function toggleToc() {
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $this.hasClass( 'tochidden' ) ) {
// FIXME: Use CSS transitions
// eslint-disable-next-line no-jquery/no-slide
$portlet.removeClass( 'emptyPortlet' );
// Setup the list item (and a span if $portlet is a Vector tab)
+ // eslint-disable-next-line no-jquery/no-class-state
if ( $portlet.hasClass( 'vectorTabs' ) ) {
item = $( '<li>' ).append( $( '<span>' ).append( link )[ 0 ] )[ 0 ];
} else {
mw.widgets.MediaSearchWidget.prototype.runLayoutQueue = function () {
var i, len;
+ // eslint-disable-next-line no-jquery/no-sizzle
if ( this.$element.is( ':visible' ) ) {
for ( i = 0, len = this.layoutQueue.length; i < len; i++ ) {
this.layoutQueue.pop()();
if (
!this.isDisabled() &&
e.which === 1 &&
+ // eslint-disable-next-line no-jquery/no-class-state
$( e.target ).hasClass( targetClass )
) {
this.deactivate( true );
'<div>' + loremIpsum + '</div>'
);
+ // eslint-disable-next-line no-jquery/no-class-state
assert.assertTrue( $collapsible.hasClass( 'mw-collapsible' ), 'mw-collapsible class present' );
} );
{ collapsed: true }
);
+ // eslint-disable-next-line no-jquery/no-class-state
assert.assertTrue( $collapsible.hasClass( 'mw-collapsed' ), 'mw-collapsed class present' );
} );
.appendTo( '#qunit-fixture' ).makeCollapsible();
$collapsible1.on( 'afterCollapse.mw-collapsible', function () {
+ // eslint-disable-next-line no-jquery/no-class-state
assert.assertTrue( $collapsible1.hasClass( 'mw-collapsed' ), 'after collapsing: parent is collapsed' );
+ // eslint-disable-next-line no-jquery/no-class-state
assert.assertFalse( $collapsible2.hasClass( 'mw-collapsed' ), 'after collapsing: child is not collapsed' );
+ // eslint-disable-next-line no-jquery/no-class-state
assert.assertTrue( $collapsible1.find( '> .mw-collapsible-toggle' ).hasClass( 'mw-collapsible-toggle-collapsed' ) );
+ // eslint-disable-next-line no-jquery/no-class-state
assert.assertFalse( $collapsible2.find( '> .mw-collapsible-toggle' ).hasClass( 'mw-collapsible-toggle-collapsed' ) );
} ).find( '> .mw-collapsible-toggle a' ).trigger( 'click' );
} );
$table.find( 'tr > th' ).eq( 1 ).trigger( 'click' );
assert.strictEqual(
+ // eslint-disable-next-line no-jquery/no-class-state
$cell.hasClass( 'headerSortUp' ) || $cell.hasClass( 'headerSortDown' ),
false,
'after sort: no class headerSortUp or headerSortDown'
mw.config.set( 'wgPageContentLanguage', 'sv' );
$table.tablesorter();
+ // eslint-disable-next-line no-jquery/no-sizzle
$table.find( '.headerSort:eq(0)' ).trigger( 'click' );
}
);
// TODO abstract the double strictEquals
// At first checkboxes are hidden
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $( '#nsinvert' ).closest( '.mw-input-with-label' ).hasClass( 'mw-input-hidden' ), true );
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $( '#nsassociated' ).closest( '.mw-input-with-label' ).hasClass( 'mw-input-hidden' ), true );
// Initiate the recentchanges module
rc.init();
// By default
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $( '#nsinvert' ).closest( '.mw-input-with-label' ).hasClass( 'mw-input-hidden' ), true );
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $( '#nsassociated' ).closest( '.mw-input-with-label' ).hasClass( 'mw-input-hidden' ), true );
// select second option...
$( '#namespace' ).trigger( 'change' );
// ... and checkboxes should be visible again
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $( '#nsinvert' ).closest( '.mw-input-with-label' ).hasClass( 'mw-input-hidden' ), false );
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $( '#nsassociated' ).closest( '.mw-input-with-label' ).hasClass( 'mw-input-hidden' ), false );
// select first option ( 'all' namespace)...
$( '#namespace' ).trigger( 'change' );
// ... and checkboxes should now be hidden
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $( '#nsinvert' ).closest( '.mw-input-with-label' ).hasClass( 'mw-input-hidden' ), true );
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $( '#nsassociated' ).closest( '.mw-input-with-label' ).hasClass( 'mw-input-hidden' ), true );
// DOM cleanup
assert.strictEqual( $toggleLink.length, 1, 'Toggle link is added to the table of contents' );
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $toc.hasClass( 'tochidden' ), false, 'The table of contents is now visible' );
$toggleLink.trigger( 'click' );
return $tocList.promise().then( function () {
+ // eslint-disable-next-line no-jquery/no-class-state
assert.strictEqual( $toc.hasClass( 'tochidden' ), true, 'The table of contents is now hidden' );
$toggleLink.trigger( 'click' );
return $tocList.promise();
"mw": false
},
"rules": {
- "no-console": 0
+ "no-console": "off",
+ "prefer-template": "off"
}
}
}
vandalizePage( name, content ) {
- let vandalUsername = 'Evil_' + browser.options.username;
+ const vandalUsername = 'Evil_' + browser.options.username;
browser.call( function () {
return Api.edit( name, content );
} );
it( 'should be re-creatable', function () {
- let initialContent = Util.getTestString( 'initialContent-' );
+ const initialContent = Util.getTestString( 'initialContent-' );
// create
browser.call( function () {
} );
// edit
- let editContent = Util.getTestString( 'editContent-' );
+ const editContent = Util.getTestString( 'editContent-' );
EditPage.edit( name, editContent );
// check
password = browser.options.password,
baseUrl = browser.options.baseUrl
) {
- let bot = new MWBot();
+ const bot = new MWBot();
return bot.loginGetEditToken( {
apiUrl: `${baseUrl}/api.php`,
* @return {Object} Promise for API action=delete response data.
*/
delete( title, reason ) {
- let bot = new MWBot();
+ const bot = new MWBot();
return bot.loginGetEditToken( {
apiUrl: `${browser.options.baseUrl}/api.php`,
* @return {Object} Promise for API action=createaccount response data.
*/
createAccount( username, password ) {
- let bot = new MWBot();
+ const bot = new MWBot();
// Log in as admin
return bot.loginGetCreateaccountToken( {
* @return {Object} Promise for API action=block response data.
*/
blockUser( username, expiry ) {
- let bot = new MWBot();
+ const bot = new MWBot();
// Log in as admin
return bot.loginGetEditToken( {
* @return {Object} Promise for API action=unblock response data.
*/
unblockUser( username ) {
- let bot = new MWBot();
+ const bot = new MWBot();
// Log in as admin
return bot.loginGetEditToken( {
MAINPAGE_REQUESTS_MAX_RUNS = 10; // (arbitrary) safe-guard against endless execution
function getJobCount() {
- let bot = new MWBot( {
+ const bot = new MWBot( {
apiUrl: `${browser.options.baseUrl}/api.php`
} );
return bot.request( {
}
function runThroughMainPageRequests( runCount = 1 ) {
- let page = new Page();
+ const page = new Page();
log( `through requests to the main page (run ${runCount}).` );
page.openTitle( '' );
beforeTest: function ( test ) {
if ( process.env.DISPLAY && process.env.DISPLAY.startsWith( ':' ) ) {
var logBuffer;
- let videoPath = filePath( test, logPath, 'mp4' );
+ const videoPath = filePath( test, logPath, 'mp4' );
const { spawn } = require( 'child_process' );
ffmpeg = spawn( 'ffmpeg', [
'-f', 'x11grab', // grab the X11 display
] );
logBuffer = function ( buffer, prefix ) {
- let lines = buffer.toString().trim().split( '\n' );
+ const lines = buffer.toString().trim().split( '\n' );
lines.forEach( function ( line ) {
console.log( prefix + line );
} );
return;
}
// save screenshot
- let screenshotfile = filePath( test, logPath, 'png' );
+ const screenshotfile = filePath( test, logPath, 'png' );
browser.saveScreenshot( screenshotfile );
console.log( '\n\tScreenshot location:', screenshotfile, '\n' );
}