jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/325287 )
Change subject: Store/update user's preview count ...................................................................... Store/update user's preview count Action changes: * Add the PREVIEW_SHOW action. Reducer changes: * Increment the user's preview count in the eventLogging reducer. Changes: * Dispatch the PREVIEW_SHOW action when the preview has been shown. * Add the previewCount change listener, which is responsible for persisting the user's preview count to storage when it changes. * Call the change listener factories individually in #registerChangeListeners as their signatures aren't consistent. Bug: T152225 Change-Id: Ifb493c5bff66712a25614ebb905251e43375420a --- M extension.json M resources/ext.popups/actions.js M resources/ext.popups/boot.js A resources/ext.popups/previewCountChangeListener.js M resources/ext.popups/reducers.js M resources/ext.popups/renderChangeListener.js A tests/qunit/ext.popups/previewCountChangeListener.test.js M tests/qunit/ext.popups/reducers.eventLogging.test.js M tests/qunit/ext.popups/reducers.test.js A tests/qunit/ext.popups/renderChangeListener.test.js 10 files changed, 204 insertions(+), 4 deletions(-) Approvals: Jhernandez: Looks good to me, approved jenkins-bot: Verified diff --git a/extension.json b/extension.json index 602d487..3dfaf95 100644 --- a/extension.json +++ b/extension.json @@ -73,6 +73,7 @@ "resources/ext.popups/renderChangeListener.js", "resources/ext.popups/schema.js", "resources/ext.popups/eventLoggingChangeListener.js", + "resources/ext.popups/previewCountChangeListener.js", "resources/ext.popups/boot.js" ], "templates": { diff --git a/resources/ext.popups/actions.js b/resources/ext.popups/actions.js index 0cf7d7b..2afa447 100644 --- a/resources/ext.popups/actions.js +++ b/resources/ext.popups/actions.js @@ -15,6 +15,7 @@ PREVIEW_ABANDON_END: 'PREVIEW_ABANDON_END', PREVIEW_ANIMATING: 'PREVIEW_ANIMATING', PREVIEW_INTERACTIVE: 'PREVIEW_INTERACTIVE', + PREVIEW_SHOW: 'PREVIEW_SHOW', PREVIEW_CLICK: 'PREVIEW_CLICK', COG_CLICK: 'COG_CLICK', SETTINGS_DIALOG_RENDERED: 'SETTINGS_DIALOG_RENDERED', @@ -175,7 +176,7 @@ }; /** - * Represents the user dwelling on a preivew with their mouse. + * Represents the user dwelling on a preview with their mouse. * * @return {Object} */ @@ -207,6 +208,20 @@ }; /** + * Represents a preview being shown to the user. + * + * This action is dispatched by the `mw.popups.changeListeners.render` change + * listener. + * + * @return {Object} + */ + actions.previewShow = function () { + return { + type: types.PREVIEW_SHOW + }; + }; + + /** * Represents the user clicking either the "Enable previews" footer menu link, * or the "cog" icon that's present on each preview. * diff --git a/resources/ext.popups/boot.js b/resources/ext.popups/boot.js index 0cf655f..895b463 100644 --- a/resources/ext.popups/boot.js +++ b/resources/ext.popups/boot.js @@ -30,8 +30,9 @@ * @param {Redux.Store} store * @param {Object} actions * @param {mw.eventLog.Schema} schema + * @param {ext.popups.UserSettings} userSettings */ - function registerChangeListeners( store, actions, schema ) { + function registerChangeListeners( store, actions, schema, userSettings ) { // Sugar. var changeListeners = mw.popups.changeListeners, @@ -41,6 +42,7 @@ registerChangeListener( store, changeListeners.linkTitle() ); registerChangeListener( store, changeListeners.render( actions ) ); registerChangeListener( store, changeListeners.eventLogging( actions, schema ) ); + registerChangeListener( store, changeListeners.previewCount( userSettings ) ); } /** @@ -102,7 +104,7 @@ ) ) ); actions = createBoundActions( store ); - registerChangeListeners( store, actions, schema ); + registerChangeListeners( store, actions, schema, userSettings ); actions.boot( isUserInCondition, diff --git a/resources/ext.popups/previewCountChangeListener.js b/resources/ext.popups/previewCountChangeListener.js new file mode 100644 index 0000000..56849d9 --- /dev/null +++ b/resources/ext.popups/previewCountChangeListener.js @@ -0,0 +1,38 @@ +( function ( mw ) { + + /** + * Creates an instance of the preview count change listener. + * + * When the user dwells on a link for long enough that a preview is shown, + * then their preview count will be incremented (see + * `mw.popups.reducers.eventLogging`, and is persisted to local storage. + * + * @return {ext.popups.ChangeListener} + */ + mw.popups.changeListeners.previewCount = function ( userSettings ) { + + /** + * FIXME: This kind of function, one that selects the specific part(s) of + * the state tree that a change listener will use, is a common pattern and + * should be extracted. + * + * @param {Object} state + * @return {Number} + */ + function getPreviewCount( state ) { + return state.eventLogging.previewCount; + } + + return function ( prevState, state ) { + var previewCount = getPreviewCount( state ); + + if ( + prevState && + previewCount > getPreviewCount( prevState ) + ) { + userSettings.setPreviewCount( previewCount ); + } + }; + }; + +}( mediaWiki ) ); diff --git a/resources/ext.popups/reducers.js b/resources/ext.popups/reducers.js index 6fe340d..7fae9c1 100644 --- a/resources/ext.popups/reducers.js +++ b/resources/ext.popups/reducers.js @@ -145,8 +145,11 @@ * @return {Object} The state as a result of processing the action */ mw.popups.reducers.eventLogging = function ( state, action ) { + var nextCount; + if ( state === undefined ) { state = { + previewCount: undefined, baseData: {}, event: undefined }; @@ -177,6 +180,16 @@ event: undefined } ); + case mw.popups.actionTypes.PREVIEW_SHOW: + nextCount = state.previewCount + 1; + + return nextState( state, { + previewCount: nextCount, + baseData: nextState( state.baseData, { + previewCountBucket: counts.getPreviewCountBucket( nextCount ) + } ) + } ); + default: return state; } diff --git a/resources/ext.popups/renderChangeListener.js b/resources/ext.popups/renderChangeListener.js index 99fd821..99c9ccb 100644 --- a/resources/ext.popups/renderChangeListener.js +++ b/resources/ext.popups/renderChangeListener.js @@ -12,7 +12,8 @@ return function ( prevState, state ) { if ( state.preview.shouldShow && !preview ) { preview = mw.popups.renderer.render( state.preview.fetchResponse ); - preview.show( state.preview.activeEvent, boundActions ); + preview.show( state.preview.activeEvent, boundActions ) + .done( boundActions.previewShow ); } else if ( !state.preview.shouldShow && preview ) { preview.hide() .done( function () { diff --git a/tests/qunit/ext.popups/previewCountChangeListener.test.js b/tests/qunit/ext.popups/previewCountChangeListener.test.js new file mode 100644 index 0000000..4972327 --- /dev/null +++ b/tests/qunit/ext.popups/previewCountChangeListener.test.js @@ -0,0 +1,59 @@ +( function ( mw, $ ) { + + QUnit.module( 'ext.popups/previewCountChangeListener', { + setup: function () { + this.userSettings = { + setPreviewCount: this.sandbox.spy() + }; + + this.changeListener = mw.popups.changeListeners.previewCount( this.userSettings ); + } + } ); + + QUnit.test( + 'it shouldn\'t update the storage if the preview count hasn\'t changed', + function ( assert ) { + var state, + prevState; + + assert.expect( 1 ); + + state = { + eventLogging: { + previewCount: 222 + } + }; + + this.changeListener( undefined, state ); + + // --- + + prevState = $.extend( true, {}, state ); + + this.changeListener( prevState, state ); + + assert.notOk( this.userSettings.setPreviewCount.called ); + } + ); + + QUnit.test( 'it should update the storage', function ( assert ) { + var prevState, + state; + + assert.expect( 1 ); + + prevState = { + eventLogging: { + previewCount: 222 + } + }; + + state = $.extend( true, {}, prevState ); + ++state.eventLogging.previewCount; + + this.changeListener( prevState, state ); + + assert.ok( this.userSettings.setPreviewCount.calledWith( 223 ) ); + } ); + +}( mediaWiki, jQuery ) ); diff --git a/tests/qunit/ext.popups/reducers.eventLogging.test.js b/tests/qunit/ext.popups/reducers.eventLogging.test.js index 52f37bb..6e2c176 100644 --- a/tests/qunit/ext.popups/reducers.eventLogging.test.js +++ b/tests/qunit/ext.popups/reducers.eventLogging.test.js @@ -76,4 +76,35 @@ ); } ); + QUnit.test( 'PREVIEW_SHOW', function ( assert ) { + var state, + count = 22, + action, + expectedCount = count + 1; + + state = { + previewCount: count, + baseData: { + previewCountBucket: counts.getPreviewCountBucket( count ) + }, + event: undefined + }; + + action = { + type: 'PREVIEW_SHOW' + }; + + assert.deepEqual( + mw.popups.reducers.eventLogging( state, action ), + { + previewCount: expectedCount, + baseData: { + previewCountBucket: counts.getPreviewCountBucket( expectedCount ) + }, + event: undefined + }, + 'It increments the user\'s preview count and re-buckets that count.' + ); + } ); + }( mediaWiki ) ); diff --git a/tests/qunit/ext.popups/reducers.test.js b/tests/qunit/ext.popups/reducers.test.js index 45ecd45..9751c2a 100644 --- a/tests/qunit/ext.popups/reducers.test.js +++ b/tests/qunit/ext.popups/reducers.test.js @@ -22,6 +22,7 @@ isUserDwelling: false }, eventLogging: { + previewCount: undefined, baseData: {}, event: undefined }, diff --git a/tests/qunit/ext.popups/renderChangeListener.test.js b/tests/qunit/ext.popups/renderChangeListener.test.js new file mode 100644 index 0000000..7b65dc7 --- /dev/null +++ b/tests/qunit/ext.popups/renderChangeListener.test.js @@ -0,0 +1,39 @@ +( function ( mw, $ ) { + + // Since mw.popups.changeListeners.render manipulates the DOM, this test is, + // by necessity, an integration test. + QUnit.module( 'ext.popups/renderChangeListener @integration' ); + + QUnit.test( + 'it should call the showPreview action creator when the preview is shown', + function ( assert ) { + var boundActions, + changeListener, + state; + + boundActions = { + previewShow: this.sandbox.spy() + }; + + this.sandbox.stub( mw.popups.renderer, 'render', function () { + return { + show: function () { + return $.Deferred().resolve(); + } + }; + } ); + + state = { + preview: { + shouldShow: true + } + }; + + changeListener = mw.popups.changeListeners.render( boundActions ); + changeListener( undefined, state ); + + assert.ok( boundActions.previewShow.called ); + } + ); + +}( mediaWiki, jQuery ) ); -- To view, visit https://gerrit.wikimedia.org/r/325287 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ifb493c5bff66712a25614ebb905251e43375420a Gerrit-PatchSet: 7 Gerrit-Project: mediawiki/extensions/Popups Gerrit-Branch: mpga Gerrit-Owner: Phuedx <samsm...@wikimedia.org> Gerrit-Reviewer: Jhernandez <jhernan...@wikimedia.org> Gerrit-Reviewer: Phuedx <samsm...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits