Make the limited width and font size controls work for logged in users

For time being manage classes inside Vector. Document with FIXME and a
test.

Bug: T351447
Change-Id: Icc084a59a0141ec2b7c772cf92e8cc58c11f15b1
This commit is contained in:
Jon Robson 2023-11-20 14:55:41 -08:00 committed by Jdlrobson
parent c4802af02c
commit 845a0ab71d
7 changed files with 81 additions and 22 deletions

View file

@ -47,6 +47,10 @@ module.exports = {
'vue'
],
modulePathIgnorePatterns: [
'<rootDir>/tests/integration-qunit/'
],
// The paths to modules that run some code to configure or
// set up the testing environment before each test
setupFiles: [

14
package-lock.json generated
View file

@ -15,7 +15,7 @@
"@wikimedia/codex": "0.20.0",
"@wikimedia/codex-icons": "0.20.0",
"@wikimedia/mw-node-qunit": "7.2.0",
"@wikimedia/types-wikimedia": "0.4.1",
"@wikimedia/types-wikimedia": "0.4.2",
"eslint-config-wikimedia": "0.25.1",
"eslint-plugin-no-jquery": "2.7.0",
"grunt-banana-checker": "0.11.0",
@ -2562,9 +2562,9 @@
"dev": true
},
"node_modules/@wikimedia/types-wikimedia": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@wikimedia/types-wikimedia/-/types-wikimedia-0.4.1.tgz",
"integrity": "sha512-RJUZXQNo+z7zBjcRSsVRR5GH2/R8/aSJc9Vo/ntnTzr8v1TjUlM3Dh4sP6XQODYKm/0HQn+hln3bWyeU6YTyRw==",
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/@wikimedia/types-wikimedia/-/types-wikimedia-0.4.2.tgz",
"integrity": "sha512-MWZJE6JRUYRSuwajjiO4l7xz6530MUqdTOP0t0AteVm8Gqs+hUEcs5tTmAVJDg/ByvzyZ/M/KsW1UcuTRs0N8g==",
"dev": true
},
"node_modules/abab": {
@ -14469,9 +14469,9 @@
}
},
"@wikimedia/types-wikimedia": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@wikimedia/types-wikimedia/-/types-wikimedia-0.4.1.tgz",
"integrity": "sha512-RJUZXQNo+z7zBjcRSsVRR5GH2/R8/aSJc9Vo/ntnTzr8v1TjUlM3Dh4sP6XQODYKm/0HQn+hln3bWyeU6YTyRw==",
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/@wikimedia/types-wikimedia/-/types-wikimedia-0.4.2.tgz",
"integrity": "sha512-MWZJE6JRUYRSuwajjiO4l7xz6530MUqdTOP0t0AteVm8Gqs+hUEcs5tTmAVJDg/ByvzyZ/M/KsW1UcuTRs0N8g==",
"dev": true
},
"abab": {

View file

@ -26,7 +26,7 @@
"@wikimedia/codex": "0.20.0",
"@wikimedia/codex-icons": "0.20.0",
"@wikimedia/mw-node-qunit": "7.2.0",
"@wikimedia/types-wikimedia": "0.4.1",
"@wikimedia/types-wikimedia": "0.4.2",
"eslint-config-wikimedia": "0.25.1",
"eslint-plugin-no-jquery": "2.7.0",
"grunt-banana-checker": "0.11.0",

View file

@ -21,14 +21,40 @@ function getClientPreferences() {
).map( ( className ) => className.split( '-clientpref-' )[ 0 ] );
}
/**
* @param {string} featureName
* @param {string} value
*/
function toggleDocClassAndSave( featureName, value ) {
const pref = config[ featureName ];
if ( mw.user.isNamed() ) {
// FIXME: Ideally this would be done in mw.user.clientprefs API.
// mw.user.clientPrefs.get is marked as being only stable for anonymous and temporary users.
// So instead we have to keep track of all the different possible values and remove them
// before adding the new class.
config[ featureName ].options.forEach( ( possibleValue ) => {
document.documentElement.classList.remove( `${featureName}-clientpref-${possibleValue}` );
} );
document.documentElement.classList.add( `${featureName}-clientpref-${value}` );
// Ideally this should be taken care of via a single core helper function.
mw.util.debounce( function () {
api = api || new mw.Api();
api.saveOption( pref.preferenceKey, value );
}, 100 )();
// END FIXME.
} else {
// This case is much simpler - the API transparently takes care of classes as well as storage.
mw.user.clientPrefs.set( featureName, value );
}
}
/**
* @param {Element} parent
* @param {string} featureName
* @param {ClientPreference} pref
* @param {string} value
* @param {string} currentValue
*/
function appendRadioToggle( parent, featureName, pref, value, currentValue ) {
function appendRadioToggle( parent, featureName, value, currentValue ) {
const input = document.createElement( 'input' );
const name = `vector-client-pref-${featureName}-group`;
const id = `vector-client-pref-${featureName}-value-${value}`;
@ -55,14 +81,7 @@ function appendRadioToggle( parent, featureName, pref, value, currentValue ) {
container.appendChild( label );
parent.appendChild( container );
input.addEventListener( 'change', () => {
// @ts-ignore https://github.com/wikimedia/typescript-types/pull/44
mw.user.clientPrefs.set( featureName, value );
if ( mw.user.isNamed() ) {
mw.util.debounce( function () {
api = api || new mw.Api();
api.saveOption( pref.preferenceKey, value );
}, 100 )();
}
toggleDocClassAndSave( featureName, value );
} );
}
@ -87,17 +106,16 @@ function makeClientPreferenceBinaryToggle( featureName ) {
if ( !pref ) {
return null;
}
// @ts-ignore https://github.com/wikimedia/typescript-types/pull/44
const currentValue = mw.user.clientPrefs.get( featureName );
// The client preference was invalid. This shouldn't happen unless a gadget
// or script has modified the documentElement.
if ( !currentValue ) {
if ( typeof currentValue === 'boolean' ) {
return null;
}
const row = createRow( '' );
const form = document.createElement( 'form' );
pref.options.forEach( ( value ) => {
appendRadioToggle( form, featureName, pref, value, currentValue );
appendRadioToggle( form, featureName, value, currentValue );
} );
row.appendChild( form );
return row;
@ -194,5 +212,6 @@ function bind( clickSelector, renderSelector ) {
}
module.exports = {
bind,
toggleDocClassAndSave,
render
};

View file

@ -549,6 +549,14 @@
"+ext.uls.interface": "skinStyles/ext.uls.interface.less"
}
},
"QUnitTestModule": {
"localBasePath": "",
"remoteExtPath": "Vector",
"dependencies": [ "skins.vector.clientPreferences" ],
"scripts": [
"tests/integration-qunit/integration.test.js"
]
},
"config": {
"VectorClientPreferences": {
"value": {

View file

@ -0,0 +1,27 @@
/* global QUnit */
const clientPreferences = require( 'skins.vector.clientPreferences' );
/*!
* Vector integration tests.
*
* This should only be used to test APIs that Vector depends on to work.
* For unit tests please see tests/jest.
*/
QUnit.module( 'Vector (integration)', function () {
QUnit.test( 'Client preferences: Behaves same for all users', function ( assert ) {
const sandbox = this.sandbox;
const helper = ( feature, isNamedReturnValue ) => {
document.documentElement.setAttribute( 'class', `${feature}-clientpref-0` );
const stub = sandbox.stub( mw.user, 'isNamed', () => isNamedReturnValue );
clientPreferences.toggleDocClassAndSave( feature, '1' );
stub.restore();
return document.documentElement.getAttribute( 'class' );
};
assert.strictEqual(
helper( 'vector-feature-limited-width', false ),
helper( 'vector-feature-limited-width', true ),
'The same classes are modified regardless of the user status.'
);
} );
} );

View file

@ -4,7 +4,8 @@
"jest.setup.js",
"vendor",
"coverage",
"tests/jest"
"tests/jest",
"tests/integration-qunit"
],
"compilerOptions": {
"resolveJsonModule": true,