mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Popups
synced 2024-11-27 17:00:37 +00:00
Limit line length to 80 characters
Enforce it with eslint. Ignore: * Comment lines with eslint disable directives * QUnit test lines as they contain long subjects (QUnit.* (only, test, module, skip, etc) * Strings, since long strings are used extensively in tests * Ignore template literals for similar reasons * Regex literals as they may be too long, but can't be easily split in several lines * Long urls See bug for more general proposal for eslint-wikimedia-config. Bug: T185295 Change-Id: I3aacaf46e61a4d96547c513073e179ef997deb09
This commit is contained in:
parent
64e81b0fee
commit
807100bcca
|
@ -19,6 +19,23 @@
|
|||
},
|
||||
"rules": {
|
||||
"dot-notation": [ "error", { "allowKeywords": true } ],
|
||||
"no-use-before-define": 0
|
||||
"no-use-before-define": 0,
|
||||
"max-len": [
|
||||
"warn",
|
||||
{
|
||||
"tabWidth": 2,
|
||||
// Note: exclude all eslint- directives except for max-len itself
|
||||
// since `// eslint-disable-line max-len` would cause this line to be
|
||||
// ignored AND this rule to be disabled which would trigger
|
||||
// --report-unused-disable-directives. By excluding max-len, the effect
|
||||
// is to consider the line but disable this rule.
|
||||
"ignorePattern": "^/// .+|// (?!eslint-.+max-len)eslint-.+|QUnit.",
|
||||
"ignoreUrls": true,
|
||||
"ignoreComments": false,
|
||||
"ignoreRegExpLiterals": true,
|
||||
"ignoreStrings": true,
|
||||
"ignoreTemplateLiterals": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
BIN
resources/dist/index.js.json
vendored
BIN
resources/dist/index.js.json
vendored
Binary file not shown.
|
@ -131,7 +131,10 @@ export function fetch( gateway, title, el, token ) {
|
|||
} );
|
||||
} );
|
||||
|
||||
return $.when( request, wait( FETCH_COMPLETE_TARGET_DELAY - FETCH_START_DELAY ) )
|
||||
return $.when(
|
||||
request,
|
||||
wait( FETCH_COMPLETE_TARGET_DELAY - FETCH_START_DELAY )
|
||||
)
|
||||
.then( function ( result ) {
|
||||
dispatch( {
|
||||
type: types.FETCH_COMPLETE,
|
||||
|
@ -141,15 +144,21 @@ export function fetch( gateway, title, el, token ) {
|
|||
} );
|
||||
} )
|
||||
.fail( function ( data, result ) {
|
||||
// All failures, except those due to being offline or network error, should present "There
|
||||
// was an issue displaying this preview". e.g.:
|
||||
// - Show (timeout): data="http" {xhr: {…}, textStatus: "timeout", exception: "timeout"}
|
||||
// All failures, except those due to being offline or network error,
|
||||
// should present "There was an issue displaying this preview".
|
||||
// e.g.:
|
||||
// - Show (timeout): data="http" {xhr: {…}, textStatus: "timeout",
|
||||
// exception: "timeout"}
|
||||
// - Show (bad MW request): data="unknown_action" {error: {…}}
|
||||
// - Show (RB 4xx): data="http" {xhr: {…}, textStatus: "error", exception: "Bad Request"}
|
||||
// - Show (RB 5xx): data="http" {xhr: {…}, textStatus: "error", exception: "Service Unavailable"}
|
||||
// - Suppress (offline or network error): data="http" result={xhr: {…}, textStatus: "error", exception: ""}
|
||||
var networkError = result && result.xhr && result.xhr.readyState === 0 &&
|
||||
result.textStatus === 'error' && result.exception === '';
|
||||
// - Show (RB 4xx): data="http" {xhr: {…}, textStatus: "error",
|
||||
// exception: "Bad Request"}
|
||||
// - Show (RB 5xx): data="http" {xhr: {…}, textStatus: "error",
|
||||
// exception: "Service Unavailable"}
|
||||
// - Suppress (offline or network error): data="http"
|
||||
// result={xhr: {…}, textStatus: "error", exception: ""}
|
||||
var networkError = result && result.xhr &&
|
||||
result.xhr.readyState === 0 && result.textStatus === 'error' &&
|
||||
result.exception === '';
|
||||
if ( !networkError ) {
|
||||
dispatch( {
|
||||
// Both FETCH_FAILED and FETCH_END conclude with FETCH_COMPLETE.
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
var $ = jQuery,
|
||||
// If bracketedDevicePixelRatio is not available default to 1 (in tests for
|
||||
// example)
|
||||
pixelRatio = $.bracketedDevicePixelRatio && $.bracketedDevicePixelRatio() || 1,
|
||||
pixelRatio = $.bracketedDevicePixelRatio &&
|
||||
$.bracketedDevicePixelRatio() || 1,
|
||||
BUCKETS = {
|
||||
off: 'off',
|
||||
on: 'on',
|
||||
|
|
|
@ -55,12 +55,16 @@ function makeTitleInExtractBold( extract, title ) {
|
|||
// Make title bold in the extract text
|
||||
// As the extract is html escaped there can be no such string in it
|
||||
// Also, the title is escaped of RegExp elements thus can't have "*"
|
||||
extract = extract.replace( regExp, '$1' + snip + boldIdentifier + '$2' + snip + '$3' );
|
||||
extract = extract.replace(
|
||||
regExp,
|
||||
'$1' + snip + boldIdentifier + '$2' + snip + '$3'
|
||||
);
|
||||
extract = extract.split( snip );
|
||||
|
||||
$.each( extract, function ( index, part ) {
|
||||
if ( part.indexOf( boldIdentifier ) === 0 ) {
|
||||
elements.push( $( '<b>' ).text( part.substring( boldIdentifier.length ) ) );
|
||||
elements.push( $( '<b>' )
|
||||
.text( part.substring( boldIdentifier.length ) ) );
|
||||
} else {
|
||||
elements.push( document.createTextNode( part ) );
|
||||
}
|
||||
|
|
|
@ -36,9 +36,11 @@ export default function createGateway( config ) {
|
|||
case 'mwApiPlain':
|
||||
return createMediaWikiApiGateway( new mw.Api(), constants );
|
||||
case 'restbasePlain':
|
||||
return createRESTBaseGateway( $.ajax, constants, formatters.parsePlainTextResponse );
|
||||
return createRESTBaseGateway(
|
||||
$.ajax, constants, formatters.parsePlainTextResponse );
|
||||
case 'restbaseHTML':
|
||||
return createRESTBaseGateway( $.ajax, constants, formatters.parseHTMLResponse );
|
||||
return createRESTBaseGateway(
|
||||
$.ajax, constants, formatters.parseHTMLResponse );
|
||||
default:
|
||||
throw new Error( 'Unknown gateway' );
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@ var RESTBASE_ENDPOINT = '/api/rest_v1/page/summary/',
|
|||
* @param {Function} ajax A function with the same signature as `jQuery.ajax`
|
||||
* @param {Object} config Configuration that affects the major behavior of the
|
||||
* gateway.
|
||||
* @param {Function} extractParser A function that takes response and returns parsed extract
|
||||
* @param {Function} extractParser A function that takes response and returns
|
||||
* parsed extract
|
||||
* @return {RESTBaseGateway}
|
||||
*/
|
||||
export default function createRESTBaseGateway( ajax, config, extractParser ) {
|
||||
|
@ -76,9 +77,14 @@ export default function createRESTBaseGateway( ajax, config, extractParser ) {
|
|||
createNullModel( title, new mw.Title( title ).getUrl() )
|
||||
);
|
||||
} else {
|
||||
// The client will choose how to handle these errors which may include those due to HTTP
|
||||
// 5xx status. The rejection typing matches Fetch failures.
|
||||
result.reject( 'http', { xhr: jqXHR, textStatus: textStatus, exception: errorThrown } );
|
||||
// The client will choose how to handle these errors which may
|
||||
// include those due to HTTP 5xx status. The rejection typing
|
||||
// matches Fetch failures.
|
||||
result.reject( 'http', {
|
||||
xhr: jqXHR,
|
||||
textStatus: textStatus,
|
||||
exception: errorThrown
|
||||
} );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -163,6 +169,9 @@ function convertPageToModel( page, thumbSize, extractParser ) {
|
|||
page.lang,
|
||||
page.dir,
|
||||
extractParser( page ),
|
||||
page.thumbnail ? generateThumbnailData( page.thumbnail, page.originalimage, thumbSize ) : undefined
|
||||
page.thumbnail ?
|
||||
generateThumbnailData(
|
||||
page.thumbnail, page.originalimage, thumbSize
|
||||
) : undefined
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
* What is the bucket for the given user given the enabled sampling rate?
|
||||
*
|
||||
* @param {mw.experiments} experiments The `mw.experiments` singleton instance
|
||||
* @param {Number} experimentGroupSize [0,1] of users of which should be subjected to an
|
||||
* A/B test. The remaining users will be put in the 'off' bucket.
|
||||
* @param {Number} experimentGroupSize [0,1] of users of which should be
|
||||
* subjected to an A/B test. The remaining users will be put in the 'off'
|
||||
* bucket.
|
||||
* @param {string} sessionId a unique session token
|
||||
*
|
||||
* @return {string} bucket that the user belongs to (off/control/on)
|
||||
|
|
31
src/index.js
31
src/index.js
|
@ -15,7 +15,8 @@ import { fromElement as titleFromElement } from './title';
|
|||
import { init as rendererInit } from './ui/renderer';
|
||||
import createExperiments from './experiments';
|
||||
import { isEnabled as isStatsvEnabled } from './instrumentation/statsv';
|
||||
import { isEnabled as isEventLoggingEnabled } from './instrumentation/eventLogging';
|
||||
import { isEnabled as isEventLoggingEnabled }
|
||||
from './instrumentation/eventLogging';
|
||||
import changeListeners from './changeListeners';
|
||||
import * as actions from './actions';
|
||||
import reducers from './reducers';
|
||||
|
@ -116,14 +117,24 @@ function getCurrentTimestamp() {
|
|||
* @param {EventTracker} eventLoggingTracker
|
||||
* @param {Function} getCurrentTimestamp
|
||||
*/
|
||||
function registerChangeListeners( store, actions, userSettings, settingsDialog, previewBehavior, statsvTracker, eventLoggingTracker, getCurrentTimestamp ) {
|
||||
function registerChangeListeners(
|
||||
store, actions, userSettings, settingsDialog, previewBehavior,
|
||||
statsvTracker, eventLoggingTracker, getCurrentTimestamp
|
||||
) {
|
||||
registerChangeListener( store, changeListeners.footerLink( actions ) );
|
||||
registerChangeListener( store, changeListeners.linkTitle() );
|
||||
registerChangeListener( store, changeListeners.render( previewBehavior ) );
|
||||
registerChangeListener( store, changeListeners.statsv( actions, statsvTracker ) );
|
||||
registerChangeListener( store, changeListeners.syncUserSettings( userSettings ) );
|
||||
registerChangeListener( store, changeListeners.settings( actions, settingsDialog ) );
|
||||
registerChangeListener( store, changeListeners.eventLogging( actions, eventLoggingTracker, getCurrentTimestamp ) );
|
||||
registerChangeListener(
|
||||
store, changeListeners.statsv( actions, statsvTracker ) );
|
||||
registerChangeListener(
|
||||
store, changeListeners.syncUserSettings( userSettings ) );
|
||||
registerChangeListener(
|
||||
store, changeListeners.settings( actions, settingsDialog ) );
|
||||
registerChangeListener(
|
||||
store,
|
||||
changeListeners.eventLogging(
|
||||
actions, eventLoggingTracker, getCurrentTimestamp
|
||||
) );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -153,7 +164,9 @@ mw.requestIdleCallback( function () {
|
|||
isEnabled,
|
||||
previewBehavior;
|
||||
|
||||
userBucket = getUserBucket( mw.experiments, mw.config.get( 'wgPopupsAnonsExperimentalGroupSize' ),
|
||||
userBucket = getUserBucket(
|
||||
mw.experiments,
|
||||
mw.config.get( 'wgPopupsAnonsExperimentalGroupSize' ),
|
||||
mw.user.sessionId() );
|
||||
userSettings = createUserSettings( mw.storage );
|
||||
settingsDialog = createSettingsDialogRenderer();
|
||||
|
@ -215,7 +228,9 @@ mw.requestIdleCallback( function () {
|
|||
var mwTitle = titleFromElement( this, mw.config );
|
||||
|
||||
if ( mwTitle ) {
|
||||
boundActions.linkDwell( mwTitle, this, event, gateway, generateToken );
|
||||
boundActions.linkDwell(
|
||||
mwTitle, this, event, gateway, generateToken
|
||||
);
|
||||
}
|
||||
} )
|
||||
.on( 'mouseout blur', validLinkSelector, function () {
|
||||
|
|
|
@ -8,9 +8,9 @@ import { BUCKETS } from './../constants';
|
|||
* session.
|
||||
* If wgPopupsEventLogging is false this will return false unless debug=true has
|
||||
* been enabled.
|
||||
* If an experiment is being run (ie. wgPopupsAnonsExperimentalGroupSize has been
|
||||
* defined) then event logging will only be enabled for those in the `on` or `control`
|
||||
* groups.
|
||||
* If an experiment is being run (ie. wgPopupsAnonsExperimentalGroupSize has
|
||||
* been defined) then event logging will only be enabled for those in the `on`
|
||||
* or `control` groups.
|
||||
* However, if the UA doesn't support [the Beacon API][1], then bucketing is
|
||||
* disabled.
|
||||
*
|
||||
|
|
|
@ -78,7 +78,8 @@ export function createNullModel( title, url ) {
|
|||
* returned.
|
||||
*
|
||||
* @param {Array|undefined|null} extract
|
||||
* @return {Array|undefined} Array when extract is an not empty array, undefined otherwise
|
||||
* @return {Array|undefined} Array when extract is an not empty array, undefined
|
||||
* otherwise
|
||||
*/
|
||||
function processExtract( extract ) {
|
||||
if ( extract === undefined || extract === null || extract.length === 0 ) {
|
||||
|
|
|
@ -21,12 +21,15 @@ function getBaseData( bootAction ) {
|
|||
popupEnabled: bootAction.isEnabled,
|
||||
pageToken: bootAction.pageToken,
|
||||
sessionToken: bootAction.sessionToken,
|
||||
previewCountBucket: counts.getPreviewCountBucket( bootAction.user.previewCount ),
|
||||
previewCountBucket: counts.getPreviewCountBucket(
|
||||
bootAction.user.previewCount
|
||||
),
|
||||
hovercardsSuppressedByGadget: bootAction.isNavPopupsEnabled
|
||||
};
|
||||
|
||||
if ( !bootAction.user.isAnon ) {
|
||||
result.editCountBucket = counts.getEditCountBucket( bootAction.user.editCount );
|
||||
result.editCountBucket =
|
||||
counts.getEditCountBucket( bootAction.user.editCount );
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -74,7 +77,8 @@ function createEvent( interaction, actionData ) {
|
|||
*/
|
||||
function createClosingEvent( interaction ) {
|
||||
var actionData = {
|
||||
totalInteractionTime: Math.round( interaction.finished - interaction.started )
|
||||
totalInteractionTime:
|
||||
Math.round( interaction.finished - interaction.started )
|
||||
};
|
||||
|
||||
if ( interaction.finalized ) {
|
||||
|
@ -84,7 +88,8 @@ function createClosingEvent( interaction ) {
|
|||
// Has the preview been shown? If so, then, in the context of the
|
||||
// instrumentation, then the preview has been dismissed by the user
|
||||
// rather than the user has abandoned the link.
|
||||
actionData.action = interaction.timeToPreviewShow ? 'dismissed' : 'dwelledButAbandoned';
|
||||
actionData.action =
|
||||
interaction.timeToPreviewShow ? 'dismissed' : 'dwelledButAbandoned';
|
||||
|
||||
return createEvent( interaction, actionData );
|
||||
}
|
||||
|
@ -206,7 +211,8 @@ export default function eventLogging( state, action ) {
|
|||
previewCountBucket: counts.getPreviewCountBucket( nextCount )
|
||||
} ),
|
||||
interaction: nextState( state.interaction, {
|
||||
timeToPreviewShow: Math.round( action.timestamp - state.interaction.started )
|
||||
timeToPreviewShow:
|
||||
Math.round( action.timestamp - state.interaction.started )
|
||||
} )
|
||||
} );
|
||||
|
||||
|
@ -237,7 +243,8 @@ export default function eventLogging( state, action ) {
|
|||
|
||||
// Was the user interacting with another link? If so, then log the
|
||||
// abandoned event.
|
||||
event: state.interaction ? createClosingEvent( state.interaction ) : undefined
|
||||
event: state.interaction ?
|
||||
createClosingEvent( state.interaction ) : undefined
|
||||
} );
|
||||
|
||||
case actionTypes.PREVIEW_DWELL:
|
||||
|
@ -254,7 +261,8 @@ export default function eventLogging( state, action ) {
|
|||
} ),
|
||||
event: createEvent( state.interaction, {
|
||||
action: 'opened',
|
||||
totalInteractionTime: Math.round( action.timestamp - state.interaction.started )
|
||||
totalInteractionTime:
|
||||
Math.round( action.timestamp - state.interaction.started )
|
||||
} )
|
||||
} );
|
||||
|
||||
|
|
|
@ -78,5 +78,8 @@ export function isValid( title, contentNamespaces ) {
|
|||
* @return {mw.Title|null}
|
||||
*/
|
||||
export function fromElement( el, config ) {
|
||||
return isValid( getTitle( el.href, config ), config.get( 'wgContentNamespaces' ) );
|
||||
return isValid(
|
||||
getTitle( el.href, config ),
|
||||
config.get( 'wgContentNamespaces' )
|
||||
);
|
||||
}
|
||||
|
|
|
@ -93,7 +93,8 @@ export function init() {
|
|||
*/
|
||||
export function render( model ) {
|
||||
// `undefined` is the default extract for null objects.
|
||||
var preview = model.extract === undefined ? createEmptyPreview( model ) : createPreview( model );
|
||||
var preview = model.extract === undefined ?
|
||||
createEmptyPreview( model ) : createPreview( model );
|
||||
|
||||
return {
|
||||
|
||||
|
@ -406,7 +407,9 @@ export function createThumbnail( rawThumbnail ) {
|
|||
* @param {String} clipPath
|
||||
* @return {jQuery}
|
||||
*/
|
||||
export function createThumbnailElement( className, url, x, y, thumbnailWidth, thumbnailHeight, width, height, clipPath ) {
|
||||
export function createThumbnailElement(
|
||||
className, url, x, y, thumbnailWidth, thumbnailHeight, width, height, clipPath
|
||||
) {
|
||||
var $thumbnailSVGImage, $thumbnail,
|
||||
nsSvg = 'http://www.w3.org/2000/svg',
|
||||
nsXlink = 'http://www.w3.org/1999/xlink';
|
||||
|
@ -449,12 +452,15 @@ export function createThumbnailElement( className, url, x, y, thumbnailWidth, th
|
|||
|
||||
/**
|
||||
* @param {isPreviewTall} isPreviewTall
|
||||
* @param {Object} eventData Data related to the event that triggered showing a popup
|
||||
* @param {Object} eventData Data related to the event that triggered showing
|
||||
* a popup
|
||||
* @param {number} eventData.pageX
|
||||
* @param {number} eventData.pageY
|
||||
* @param {number} eventData.clientY
|
||||
* @param {Object} linkData Data related to the link that’s used for showing a popup
|
||||
* @param {ClientRectList} linkData.clientRects list of rectangles defined by four edges
|
||||
* @param {Object} linkData Data related to the link that’s used for showing
|
||||
* a popup
|
||||
* @param {ClientRectList} linkData.clientRects list of rectangles defined by
|
||||
* four edges
|
||||
* @param {Object} linkData.offset
|
||||
* @param {number} linkData.width
|
||||
* @param {number} linkData.height
|
||||
|
@ -465,7 +471,9 @@ export function createThumbnailElement( className, url, x, y, thumbnailWidth, th
|
|||
* @param {number} pokeySize Space reserved for the pokey
|
||||
* @return {ext.popups.PreviewLayout}
|
||||
*/
|
||||
export function createLayout( isPreviewTall, eventData, linkData, windowData, pokeySize ) {
|
||||
export function createLayout(
|
||||
isPreviewTall, eventData, linkData, windowData, pokeySize
|
||||
) {
|
||||
var flippedX = false,
|
||||
flippedY = false,
|
||||
offsetTop = eventData.pageY ?
|
||||
|
@ -595,7 +603,9 @@ export function getClasses( preview, layout ) {
|
|||
* @param {number} predefinedLandscapeImageHeight landscape image height
|
||||
* @param {number} pokeySize
|
||||
*/
|
||||
export function layoutPreview( preview, layout, classes, predefinedLandscapeImageHeight, pokeySize ) {
|
||||
export function layoutPreview(
|
||||
preview, layout, classes, predefinedLandscapeImageHeight, pokeySize
|
||||
) {
|
||||
var popup = preview.el,
|
||||
isTall = preview.isTall,
|
||||
hasThumbnail = preview.hasThumbnail,
|
||||
|
|
|
@ -124,7 +124,8 @@ export default function createSettingsDialogRenderer() {
|
|||
*/
|
||||
function createSettingsDialog() {
|
||||
var $el,
|
||||
path = mw.config.get( 'wgExtensionAssetsPath' ) + '/Popups/resources/ext.popups/images/',
|
||||
path = mw.config.get( 'wgExtensionAssetsPath' ) +
|
||||
'/Popups/resources/ext.popups/images/',
|
||||
choices = [
|
||||
{
|
||||
id: 'simple',
|
||||
|
|
|
@ -65,8 +65,9 @@ export default function createUserSettings( storage ) {
|
|||
/**
|
||||
* Gets the number of previews that the user has seen.
|
||||
*
|
||||
* If the storage isn't available, then -1 is returned.
|
||||
* If the value in storage is not a number it will override stored value to 0
|
||||
* - If the storage isn't available, then -1 is returned.
|
||||
* - If the value in storage is not a number it will override stored value
|
||||
* to 0
|
||||
*
|
||||
* @function
|
||||
* @name UserSettings#getPreviewCount
|
||||
|
|
|
@ -126,7 +126,9 @@ QUnit.test( '#linkDwell', function ( assert ) {
|
|||
activeToken: generateToken()
|
||||
};
|
||||
|
||||
actions.linkDwell( this.title, this.el, event, /* gateway = */ null, generateToken )(
|
||||
actions.linkDwell(
|
||||
this.title, this.el, event, /* gateway = */ null, generateToken
|
||||
)(
|
||||
dispatch,
|
||||
this.getState
|
||||
);
|
||||
|
@ -175,7 +177,9 @@ QUnit.test( '#linkDwell doesn\'t continue when previews are disabled', function
|
|||
activeToken: generateToken()
|
||||
};
|
||||
|
||||
actions.linkDwell( this.title, this.el, event, /* gateway = */ null, generateToken )(
|
||||
actions.linkDwell(
|
||||
this.title, this.el, event, /* gateway = */ null, generateToken
|
||||
)(
|
||||
dispatch,
|
||||
this.getState
|
||||
);
|
||||
|
@ -203,7 +207,9 @@ QUnit.test( '#linkDwell doesn\'t continue if the token has changed', function (
|
|||
activeToken: generateToken()
|
||||
};
|
||||
|
||||
actions.linkDwell( this.title, this.el, event, /* gateway = */ null, generateToken )(
|
||||
actions.linkDwell(
|
||||
this.title, this.el, event, /* gateway = */ null, generateToken
|
||||
)(
|
||||
dispatch,
|
||||
this.getState
|
||||
);
|
||||
|
@ -239,7 +245,9 @@ QUnit.test( '#linkDwell dispatches the fetch action', function ( assert ) {
|
|||
activeToken: generateToken()
|
||||
};
|
||||
|
||||
actions.linkDwell( this.title, this.el, event, /* gateway = */ null, generateToken )(
|
||||
actions.linkDwell(
|
||||
this.title, this.el, event, /* gateway = */ null, generateToken
|
||||
)(
|
||||
dispatch,
|
||||
this.getState
|
||||
);
|
||||
|
@ -279,7 +287,9 @@ QUnit.module( 'ext.popups/actions#fetch', {
|
|||
|
||||
// Sugar.
|
||||
this.fetch = function () {
|
||||
return actions.fetch( that.gateway, that.title, that.el, that.token )( that.dispatch );
|
||||
return actions.fetch(
|
||||
that.gateway, that.title, that.el, that.token
|
||||
)( that.dispatch );
|
||||
};
|
||||
}
|
||||
} );
|
||||
|
@ -381,7 +391,10 @@ QUnit.test( 'it should dispatch the FETCH_FAILED action when the request fails',
|
|||
this.gatewayDeferred.reject( new Error( 'API req failed' ) );
|
||||
|
||||
const fetch = this.fetch().catch( function () {
|
||||
assert.equal( that.dispatch.callCount, 3, 'dispatch called thrice, START, FAILED, and COMPLETE' );
|
||||
assert.equal(
|
||||
that.dispatch.callCount, 3,
|
||||
'dispatch called thrice, START, FAILED, and COMPLETE'
|
||||
);
|
||||
assert.deepEqual(
|
||||
that.dispatch.getCall( 1 ).args[ 0 ],
|
||||
{
|
||||
|
@ -402,7 +415,10 @@ QUnit.test( 'it should dispatch the FETCH_FAILED action when the request fails e
|
|||
assert.expect( 2 );
|
||||
|
||||
const fetch = this.fetch().catch( function () {
|
||||
assert.equal( that.dispatch.callCount, 3, 'dispatch called thrice, START, FAILED, and COMPLETE' );
|
||||
assert.equal(
|
||||
that.dispatch.callCount, 3,
|
||||
'dispatch called thrice, START, FAILED, and COMPLETE'
|
||||
);
|
||||
assert.deepEqual(
|
||||
that.dispatch.getCall( 1 ).args[ 0 ],
|
||||
{
|
||||
|
@ -498,12 +514,18 @@ QUnit.test( 'it should dispatch an action with previous and current enabled stat
|
|||
|
||||
actions.saveSettings( /* enabled = */ true )( dispatch, getState );
|
||||
|
||||
assert.ok( getState.calledOnce, 'it should query the global state for the current state' );
|
||||
assert.ok( dispatch.calledWith( {
|
||||
type: 'SETTINGS_CHANGE',
|
||||
wasEnabled: false,
|
||||
enabled: true
|
||||
} ), 'it should dispatch the action with the previous and next enabled state' );
|
||||
assert.ok(
|
||||
getState.calledOnce,
|
||||
'it should query the global state for the current state'
|
||||
);
|
||||
assert.ok(
|
||||
dispatch.calledWith( {
|
||||
type: 'SETTINGS_CHANGE',
|
||||
wasEnabled: false,
|
||||
enabled: true
|
||||
} ),
|
||||
'it should dispatch the action with the previous and next enabled state'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.module( 'ext.popups/actions#previewShow' );
|
||||
|
|
|
@ -7,7 +7,10 @@ QUnit.module( 'ext.popups/changeListeners/render', {
|
|||
show: this.sandbox.stub().returns( $.Deferred().resolve() )
|
||||
};
|
||||
|
||||
this.sandbox.stub( RendererModule, 'render', this.sandbox.stub().returns( this.preview ) );
|
||||
this.sandbox.stub(
|
||||
RendererModule, 'render',
|
||||
this.sandbox.stub().returns( this.preview )
|
||||
);
|
||||
}
|
||||
} );
|
||||
|
||||
|
|
|
@ -50,10 +50,14 @@ QUnit.test( 'it should create settings when shouldShow becomes true', function (
|
|||
this.settings( null, this.defaultState );
|
||||
this.settings( this.defaultState, this.showState );
|
||||
|
||||
assert.ok( this.render.calledWith( 'actions' ), 'The renderer should be called with the actions' );
|
||||
assert.ok( this.rendered.appendTo.called, 'The rendered object should be in the DOM' );
|
||||
assert.ok( this.rendered.setEnabled.called, 'The rendered form should be up to date' );
|
||||
assert.ok( this.rendered.show.called, 'The rendered object should be showed' );
|
||||
assert.ok( this.render.calledWith( 'actions' ),
|
||||
'The renderer should be called with the actions' );
|
||||
assert.ok( this.rendered.appendTo.called,
|
||||
'The rendered object should be in the DOM' );
|
||||
assert.ok( this.rendered.setEnabled.called,
|
||||
'The rendered form should be up to date' );
|
||||
assert.ok( this.rendered.show.called,
|
||||
'The rendered object should be showed' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'it should not create settings when shouldShow keeps being true', function ( assert ) {
|
||||
|
@ -61,10 +65,14 @@ QUnit.test( 'it should not create settings when shouldShow keeps being true', fu
|
|||
this.settings( this.defaultState, this.showState );
|
||||
this.settings( this.showState, this.showState );
|
||||
|
||||
assert.ok( this.render.calledOnce, 'The renderer should be called only the first time' );
|
||||
assert.ok( this.rendered.appendTo.calledOnce, 'The rendered object should be in the DOM' );
|
||||
assert.ok( this.rendered.show.calledOnce, 'The rendered object should be showed just once' );
|
||||
assert.notOk( this.rendered.hide.called, 'The rendered object should not be hidden' );
|
||||
assert.ok( this.render.calledOnce,
|
||||
'The renderer should be called only the first time' );
|
||||
assert.ok( this.rendered.appendTo.calledOnce,
|
||||
'The rendered object should be in the DOM' );
|
||||
assert.ok( this.rendered.show.calledOnce,
|
||||
'The rendered object should be showed just once' );
|
||||
assert.notOk( this.rendered.hide.called,
|
||||
'The rendered object should not be hidden' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'it should show settings and update the form when shouldShow becomes true', function ( assert ) {
|
||||
|
@ -75,11 +83,16 @@ QUnit.test( 'it should show settings and update the form when shouldShow becomes
|
|||
preview: { enabled: false }
|
||||
} ) );
|
||||
|
||||
assert.ok( this.render.calledOnce, 'The renderer should be called only the first time' );
|
||||
assert.ok( this.rendered.setEnabled.calledTwice, 'The rendered form should be up to date when shown' );
|
||||
assert.strictEqual( this.rendered.setEnabled.firstCall.args[ 0 ], true, 'Set enabled should be called with the current enabled state' );
|
||||
assert.strictEqual( this.rendered.setEnabled.secondCall.args[ 0 ], false, 'Set enabled should be called with the current enabled state' );
|
||||
assert.ok( this.rendered.show.calledTwice, 'The rendered object should be showed' );
|
||||
assert.ok( this.render.calledOnce,
|
||||
'The renderer should be called only the first time' );
|
||||
assert.ok( this.rendered.setEnabled.calledTwice,
|
||||
'The rendered form should be up to date when shown' );
|
||||
assert.strictEqual( this.rendered.setEnabled.firstCall.args[ 0 ], true,
|
||||
'Set enabled should be called with the current enabled state' );
|
||||
assert.strictEqual( this.rendered.setEnabled.secondCall.args[ 0 ], false,
|
||||
'Set enabled should be called with the current enabled state' );
|
||||
assert.ok( this.rendered.show.calledTwice,
|
||||
'The rendered object should be showed' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'it should hide settings when shouldShow becomes false', function ( assert ) {
|
||||
|
@ -87,7 +100,8 @@ QUnit.test( 'it should hide settings when shouldShow becomes false', function (
|
|||
this.settings( this.defaultState, this.showState );
|
||||
this.settings( this.showState, this.defaultState );
|
||||
|
||||
assert.ok( this.rendered.hide.calledOnce, 'The rendered object should be hidden' );
|
||||
assert.ok( this.rendered.hide.calledOnce,
|
||||
'The rendered object should be hidden' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'it should show help when showHelp becomes true', function ( assert ) {
|
||||
|
@ -95,7 +109,8 @@ QUnit.test( 'it should show help when showHelp becomes true', function ( assert
|
|||
this.settings( this.defaultState, this.showState );
|
||||
this.settings( this.showState, this.showHelpState );
|
||||
|
||||
assert.ok( this.rendered.toggleHelp.calledWith( true ), 'Help should be shown' );
|
||||
assert.ok( this.rendered.toggleHelp.calledWith( true ),
|
||||
'Help should be shown' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'it should hide help when showHelp becomes false', function ( assert ) {
|
||||
|
@ -104,6 +119,8 @@ QUnit.test( 'it should hide help when showHelp becomes false', function ( assert
|
|||
this.settings( this.showState, this.showHelpState );
|
||||
this.settings( this.showHelpState, this.hideHelpState );
|
||||
|
||||
assert.equal( this.rendered.toggleHelp.callCount, 2, 'Help should have been toggled on and off' );
|
||||
assert.deepEqual( this.rendered.toggleHelp.secondCall.args, [ false ], 'Help should be hidden' );
|
||||
assert.equal( this.rendered.toggleHelp.callCount, 2,
|
||||
'Help should have been toggled on and off' );
|
||||
assert.deepEqual( this.rendered.toggleHelp.secondCall.args, [ false ],
|
||||
'Help should be hidden' );
|
||||
} );
|
||||
|
|
|
@ -63,7 +63,8 @@ QUnit.test( '#getPreviewCountBucket', function ( assert ) {
|
|||
assert.equal(
|
||||
bucket,
|
||||
cases[ i ][ 1 ],
|
||||
'Preview count bucket is "' + bucket + '" when preview count is ' + count + '.'
|
||||
'Preview count bucket is "' +
|
||||
bucket + '" when preview count is ' + count + '.'
|
||||
);
|
||||
}
|
||||
} );
|
||||
|
|
|
@ -6,7 +6,8 @@ QUnit.module( 'gateway/index.js', {
|
|||
beforeEach: function () {
|
||||
mediaWiki.Api = function () {};
|
||||
|
||||
this.createMediaWikiApiGateway = this.sandbox.stub( MediawikiModule, 'default' );
|
||||
this.createMediaWikiApiGateway =
|
||||
this.sandbox.stub( MediawikiModule, 'default' );
|
||||
this.createRESTBaseGateway = this.sandbox.stub( RestModule, 'default' );
|
||||
|
||||
this.config = new Map(); /* global Map */
|
||||
|
@ -18,7 +19,8 @@ QUnit.test( 'it uses mediawiki plain text gateway with wgPopupsGateway == "mwApi
|
|||
|
||||
createGateway( this.config );
|
||||
|
||||
assert.ok( this.createMediaWikiApiGateway.called, 'MW plain text gateway called' );
|
||||
assert.ok( this.createMediaWikiApiGateway.called,
|
||||
'MW plain text gateway called' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'it uses rest plain text gateway with wgPopupsGateway == "restbasePlain"', function ( assert ) {
|
||||
|
@ -26,7 +28,8 @@ QUnit.test( 'it uses rest plain text gateway with wgPopupsGateway == "restbasePl
|
|||
|
||||
createGateway( this.config );
|
||||
|
||||
assert.ok( this.createRESTBaseGateway.called, 'REST plain text gateway called' );
|
||||
assert.ok( this.createRESTBaseGateway.called,
|
||||
'REST plain text gateway called' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'it uses rest HTML gateway with wgPopupsGateway == "restbaseHTML"', function ( assert ) {
|
||||
|
|
|
@ -154,7 +154,8 @@ QUnit.test( 'MediaWiki API gateway is correctly converting the page data to a mo
|
|||
|
||||
QUnit.test( 'MediaWiki API gateway handles API failure', function ( assert ) {
|
||||
var api = {
|
||||
get: this.sandbox.stub().returns( $.Deferred().reject( { status: 400 } ).promise() )
|
||||
get: this.sandbox.stub()
|
||||
.returns( $.Deferred().reject( { status: 400 } ).promise() )
|
||||
},
|
||||
gateway = createMediaWikiApiGateway( api, DEFAULT_CONSTANTS );
|
||||
|
||||
|
|
|
@ -157,7 +157,8 @@ QUnit.test( 'RESTBase gateway doesn\'t stretch thumbnails', function ( assert )
|
|||
var model,
|
||||
gateway = createRESTBaseGateway();
|
||||
|
||||
model = gateway.convertPageToModel( RESTBASE_RESPONSE, 2000, provideParsedExtract );
|
||||
model = gateway.convertPageToModel(
|
||||
RESTBASE_RESPONSE, 2000, provideParsedExtract );
|
||||
|
||||
assert.deepEqual(
|
||||
model.thumbnail,
|
||||
|
@ -166,7 +167,11 @@ QUnit.test( 'RESTBase gateway doesn\'t stretch thumbnails', function ( assert )
|
|||
);
|
||||
|
||||
// ---
|
||||
model = gateway.convertPageToModel( RESTBASE_RESPONSE, RESTBASE_RESPONSE.originalimage.height, provideParsedExtract );
|
||||
model = gateway.convertPageToModel(
|
||||
RESTBASE_RESPONSE,
|
||||
RESTBASE_RESPONSE.originalimage.height,
|
||||
provideParsedExtract
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
model.thumbnail,
|
||||
|
@ -175,7 +180,8 @@ QUnit.test( 'RESTBase gateway doesn\'t stretch thumbnails', function ( assert )
|
|||
);
|
||||
|
||||
// ---
|
||||
model = gateway.convertPageToModel( RESTBASE_RESPONSE_WITH_SMALL_IMAGE, 320, provideParsedExtract );
|
||||
model = gateway.convertPageToModel(
|
||||
RESTBASE_RESPONSE_WITH_SMALL_IMAGE, 320, provideParsedExtract );
|
||||
|
||||
assert.deepEqual(
|
||||
model.thumbnail,
|
||||
|
@ -184,7 +190,8 @@ QUnit.test( 'RESTBase gateway doesn\'t stretch thumbnails', function ( assert )
|
|||
);
|
||||
|
||||
// ---
|
||||
model = gateway.convertPageToModel( RESTBASE_RESPONSE_WITH_LANDSCAPE_IMAGE, 640, provideParsedExtract );
|
||||
model = gateway.convertPageToModel(
|
||||
RESTBASE_RESPONSE_WITH_LANDSCAPE_IMAGE, 640, provideParsedExtract );
|
||||
|
||||
assert.deepEqual(
|
||||
model.thumbnail,
|
||||
|
@ -219,7 +226,8 @@ QUnit.test( 'RESTBase gateway stretches SVGs', function ( assert ) {
|
|||
var model,
|
||||
gateway = createRESTBaseGateway();
|
||||
|
||||
model = gateway.convertPageToModel( SVG_RESTBASE_RESPONSE, 2000, provideParsedExtract );
|
||||
model = gateway.convertPageToModel(
|
||||
SVG_RESTBASE_RESPONSE, 2000, provideParsedExtract );
|
||||
|
||||
assert.equal(
|
||||
model.thumbnail.source,
|
||||
|
@ -229,7 +237,8 @@ QUnit.test( 'RESTBase gateway stretches SVGs', function ( assert ) {
|
|||
} );
|
||||
|
||||
QUnit.test( 'RESTBase gateway handles API failure', function ( assert ) {
|
||||
var api = this.sandbox.stub().returns( $.Deferred().reject( { status: 500 } ).promise() ),
|
||||
var api = this.sandbox.stub()
|
||||
.returns( $.Deferred().reject( { status: 500 } ).promise() ),
|
||||
gateway = createRESTBaseGateway( api );
|
||||
|
||||
return gateway.getPageSummary( 'Test Title' ).catch( function () {
|
||||
|
@ -249,11 +258,13 @@ QUnit.test( 'RESTBase gateway does not treat a 404 as a failure', function ( ass
|
|||
api = this.sandbox.stub().returns(
|
||||
$.Deferred().reject( response ).promise()
|
||||
),
|
||||
gateway = createRESTBaseGateway( api, DEFAULT_CONSTANTS, provideParsedExtract );
|
||||
gateway = createRESTBaseGateway(
|
||||
api, DEFAULT_CONSTANTS, provideParsedExtract );
|
||||
|
||||
return gateway.getPageSummary( 'Missing Page' ).then( function ( result ) {
|
||||
assert.equal( result.title, 'Missing Page', 'Title' );
|
||||
// Extract is undefined since the parser is only invoked for successful responses.
|
||||
// Extract is undefined since the parser is only invoked for successful
|
||||
// responses.
|
||||
assert.equal( result.extract, undefined, 'Extract' );
|
||||
} );
|
||||
} );
|
||||
|
@ -262,7 +273,8 @@ QUnit.test( 'RESTBase gateway returns the correct data ', function ( assert ) {
|
|||
var api = this.sandbox.stub().returns(
|
||||
$.Deferred().resolve( RESTBASE_RESPONSE ).promise()
|
||||
),
|
||||
gateway = createRESTBaseGateway( api, DEFAULT_CONSTANTS, provideParsedExtract );
|
||||
gateway = createRESTBaseGateway(
|
||||
api, DEFAULT_CONSTANTS, provideParsedExtract );
|
||||
|
||||
return gateway.getPageSummary( 'Test Title' ).then( function ( result ) {
|
||||
assert.deepEqual( result, RESTBASE_RESPONSE_PREVIEW_MODEL );
|
||||
|
@ -272,7 +284,8 @@ QUnit.test( 'RESTBase gateway returns the correct data ', function ( assert ) {
|
|||
QUnit.test( 'RESTBase gateway handles missing images ', function ( assert ) {
|
||||
var model,
|
||||
gateway = createRESTBaseGateway();
|
||||
model = gateway.convertPageToModel( RESTBASE_RESPONSE_WITHOUT_IMAGE, 300, provideParsedExtract );
|
||||
model = gateway.convertPageToModel(
|
||||
RESTBASE_RESPONSE_WITHOUT_IMAGE, 300, provideParsedExtract );
|
||||
|
||||
assert.equal(
|
||||
model.originalimage,
|
||||
|
@ -283,20 +296,25 @@ QUnit.test( 'RESTBase gateway handles missing images ', function ( assert ) {
|
|||
|
||||
QUnit.test( 'RESTBase gateway handles missing extracts', function ( assert ) {
|
||||
var api = this.sandbox.stub().returns( $.Deferred().resolve( {} ).promise() ),
|
||||
gateway = createRESTBaseGateway( api, DEFAULT_CONSTANTS, provideParsedExtract );
|
||||
gateway = createRESTBaseGateway(
|
||||
api, DEFAULT_CONSTANTS, provideParsedExtract );
|
||||
|
||||
return gateway.getPageSummary( 'Test Title with missing extract' ).then( function ( result ) {
|
||||
assert.equal( result.title, 'Test Title with missing extract', 'Title' );
|
||||
assert.equal( result.extract, '!!', 'Extract' );
|
||||
} );
|
||||
return gateway.getPageSummary( 'Test Title with missing extract' )
|
||||
.then( function ( result ) {
|
||||
assert.equal( result.title, 'Test Title with missing extract', 'Title' );
|
||||
assert.equal( result.extract, '!!', 'Extract' );
|
||||
} );
|
||||
} );
|
||||
|
||||
QUnit.test( 'RESTBase gateway handles no content success responses', function ( assert ) {
|
||||
var api = this.sandbox.stub().returns( $.Deferred().resolve( { status: 204 } ).promise() ),
|
||||
gateway = createRESTBaseGateway( api, DEFAULT_CONSTANTS, provideParsedExtract );
|
||||
var api = this.sandbox.stub()
|
||||
.returns( $.Deferred().resolve( { status: 204 } ).promise() ),
|
||||
gateway = createRESTBaseGateway(
|
||||
api, DEFAULT_CONSTANTS, provideParsedExtract );
|
||||
|
||||
return gateway.getPageSummary( 'Test Title with empty response' ).then( function ( result ) {
|
||||
assert.equal( result.title, 'Test Title with empty response', 'Title' );
|
||||
assert.equal( result.extract, '!!', 'Extract' );
|
||||
} );
|
||||
return gateway.getPageSummary( 'Test Title with empty response' )
|
||||
.then( function ( result ) {
|
||||
assert.equal( result.title, 'Test Title with empty response', 'Title' );
|
||||
assert.equal( result.extract, '!!', 'Extract' );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -4,7 +4,8 @@ import getUserBucket from '../../src/getUserBucket';
|
|||
QUnit.module( 'ext.popups#getUserBucket' );
|
||||
|
||||
QUnit.test( 'If no users are subject to experiment everyone is bucketed as on', function ( assert ) {
|
||||
assert.ok( getUserBucket( stubs.createStubExperiments( 'A' ), 0, 'a' ) === 'on' );
|
||||
assert.ok(
|
||||
getUserBucket( stubs.createStubExperiments( 'A' ), 0, 'a' ) === 'on' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'Define how experiment size impacts buckets', function ( assert ) {
|
||||
|
@ -26,10 +27,16 @@ QUnit.test( 'Define how experiment size impacts buckets', function ( assert ) {
|
|||
getUserBucket( experiments, test[ 0 ], 'a' );
|
||||
|
||||
actualBuckets = spy.getCall( 0 ).args[ 0 ].buckets;
|
||||
// To avoid precision issues we'll need to test them all individually rather than check
|
||||
// use calledWith. Otherwise we'll get some false positives.
|
||||
assert.ok( actualBuckets.off.toFixed( 2 ) === expectedBuckets.off.toFixed( 2 ) );
|
||||
assert.ok( actualBuckets.on.toFixed( 2 ) === expectedBuckets.on.toFixed( 2 ) );
|
||||
assert.ok( actualBuckets.control.toFixed( 2 ) === expectedBuckets.control.toFixed( 2 ) );
|
||||
// To avoid precision issues we'll need to test them all individually
|
||||
// rather than check use calledWith. Otherwise we'll get some false
|
||||
// positives.
|
||||
assert.ok(
|
||||
actualBuckets.off.toFixed( 2 ) === expectedBuckets.off.toFixed( 2 ) );
|
||||
assert.ok(
|
||||
actualBuckets.on.toFixed( 2 ) === expectedBuckets.on.toFixed( 2 ) );
|
||||
assert.ok(
|
||||
actualBuckets.control.toFixed( 2 ) ===
|
||||
expectedBuckets.control.toFixed( 2 )
|
||||
);
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -65,7 +65,9 @@ QUnit.test( 'if experiment is running on group is subject to event logging', fun
|
|||
|
||||
QUnit.test( 'if experiment is running control group is subject to event logging', function ( assert ) {
|
||||
assert.ok( this.isEnabled( true, BUCKETS.control ), 'anons are logged' );
|
||||
assert.notOk( this.isEnabled( false, BUCKETS.control ), 'but not authenticated users' );
|
||||
assert.notOk(
|
||||
this.isEnabled( false, BUCKETS.control ),
|
||||
'but not authenticated users' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'if experiment is running off group is not subject to event logging', function ( assert ) {
|
||||
|
@ -85,6 +87,9 @@ QUnit.test( 'it should respect the debug flag always', function ( assert ) {
|
|||
|
||||
this.config.set( 'wgPopupsEventLogging', true );
|
||||
|
||||
assert.ok( this.isEnabled( true, BUCKETS.off ), 'Even when user is bucketed as off' );
|
||||
assert.ok( this.isEnabled( false, BUCKETS.off ), 'Even when user is logged in and bucketed as off' );
|
||||
assert.ok(
|
||||
this.isEnabled( true, BUCKETS.off ), 'Even when user is bucketed as off' );
|
||||
assert.ok(
|
||||
this.isEnabled( false, BUCKETS.off ),
|
||||
'Even when user is logged in and bucketed as off' );
|
||||
} );
|
||||
|
|
|
@ -102,18 +102,23 @@ QUnit.module( 'ext.popups preview @integration', {
|
|||
{ get: identity }
|
||||
);
|
||||
|
||||
this.dwell = function ( title, el, ev, fetchResponse, resolution = FETCH_RESOLUTION.RESOLVE ) {
|
||||
this.dwell = function (
|
||||
title, el, ev, fetchResponse, resolution = FETCH_RESOLUTION.RESOLVE
|
||||
) {
|
||||
that.resetWait();
|
||||
that.actions.linkDwell( title, el, ev, {
|
||||
getPageSummary: function () {
|
||||
var method = resolution === FETCH_RESOLUTION.RESOLVE ? 'resolve' : 'reject';
|
||||
var method = resolution === FETCH_RESOLUTION.RESOLVE ?
|
||||
'resolve' : 'reject';
|
||||
return $.Deferred()[ method ]( fetchResponse ).promise();
|
||||
}
|
||||
}, function () { return 'pagetoken'; } );
|
||||
return that.waitPromise;
|
||||
};
|
||||
|
||||
this.dwellAndShowPreview = function ( title, el, ev, fetchResponse, reject = FETCH_RESOLUTION.RESOLVE ) {
|
||||
this.dwellAndShowPreview = function (
|
||||
title, el, ev, fetchResponse, reject = FETCH_RESOLUTION.RESOLVE
|
||||
) {
|
||||
that.dwell( title, el, ev, fetchResponse, reject );
|
||||
that.waitDeferred.resolve();
|
||||
|
||||
|
@ -194,21 +199,27 @@ QUnit.test( 'in ACTIVE state, fetch end switches it to DATA', function ( assert
|
|||
var store = this.store,
|
||||
el = this.el;
|
||||
|
||||
return this.dwellAndShowPreview( this.title, el, 'event', 42 ).then( function () {
|
||||
var state = store.getState();
|
||||
assert.equal( state.preview.activeLink, el );
|
||||
assert.equal( state.preview.shouldShow, true, 'Should show when data has been fetched' );
|
||||
} );
|
||||
return this.dwellAndShowPreview( this.title, el, 'event', 42 )
|
||||
.then( function () {
|
||||
var state = store.getState();
|
||||
assert.equal( state.preview.activeLink, el );
|
||||
assert.equal(
|
||||
state.preview.shouldShow, true,
|
||||
'Should show when data has been fetched' );
|
||||
} );
|
||||
} );
|
||||
|
||||
QUnit.test( 'in ACTIVE state, fetch fail switches it to DATA', function ( assert ) {
|
||||
var store = this.store,
|
||||
el = this.el;
|
||||
|
||||
return this.dwellAndShowPreview( this.title, el, 'event', 42, FETCH_RESOLUTION.REJECT ).then( function () {
|
||||
return this.dwellAndShowPreview(
|
||||
this.title, el, 'event', 42, FETCH_RESOLUTION.REJECT
|
||||
).then( function () {
|
||||
var state = store.getState();
|
||||
assert.equal( state.preview.activeLink, el );
|
||||
assert.equal( state.preview.shouldShow, true, 'Should show when data couldn\'t be fetched' );
|
||||
assert.equal( state.preview.shouldShow, true,
|
||||
'Should show when data couldn\'t be fetched' );
|
||||
} );
|
||||
} );
|
||||
|
||||
|
@ -216,12 +227,14 @@ QUnit.test( 'in ACTIVE state, abandon start, and then end, switch it to INACTIVE
|
|||
var that = this,
|
||||
el = this.el;
|
||||
|
||||
return this.dwellAndShowPreview( this.title, el, 'event', 42 ).then( function () {
|
||||
return that.abandonAndWait( el );
|
||||
} ).then( function () {
|
||||
var state = that.store.getState();
|
||||
assert.equal( state.preview.activeLink, undefined, 'After abandoning, preview is back to INACTIVE' );
|
||||
} );
|
||||
return this.dwellAndShowPreview( this.title, el, 'event', 42 )
|
||||
.then( function () {
|
||||
return that.abandonAndWait( el );
|
||||
} ).then( function () {
|
||||
var state = that.store.getState();
|
||||
assert.equal( state.preview.activeLink, undefined,
|
||||
'After abandoning, preview is back to INACTIVE' );
|
||||
} );
|
||||
} );
|
||||
|
||||
QUnit.test( 'in ACTIVE state, abandon link, and then dwell preview, should keep it active after all delays', function ( assert ) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { createModel, TYPE_PAGE, TYPE_GENERIC } from '../../../src/preview/model';
|
||||
import { createModel, TYPE_PAGE, TYPE_GENERIC }
|
||||
from '../../../src/preview/model';
|
||||
|
||||
QUnit.module( 'ext.popups.preview#createModel' );
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ QUnit.test( 'BOOT', function ( assert ) {
|
|||
state;
|
||||
|
||||
expectedEditCountBucket = counts.getEditCountBucket( action.user.editCount );
|
||||
expectedPreviewCountBucket = counts.getPreviewCountBucket( action.user.previewCount );
|
||||
expectedPreviewCountBucket =
|
||||
counts.getPreviewCountBucket( action.user.previewCount );
|
||||
|
||||
state = eventLogging( this.initialState, action );
|
||||
|
||||
|
@ -249,81 +250,78 @@ QUnit.test( 'LINK_DWELL doesn\'t start a new interaction under certain condition
|
|||
);
|
||||
} );
|
||||
|
||||
QUnit.test(
|
||||
'LINK_DWELL should enqueue a "dismissed" or "dwelledButAbandoned" event under certain conditions',
|
||||
function ( assert ) {
|
||||
var token = '0987654321',
|
||||
now = Date.now(),
|
||||
state;
|
||||
QUnit.test( 'LINK_DWELL should enqueue a "dismissed" or "dwelledButAbandoned" event under certain conditions', function ( assert ) {
|
||||
var token = '0987654321',
|
||||
now = Date.now(),
|
||||
state;
|
||||
|
||||
// Read: The user dwells on link A, abandons it, and dwells on link B fewer
|
||||
// than 300 ms after (before the ABANDON_END action is reduced).
|
||||
state = eventLogging( undefined, {
|
||||
type: 'LINK_DWELL',
|
||||
el: this.link,
|
||||
title: 'Foo',
|
||||
namespaceID: 1,
|
||||
token: token,
|
||||
timestamp: now
|
||||
} );
|
||||
// Read: The user dwells on link A, abandons it, and dwells on link B fewer
|
||||
// than 300 ms after (before the ABANDON_END action is reduced).
|
||||
state = eventLogging( undefined, {
|
||||
type: 'LINK_DWELL',
|
||||
el: this.link,
|
||||
title: 'Foo',
|
||||
namespaceID: 1,
|
||||
token: token,
|
||||
timestamp: now
|
||||
} );
|
||||
|
||||
state = eventLogging( state, {
|
||||
type: 'ABANDON_START',
|
||||
timestamp: now + 250
|
||||
} );
|
||||
state = eventLogging( state, {
|
||||
type: 'ABANDON_START',
|
||||
timestamp: now + 250
|
||||
} );
|
||||
|
||||
state = eventLogging( state, {
|
||||
type: 'LINK_DWELL',
|
||||
el: $( '<a>' ),
|
||||
title: 'Bar',
|
||||
namespaceID: 1,
|
||||
token: '1234567890',
|
||||
timestamp: now + 500
|
||||
} );
|
||||
state = eventLogging( state, {
|
||||
type: 'LINK_DWELL',
|
||||
el: $( '<a>' ),
|
||||
title: 'Bar',
|
||||
namespaceID: 1,
|
||||
token: '1234567890',
|
||||
timestamp: now + 500
|
||||
} );
|
||||
|
||||
assert.deepEqual(
|
||||
state.event,
|
||||
{
|
||||
pageTitleHover: 'Foo',
|
||||
namespaceIdHover: 1,
|
||||
linkInteractionToken: '0987654321',
|
||||
totalInteractionTime: 250, // 250 - 0
|
||||
action: 'dwelledButAbandoned'
|
||||
}
|
||||
);
|
||||
assert.deepEqual(
|
||||
state.event,
|
||||
{
|
||||
pageTitleHover: 'Foo',
|
||||
namespaceIdHover: 1,
|
||||
linkInteractionToken: '0987654321',
|
||||
totalInteractionTime: 250, // 250 - 0
|
||||
action: 'dwelledButAbandoned'
|
||||
}
|
||||
);
|
||||
|
||||
// ---
|
||||
// ---
|
||||
|
||||
state = eventLogging( undefined, {
|
||||
type: 'LINK_DWELL',
|
||||
el: this.link,
|
||||
title: 'Foo',
|
||||
namespaceID: 1,
|
||||
token: token,
|
||||
timestamp: now
|
||||
} );
|
||||
state = eventLogging( undefined, {
|
||||
type: 'LINK_DWELL',
|
||||
el: this.link,
|
||||
title: 'Foo',
|
||||
namespaceID: 1,
|
||||
token: token,
|
||||
timestamp: now
|
||||
} );
|
||||
|
||||
state = eventLogging( state, {
|
||||
type: 'LINK_CLICK',
|
||||
el: this.link
|
||||
} );
|
||||
state = eventLogging( state, {
|
||||
type: 'LINK_CLICK',
|
||||
el: this.link
|
||||
} );
|
||||
|
||||
state = eventLogging( state, {
|
||||
type: 'LINK_DWELL',
|
||||
el: $( '<a>' ),
|
||||
title: 'Bar',
|
||||
namespaceID: 1,
|
||||
token: 'banana',
|
||||
timestamp: now + 500
|
||||
} );
|
||||
state = eventLogging( state, {
|
||||
type: 'LINK_DWELL',
|
||||
el: $( '<a>' ),
|
||||
title: 'Bar',
|
||||
namespaceID: 1,
|
||||
token: 'banana',
|
||||
timestamp: now + 500
|
||||
} );
|
||||
|
||||
assert.strictEqual(
|
||||
state.event,
|
||||
undefined,
|
||||
'It shouldn\'t enqueue either event if the interaction is finalized.'
|
||||
);
|
||||
}
|
||||
);
|
||||
assert.strictEqual(
|
||||
state.event,
|
||||
undefined,
|
||||
'It shouldn\'t enqueue either event if the interaction is finalized.'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( 'LINK_CLICK should enqueue an "opened" event', function ( assert ) {
|
||||
var token = '0987654321',
|
||||
|
|
|
@ -124,7 +124,9 @@ QUnit.test( 'it should return null if the title can\'t be parsed properly', func
|
|||
QUnit.test( 'it should return null if the title can\'t be parsed properly', function ( assert ) {
|
||||
window.mediaWiki.Title.newFromText.withArgs( 'title' ).returns( null );
|
||||
assert.equal( isValid( 'title' ), null );
|
||||
assert.equal( window.mediaWiki.Title.newFromText.callCount, 1, 'mediaWiki.Title.newFromText called for parsing the title' );
|
||||
assert.equal(
|
||||
window.mediaWiki.Title.newFromText.callCount, 1,
|
||||
'mediaWiki.Title.newFromText called for parsing the title' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'it should return null if the title is not from a content namespace', function ( assert ) {
|
||||
|
|
|
@ -216,7 +216,8 @@ QUnit.test( 'bindBehavior - preview dwell', function ( assert ) {
|
|||
preview.el.mouseenter();
|
||||
|
||||
assert.ok( behavior.previewDwell.calledOnce, 'Preview dwell is called.' );
|
||||
assert.notOk( behavior.previewAbandon.called, 'Preview abandon is NOT called.' );
|
||||
assert.notOk(
|
||||
behavior.previewAbandon.called, 'Preview abandon is NOT called.' );
|
||||
assert.notOk( behavior.click.called, 'Click is NOT called.' );
|
||||
assert.notOk( behavior.showSettings.called, 'Show settings is NOT called.' );
|
||||
} );
|
||||
|
@ -242,9 +243,11 @@ QUnit.test( 'bindBehavior - preview click', function ( assert ) {
|
|||
preview.el.click();
|
||||
|
||||
assert.notOk( behavior.previewDwell.called, 'Preview dwell is NOT called.' );
|
||||
assert.notOk( behavior.previewAbandon.called, 'Preview abandon is NOT called.' );
|
||||
assert.notOk(
|
||||
behavior.previewAbandon.called, 'Preview abandon is NOT called.' );
|
||||
assert.ok( behavior.click.calledOnce, 'Click is called.' );
|
||||
assert.notOk( behavior.showSettings.called, 'Settings link click is NOT called.' );
|
||||
assert.notOk( behavior.showSettings.called,
|
||||
'Settings link click is NOT called.' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'bindBehavior - settings link click', function ( assert ) {
|
||||
|
@ -255,9 +258,11 @@ QUnit.test( 'bindBehavior - settings link click', function ( assert ) {
|
|||
preview.el.find( '.mwe-popups-settings-icon' ).click();
|
||||
|
||||
assert.notOk( behavior.previewDwell.called, 'Preview dwell is NOT called.' );
|
||||
assert.notOk( behavior.previewAbandon.called, 'Preview abandon is NOT called.' );
|
||||
assert.notOk(
|
||||
behavior.previewAbandon.called, 'Preview abandon is NOT called.' );
|
||||
assert.notOk( behavior.click.called, 'Click is NOT called.' );
|
||||
assert.ok( behavior.showSettings.calledOnce, 'Settings link click is called.' );
|
||||
assert.ok(
|
||||
behavior.showSettings.calledOnce, 'Settings link click is called.' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'bindBehavior - settings link URL', function ( assert ) {
|
||||
|
@ -683,7 +688,8 @@ QUnit.test( '#createLayout - portrait preview, mouse event, link is on the top l
|
|||
height: 827
|
||||
},
|
||||
pokeySize = 8,
|
||||
layout = renderer.createLayout( isPreviewTall, eventData, linkData, windowData, pokeySize );
|
||||
layout = renderer.createLayout(
|
||||
isPreviewTall, eventData, linkData, windowData, pokeySize );
|
||||
|
||||
assert.deepEqual(
|
||||
layout,
|
||||
|
@ -728,7 +734,8 @@ QUnit.test( '#createLayout - tall preview, mouse event, link is on the bottom ce
|
|||
height: 827
|
||||
},
|
||||
pokeySize = 8,
|
||||
layout = renderer.createLayout( isPreviewTall, eventData, linkData, windowData, pokeySize );
|
||||
layout = renderer.createLayout(
|
||||
isPreviewTall, eventData, linkData, windowData, pokeySize );
|
||||
|
||||
assert.deepEqual(
|
||||
layout,
|
||||
|
@ -769,7 +776,8 @@ QUnit.test( '#createLayout - empty preview, keyboard event, link is on the cente
|
|||
height: 827
|
||||
},
|
||||
pokeySize = 8,
|
||||
layout = renderer.createLayout( isPreviewTall, eventData, linkData, windowData, pokeySize );
|
||||
layout = renderer.createLayout(
|
||||
isPreviewTall, eventData, linkData, windowData, pokeySize );
|
||||
|
||||
assert.deepEqual(
|
||||
layout,
|
||||
|
|
|
@ -90,7 +90,8 @@ QUnit.test( '#getPreviewCount should return the count as a number', function ( a
|
|||
QUnit.test( '#setPreviewCount should store the count as a string', function ( assert ) {
|
||||
this.userSettings.setPreviewCount( 222 );
|
||||
|
||||
assert.strictEqual( this.storage.get( 'ext.popups.core.previewCount' ), '222' );
|
||||
assert.strictEqual(
|
||||
this.storage.get( 'ext.popups.core.previewCount' ), '222' );
|
||||
} );
|
||||
|
||||
QUnit.test( '#getPreviewCount should override value in storage when is not a number', function ( assert ) {
|
||||
|
|
Loading…
Reference in a new issue