mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Popups
synced 2024-11-23 15:16:50 +00:00
Merge "Generalize settings code (attempt 2)"
This commit is contained in:
commit
93d9c88c26
|
@ -16,7 +16,7 @@ module.exports = {
|
|||
|
||||
// Set the coverage percentage by category thresholds.
|
||||
statements: 80,
|
||||
branches: 70,
|
||||
branches: 69,
|
||||
functions: 80,
|
||||
lines: 90,
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
"bundlesize": [
|
||||
{
|
||||
"path": "resources/dist/index.js",
|
||||
"maxSize": "14.8kB"
|
||||
"maxSize": "15.1kB"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
BIN
resources/dist/index.js
vendored
BIN
resources/dist/index.js
vendored
Binary file not shown.
BIN
resources/dist/index.js.map.json
vendored
BIN
resources/dist/index.js.map.json
vendored
Binary file not shown.
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
);
|
||||
} );
|
||||
};
|
||||
}
|
||||
|
||||
|
|
21
src/index.js
21
src/index.js
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -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' ),
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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'
|
||||
} );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.'
|
||||
);
|
||||
} );
|
||||
|
|
|
@ -3,7 +3,7 @@ import isPagePreviewsEnabled from '../../src/isPagePreviewsEnabled';
|
|||
|
||||
function createStubUserSettings( expectEnabled ) {
|
||||
return {
|
||||
isPagePreviewsEnabled() {
|
||||
isPreviewTypeEnabled() {
|
||||
return expectEnabled !== false;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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' )
|
||||
},
|
||||
|
|
|
@ -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 } ),
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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.'
|
||||
);
|
||||
} );
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in a new issue