Merge "Generalize settings code (attempt 2)"

This commit is contained in:
jenkins-bot 2024-01-10 11:36:38 +00:00 committed by Gerrit Code Review
commit 93d9c88c26
27 changed files with 270 additions and 163 deletions

View file

@ -16,7 +16,7 @@ module.exports = {
// Set the coverage percentage by category thresholds.
statements: 80,
branches: 70,
branches: 69,
functions: 80,
lines: 90,

View file

@ -70,7 +70,7 @@
"bundlesize": [
{
"path": "resources/dist/index.js",
"maxSize": "14.8kB"
"maxSize": "15.1kB"
}
]
}

Binary file not shown.

Binary file not shown.

View file

@ -12,8 +12,15 @@ if ( !isTouchDevice && supportNotQueries ) {
mw.loader.using( types.concat( [ 'ext.popups.main' ] ) ).then( function () {
// Load custom popup types
types.forEach( function ( moduleName ) {
var module = require( moduleName );
mw.popups.register( module );
const module = require( moduleName );
// Check the module exists. A module can export undefined or null if
// it does not want to be registered (for example where registration may
// depend on something that can only be checked at runtime.
// For example the Math module shouldn't register itself if there are no Math
// equations on the page.
if ( module ) {
mw.popups.register( module );
}
} );
// For now this API is limited to extensions/skins as we have not had a chance to
// consider the implications of gadgets having access to this function and dealing with

View file

@ -5,6 +5,7 @@
export default {
BOOT: 'BOOT',
LINK_DWELL: 'LINK_DWELL',
REGISTER_SETTING: 'REGISTER_SETTING',
ABANDON_START: 'ABANDON_START',
ABANDON_END: 'ABANDON_END',
LINK_CLICK: 'LINK_CLICK',

View file

@ -72,6 +72,22 @@ export function boot(
};
}
/**
* Registers a page preview setting for anonymous users.
*
* @param {string} name setting name which is used for storage and deriving associated
* messages.
* @param {boolean} enabled is the feature enabled by default?
* @return {Object}
*/
export function registerSetting( name, enabled ) {
return {
type: types.REGISTER_SETTING,
name,
enabled
};
}
/**
* Represents Page Previews fetching data via the gateway.
*
@ -213,7 +229,6 @@ export function linkDwell( title, el, measures, gateway, generateToken, type ) {
return promise.then( () => {
const previewState = getState().preview;
const enabledValue = previewState.enabled[ type ];
// Note: Only reference previews and default previews can be disabled at this point.
// If there is no UI the enabledValue is always true.
const isEnabled = typeof enabledValue === 'undefined' ? true : enabledValue;

View file

@ -13,12 +13,19 @@ export default function settings( boundActions, render ) {
// Nothing to do on initialization
return;
}
if (
settingsObj &&
Object.keys( oldState.settings.previewTypesEnabled ).length !== Object.keys( newState.settings.previewTypesEnabled ).length
) {
// the number of settings changed so force it to be repainted.
settingsObj.refresh( newState.settings.previewTypesEnabled );
}
// Update global modal visibility
if ( oldState.settings.shouldShow === false && newState.settings.shouldShow ) {
// Lazily instantiate the settings UI
if ( !settingsObj ) {
settingsObj = render( boundActions );
settingsObj = render( boundActions, newState.settings.previewTypesEnabled );
settingsObj.appendTo( document.body );
}

View file

@ -2,8 +2,6 @@
* @module changeListeners/syncUserSettings
*/
import { previewTypes } from '../preview/model';
/**
* Creates an instance of the user settings sync change listener.
*
@ -22,14 +20,14 @@ import { previewTypes } from '../preview/model';
*/
export default function syncUserSettings( userSettings ) {
return ( oldState, newState ) => {
syncIfChanged(
oldState, newState, 'preview.enabled.' + previewTypes.TYPE_PAGE,
userSettings.storePagePreviewsEnabled
);
syncIfChanged(
oldState, newState, 'preview.enabled.' + previewTypes.TYPE_REFERENCE,
userSettings.storeReferencePreviewsEnabled
);
Object.keys( newState.preview.enabled ).forEach( ( key ) => {
syncIfChanged(
oldState, newState, `preview.enabled.${key}`,
( value ) => {
userSettings.storePreviewTypeEnabled( key, value );
}
);
} );
};
}

View file

@ -191,15 +191,11 @@ function handleDOMEventIfEligible( handler ) {
referenceGateway = createReferenceGateway(),
userSettings = createUserSettings( mw.storage ),
referencePreviewsState = isReferencePreviewsEnabled( mw.user, userSettings, mw.config ),
settingsDialog = createSettingsDialogRenderer( referencePreviewsState !== null ),
settingsDialog = createSettingsDialogRenderer(),
experiments = createExperiments( mw.experiments ),
statsvTracker = getStatsvTracker( mw.user, mw.config, experiments ),
pageviewTracker = getPageviewTracker( mw.config ),
initiallyEnabled = {
[ previewTypes.TYPE_PAGE ]:
createIsPagePreviewsEnabled( mw.user, userSettings, mw.config ),
[ previewTypes.TYPE_REFERENCE ]: referencePreviewsState
};
pagePreviewState = createIsPagePreviewsEnabled( mw.user, userSettings, mw.config );
// If debug mode is enabled, then enable Redux DevTools.
if ( mw.config.get( 'debug' ) ||
@ -224,7 +220,7 @@ function handleDOMEventIfEligible( handler ) {
);
boundActions.boot(
initiallyEnabled,
{},
mw.user,
userSettings,
mw.config,
@ -236,10 +232,15 @@ function handleDOMEventIfEligible( handler ) {
* extensions can query it (T171287)
*/
mw.popups = createMediaWikiPopupsObject(
store, registerModel, registerPreviewUI, registerGatewayForPreviewType
store, registerModel, registerPreviewUI, registerGatewayForPreviewType,
boundActions.registerSetting, userSettings
);
if ( initiallyEnabled[ previewTypes.TYPE_PAGE ] !== null ) {
// Migrate any old preferences to new system.
// FIXME: This can be removed in 4 weeks time.
userSettings.migrateOldPreferences();
if ( pagePreviewState !== null ) {
const excludedLinksSelector = EXCLUDED_LINK_SELECTORS.join( ', ' );
// Register default preview type
mw.popups.register( {
@ -257,7 +258,7 @@ function handleDOMEventIfEligible( handler ) {
]
} );
}
if ( initiallyEnabled[ previewTypes.TYPE_REFERENCE ] !== null ) {
if ( referencePreviewsState !== null ) {
// Register the reference preview type
mw.popups.register( {
type: previewTypes.TYPE_REFERENCE,

View file

@ -4,6 +4,14 @@
import { previewTypes } from '../preview/model';
/**
* @param {string} type
* @return {boolean} whether the preview type supports being disabled/enabled.
*/
function canShowSettingForPreviewType( type ) {
return mw.message( `popups-settings-option-${type}` ).exists();
}
/**
* This function provides a mw.popups object which can be used by 3rd party
* to interact with Popups.
@ -12,9 +20,13 @@ import { previewTypes } from '../preview/model';
* @param {Function} registerModel allows extensions to register custom preview handlers.
* @param {Function} registerPreviewUI allows extensions to register custom preview renderers.
* @param {Function} registerGatewayForPreviewType allows extensions to register gateways for preview types.
* @param {Function} registerSetting
* @param {UserSettings} userSettings
* @return {Object} external Popups interface
*/
export default function createMwPopups( store, registerModel, registerPreviewUI, registerGatewayForPreviewType ) {
export default function createMwPopups( store, registerModel, registerPreviewUI,
registerGatewayForPreviewType, registerSetting, userSettings
) {
return {
/**
* @return {boolean} If Page Previews are currently active
@ -69,6 +81,15 @@ export default function createMwPopups( store, registerModel, registerPreviewUI,
registerModel( type, selector, delay );
registerGatewayForPreviewType( type, gateway );
registerPreviewUI( type, renderFn, doNotRequireSummary );
// Only show if doesn't exist.
if ( canShowSettingForPreviewType( type ) ) {
registerSetting( type, userSettings.isPreviewTypeEnabled( type ) );
} else {
mw.log.warn(
`[Popups] No setting for ${type} registered.
Please create message with key "popups-settings-option-${type}" if this is a mistake.`
);
}
if ( subTypes ) {
subTypes.forEach( function ( subTypePreview ) {
registerPreviewUI( subTypePreview.type, subTypePreview.renderFn, subTypePreview.doNotRequireSummary );

View file

@ -1,6 +1,7 @@
/**
* @module isPagePreviewsEnabled
*/
import { previewTypes } from './preview/model';
const canSaveToUserPreferences = require( './canSaveToUserPreferences.js' );
/**
@ -28,7 +29,7 @@ export default function isPagePreviewsEnabled( user, userSettings, config ) {
// For anonymous users, and for IP masked usersm the code loads always,
// but the feature can be toggled at run-time via local storage.
if ( !canSaveToUserPreferences( user ) ) {
return userSettings.isPagePreviewsEnabled();
return userSettings.isPreviewTypeEnabled( previewTypes.TYPE_PAGE );
}
// Registered users never can enable popup types at run-time.

View file

@ -1,3 +1,5 @@
import { previewTypes } from './preview/model';
/**
* @module isReferencePreviewsEnabled
*/
@ -32,7 +34,7 @@ export default function isReferencePreviewsEnabled( user, userSettings, config )
// For anonymous users, the code loads always, but the feature can be toggled at run-time via
// local storage.
if ( !canSaveToUserPreferences( user ) ) {
return userSettings.isReferencePreviewsEnabled();
return userSettings.isPreviewTypeEnabled( previewTypes.TYPE_REFERENCE );
}
// Registered users never can enable popup types at run-time.

View file

@ -28,7 +28,12 @@ export default function preview( state, action ) {
return nextState( state, {
enabled: action.initiallyEnabled
} );
case actionTypes.REGISTER_SETTING:
return nextState( state, {
enabled: Object.assign( {}, state.enabled, {
[ action.name ]: action.enabled
} )
} );
case actionTypes.SETTINGS_CHANGE: {
return nextState( state, {
enabled: action.newValue

View file

@ -12,6 +12,7 @@ export default function settings( state, action ) {
if ( state === undefined ) {
state = {
shouldShow: false,
previewTypesEnabled: {},
showHelp: false,
shouldShowFooterLink: false
};
@ -57,12 +58,23 @@ export default function settings( state, action ) {
shouldShowFooterLink: anyDisabled
} );
}
case actionTypes.REGISTER_SETTING: {
const previewTypesEnabled = Object.assign( {}, state.previewTypesEnabled, {
[ action.name ]: action.enabled
} );
return nextState( state, {
previewTypesEnabled,
shouldShowFooterLink: state.shouldShowFooterLink || !action.enabled
} );
}
case actionTypes.BOOT: {
// Warning, when the state is null the user can't re-enable this popup type!
const anyDisabled = Object.keys( action.initiallyEnabled )
.some( ( type ) => action.initiallyEnabled[ type ] === false );
const previewTypesEnabled = Object.assign( {}, action.initiallyEnabled );
return nextState( state, {
previewTypesEnabled,
shouldShowFooterLink: action.user.isAnon && anyDisabled
} );
}

View file

@ -3,33 +3,28 @@
*/
import { renderSettingsDialog } from './templates/settingsDialog/settingsDialog';
import { previewTypes } from '../preview/model';
/**
* Create the settings dialog shown to anonymous users.
*
* @param {boolean} referencePreviewsAvaliable
* @param {Object} previewTypesEnabled
* @return {HTMLElement} settings dialog
*/
export function createSettingsDialog( referencePreviewsAvaliable ) {
const choices = [
export function createSettingsDialog( previewTypesEnabled ) {
const choices = Object.keys( previewTypesEnabled ).map( ( id ) => (
{
id: previewTypes.TYPE_PAGE,
name: mw.msg( 'popups-settings-option-page' ),
description: mw.msg( 'popups-settings-option-page-description' )
},
{
id: previewTypes.TYPE_REFERENCE,
name: mw.msg( 'popups-settings-option-reference' ),
description: mw.msg( 'popups-settings-option-reference-description' )
id,
// This can produce:
// * popups-settings-option-preview
// * popups-settings-option-reference
name: mw.msg( `popups-settings-option-${id}` ),
// This can produce:
// * popups-settings-option-preview-description
// * popups-settings-option-reference-description
description: mw.msg( `popups-settings-option-${id}-description` ),
isChecked: previewTypesEnabled[ id ]
}
];
if ( !referencePreviewsAvaliable ) {
// Anonymous users can't access reference previews when they're disabled
// TODO: Remove when the wgPopupsReferencePreviews feature flag is not needed any more
choices.splice( 1, 1 );
}
) );
return renderSettingsDialog( {
heading: mw.msg( 'popups-settings-title' ),

View file

@ -4,14 +4,34 @@
import { createSettingsDialog } from './settingsDialog';
const initDialog = ( boundActions, previewTypesEnabled ) => {
const dialog = createSettingsDialog( previewTypesEnabled );
// Setup event bindings
dialog.querySelector( '.save' ).addEventListener( 'click', () => {
boundActions.saveSettings(
Array.from( dialog.querySelectorAll( 'input' ) ).reduce(
( enabled, el ) => {
enabled[ el.value ] = el.matches( ':checked' );
return enabled;
},
{}
)
);
} );
dialog.querySelector( '.okay' ).addEventListener( 'click', boundActions.hideSettings );
dialog.querySelector( '.close' ).addEventListener( 'click', boundActions.hideSettings );
return dialog;
};
/**
* Creates a render function that will create the settings dialog and return
* a set of methods to operate on it
*
* @param {boolean} referencePreviewsAvaliable
* @return {Function} render function
*/
export default function createSettingsDialogRenderer( referencePreviewsAvaliable ) {
export default function createSettingsDialogRenderer() {
/**
* Cached settings dialog
*
@ -29,28 +49,30 @@ export default function createSettingsDialogRenderer( referencePreviewsAvaliable
* Renders the relevant form and labels in the settings dialog
*
* @param {Object} boundActions
* @param {Object} previewTypesEnabled
* @return {Object} object with methods to affect the rendered UI
*/
return ( boundActions ) => {
return ( boundActions, previewTypesEnabled ) => {
if ( !dialog ) {
dialog = createSettingsDialog( referencePreviewsAvaliable );
overlay = document.createElement( 'div' );
overlay.classList.add( 'mwe-popups-overlay' );
// Setup event bindings
dialog.querySelector( '.save' ).addEventListener( 'click', () => {
const enabled = {};
Array.prototype.forEach.call( dialog.querySelectorAll( 'input' ), ( el ) => {
enabled[ el.value ] = el.matches( ':checked' );
} );
boundActions.saveSettings( enabled );
} );
dialog.querySelector( '.close' ).addEventListener( 'click', boundActions.hideSettings );
dialog.querySelector( '.okay' ).addEventListener( 'click', boundActions.hideSettings );
dialog = initDialog( boundActions, previewTypesEnabled );
}
return {
/**
* Re-initialize the dialog when the available settings have changed.
*
* @param {Object} previewTypesEnabledNew updated key value pairs
*/
refresh( previewTypesEnabledNew ) {
const parent = dialog.parentNode;
dialog.remove();
dialog = initDialog( boundActions, previewTypesEnabledNew );
if ( parent ) {
dialog.appendTo( parent );
}
},
/**
* Append the dialog and overlay to a DOM element
*

View file

@ -1,3 +1,5 @@
import { previewTypes } from './preview/model';
/**
* @module userSettings
*/
@ -22,61 +24,51 @@ const PAGE_PREVIEWS_ENABLED_KEY = 'mwe-popups-enabled',
*/
export default function createUserSettings( storage ) {
return {
/**
* Gets whether the user has previously enabled Page Previews.
*
* N.B. that if the user hasn't previously enabled or disabled Page
* Previews, i.e. userSettings.storePagePreviewsEnabled(true), then they are treated as
* if they have enabled them.
*
* @method
* @name UserSettings#isPagePreviewsEnabled
* @return {boolean}
*/
isPagePreviewsEnabled() {
return storage.get( PAGE_PREVIEWS_ENABLED_KEY ) !== '0';
},
/**
* Permanently persists (typically in localStorage) whether the user has enabled Page
* Previews.
*
* @method
* @name UserSettings#storePagePreviewsEnabled
* @param {boolean} enabled
*/
storePagePreviewsEnabled( enabled ) {
if ( enabled ) {
migrateOldPreferences() {
const isDisabled = !!storage.get( PAGE_PREVIEWS_ENABLED_KEY );
if ( isDisabled ) {
storage.remove( PAGE_PREVIEWS_ENABLED_KEY );
} else {
storage.set( PAGE_PREVIEWS_ENABLED_KEY, '0' );
this.storePreviewTypeEnabled( previewTypes.TYPE_PAGE, false );
}
const isRefsDisabled = !!storage.get( REFERENCE_PREVIEWS_ENABLED_KEY );
if ( isRefsDisabled ) {
storage.remove( REFERENCE_PREVIEWS_ENABLED_KEY );
this.storePreviewTypeEnabled( previewTypes.TYPE_REFERENCE, false );
}
},
/**
* Check whether the preview type is enabled.
*
* @method
* @name UserSettings#isReferencePreviewsEnabled
* @return {boolean}
* @param {string} previewType
*/
isReferencePreviewsEnabled() {
return storage.get( REFERENCE_PREVIEWS_ENABLED_KEY ) !== '0';
isPreviewTypeEnabled( previewType ) {
const storageKey = `mwe-popups-${previewType}-enabled`;
const value = storage.get( storageKey );
return value === null;
},
/**
* Permanently persists (typically in localStorage) whether the user has enabled
* the preview type.
*
* @method
* @name UserSettings#storeReferencePreviewsEnabled
* @name UserSettings#storePreviewTypeEnabled
* @param {string} previewType
* @param {boolean} enabled
*/
storeReferencePreviewsEnabled( enabled ) {
if ( enabled ) {
storage.remove( REFERENCE_PREVIEWS_ENABLED_KEY );
} else {
storage.set( REFERENCE_PREVIEWS_ENABLED_KEY, '0' );
storePreviewTypeEnabled( previewType, enabled ) {
if ( previewType === previewTypes.TYPE_REFERENCE ) {
mw.track( REFERENCE_PREVIEWS_LOGGING_SCHEMA, {
action: enabled ? 'anonymousEnabled' : 'anonymousDisabled'
} );
}
const storageKey = `mwe-popups-${previewType}-enabled`;
if ( enabled ) {
storage.remove( storageKey );
} else {
storage.set( storageKey, '0' );
}
mw.track( REFERENCE_PREVIEWS_LOGGING_SCHEMA, {
action: enabled ? 'anonymousEnabled' : 'anonymousDisabled'
} );
}
};
}

View file

@ -60,6 +60,22 @@ QUnit.test( '#boot', ( assert ) => {
);
} );
QUnit.test( '#registerSetting', ( assert ) => {
const action = actions.registerSetting(
'foo',
false
);
assert.deepEqual(
action,
{
type: actionTypes.REGISTER_SETTING,
name: 'foo',
enabled: false
},
'Setting action'
);
} );
/**
* Stubs `wait.js` and adds the deferred and its promise as properties
* of the module.

View file

@ -10,21 +10,24 @@ QUnit.module( 'ext.popups/changeListeners/settings', {
toggleHelp: this.sandbox.spy(),
setEnabled: this.sandbox.spy()
};
const previewTypesEnabled = {};
this.render.withArgs( 'actions' ).returns( this.rendered );
this.defaultState = { settings: { shouldShow: false } };
this.defaultState = { settings: { shouldShow: false, previewTypesEnabled } };
this.showState = {
settings: { shouldShow: true },
settings: { shouldShow: true, previewTypesEnabled },
preview: { enabled: { page: true, reference: true } }
};
this.showHelpState = {
settings: {
previewTypesEnabled,
shouldShow: true,
showHelp: true
}
};
this.hideHelpState = {
settings: {
previewTypesEnabled,
shouldShow: true,
showHelp: false
}

View file

@ -3,8 +3,7 @@ import syncUserSettings from '../../../src/changeListeners/syncUserSettings';
QUnit.module( 'ext.popups/changeListeners/syncUserSettings', {
beforeEach() {
this.userSettings = {
storePagePreviewsEnabled: this.sandbox.spy(),
storeReferencePreviewsEnabled: this.sandbox.spy()
storePreviewTypeEnabled: this.sandbox.spy()
};
this.changeListener = syncUserSettings( this.userSettings );
@ -21,7 +20,7 @@ QUnit.test(
this.changeListener( oldState, newState );
assert.false(
this.userSettings.storePagePreviewsEnabled.called,
this.userSettings.storePreviewTypeEnabled.called,
'The user setting is unchanged.'
);
}
@ -34,7 +33,7 @@ QUnit.test( 'it should update the storage if the enabled flag has changed', func
this.changeListener( oldState, newState );
assert.true(
this.userSettings.storePagePreviewsEnabled.calledWith( false ),
this.userSettings.storePreviewTypeEnabled.calledWith( 'page', false ),
'The user setting is disabled.'
);
} );
@ -49,7 +48,7 @@ QUnit.test(
this.changeListener( oldState, newState );
assert.false(
this.userSettings.storeReferencePreviewsEnabled.called,
this.userSettings.storePreviewTypeEnabled.called,
'Reference previews are unchanged.'
);
}
@ -61,12 +60,8 @@ QUnit.test( 'it should update the storage if the reference preview state has cha
this.changeListener( oldState, newState );
assert.false(
this.userSettings.storePagePreviewsEnabled.called,
'Page previews are unchanged.'
);
assert.true(
this.userSettings.storeReferencePreviewsEnabled.calledWith( false ),
this.userSettings.storePreviewTypeEnabled.calledWith( 'reference', false ),
'Reference previews opt-out is stored.'
);
} );

View file

@ -3,7 +3,7 @@ import isPagePreviewsEnabled from '../../src/isPagePreviewsEnabled';
function createStubUserSettings( expectEnabled ) {
return {
isPagePreviewsEnabled() {
isPreviewTypeEnabled() {
return expectEnabled !== false;
}
};

View file

@ -3,7 +3,7 @@ import isReferencePreviewsEnabled from '../../src/isReferencePreviewsEnabled';
function createStubUserSettings( expectEnabled ) {
return {
isReferencePreviewsEnabled() {
isPreviewTypeEnabled() {
return expectEnabled !== false;
}
};
@ -128,7 +128,7 @@ QUnit.test( 'all relevant combinations of flags', ( assert ) => {
isAnon: () => data.isAnon
},
userSettings = {
isReferencePreviewsEnabled: () => data.isAnon ?
isPreviewTypeEnabled: () => data.isAnon ?
data.enabledByAnon :
assert.true( false, 'not expected to be called' )
},

View file

@ -10,6 +10,7 @@ QUnit.test( '@@INIT', ( assert ) => {
state,
{
shouldShow: false,
previewTypesEnabled: {},
showHelp: false,
shouldShowFooterLink: false
},
@ -24,15 +25,15 @@ QUnit.test( 'BOOT with a single disabled popup type', ( assert ) => {
user: { isAnon: true }
};
assert.deepEqual(
settings( {}, action ),
{ shouldShowFooterLink: true },
settings( {}, action ).shouldShowFooterLink,
true,
'The boot state shows a footer link.'
);
action.user.isAnon = false;
assert.deepEqual(
settings( {}, action ),
{ shouldShowFooterLink: false },
settings( {}, action ).shouldShowFooterLink,
false,
'If the user is logged in, then it doesn\'t signal that the footer link should be shown.'
);
} );
@ -44,26 +45,62 @@ QUnit.test( 'BOOT with multiple popup types', ( assert ) => {
user: { isAnon: true }
};
assert.deepEqual(
settings( {}, action ),
{ shouldShowFooterLink: false },
settings( {}, action ).shouldShowFooterLink,
false,
'Footer link ignores unavailable popup types.'
);
action.initiallyEnabled.reference = true;
assert.deepEqual(
settings( {}, action ),
{ shouldShowFooterLink: false },
settings( {}, action ).shouldShowFooterLink,
false,
'Footer link is pointless when there is nothing to enable.'
);
action.initiallyEnabled.reference = false;
assert.deepEqual(
settings( {}, action ),
{ shouldShowFooterLink: true },
settings( {}, action ).shouldShowFooterLink,
true,
'Footer link appears when at least one popup type is disabled.'
);
} );
QUnit.test( 'REGISTER_SETTING that is disabled by default reveals footer link', ( assert ) => {
const REGISTER_SETTING_FOO_DISABLED = {
type: actionTypes.REGISTER_SETTING,
name: 'foo',
enabled: false
};
const newState = settings( {
previewTypesEnabled: {},
shouldShowFooterLink: false
}, REGISTER_SETTING_FOO_DISABLED );
assert.deepEqual(
newState.shouldShowFooterLink,
true,
'if one setting is registered as disabled, then the footer link is revealed.'
);
} );
QUnit.test( 'REGISTER_SETTING that is enabled by default should not show footer link', ( assert ) => {
const REGISTER_SETTING_FOO_ENABLED = {
type: actionTypes.REGISTER_SETTING,
name: 'foo',
enabled: true
};
const newState = settings( {
previewTypesEnabled: {},
shouldShowFooterLink: false
}, REGISTER_SETTING_FOO_ENABLED );
assert.deepEqual(
newState.previewTypesEnabled.foo,
true,
'previewTypesEnabled is updated'
);
} );
QUnit.test( 'SETTINGS_SHOW', ( assert ) => {
assert.deepEqual(
settings( {}, { type: actionTypes.SETTINGS_SHOW } ),

View file

@ -43,13 +43,14 @@ QUnit.test( '#render', ( assert ) => {
hideSettings() {}
},
expected = {
refresh() {},
appendTo() {},
show() {},
hide() {},
toggleHelp() {},
setEnabled() {}
},
result = createSettingsDialogRenderer( mw.config )( boundActions );
result = createSettingsDialogRenderer( mw.config )( boundActions, {} );
// Specifically NOT a deep equal. Only structure.
assert.propEqual(

View file

@ -9,43 +9,19 @@ QUnit.module( 'ext.popups/userSettings', {
} );
QUnit.test( '#isPagePreviewsEnabled should return false if Page Previews have been disabled', function ( assert ) {
this.userSettings.storePagePreviewsEnabled( false );
this.userSettings.storePreviewTypeEnabled( 'page', false );
assert.false(
this.userSettings.isPagePreviewsEnabled(),
this.userSettings.isPreviewTypeEnabled( 'page' ),
'The user has disabled Page Previews.'
);
// ---
this.userSettings.storePagePreviewsEnabled( true );
this.userSettings.storePreviewTypeEnabled( 'page', true );
assert.true(
this.userSettings.isPagePreviewsEnabled(),
this.userSettings.isPreviewTypeEnabled( 'page' ),
'#isPagePreviewsEnabled should return true if Page Previews have been enabled'
);
} );
QUnit.test( '#isReferencePreviewsEnabled', function ( assert ) {
assert.strictEqual(
this.storage.get( 'mwe-popups-referencePreviews-enabled' ),
null,
'Precondition: storage is empty.'
);
assert.true(
this.userSettings.isReferencePreviewsEnabled(),
'#isReferencePreviewsEnabled should default to true.'
);
this.userSettings.storeReferencePreviewsEnabled( false );
assert.strictEqual(
this.storage.get( 'mwe-popups-referencePreviews-enabled' ),
'0',
'#storeReferencePreviewsEnabled changes the storage.'
);
assert.false(
this.userSettings.isReferencePreviewsEnabled(),
'#isReferencePreviewsEnabled is now false.'
);
} );

View file

@ -119,8 +119,8 @@ module.exports = ( env, argv ) => ( {
// Minified uncompressed size limits for chunks / assets and entrypoints. Keep these numbers
// up-to-date and rounded to the nearest 10th of a kibibyte so that code sizing costs are
// well understood. Related to bundlesize minified, gzipped compressed file size tests.
maxAssetSize: 46.8 * 1024,
maxEntrypointSize: 46.8 * 1024,
maxAssetSize: 47.8 * 1024,
maxEntrypointSize: 47.8 * 1024,
// The default filter excludes map files but we rename ours.
assetFilter: ( filename ) => !filename.endsWith( srcMapExt )