mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Popups
synced 2024-12-24 13:03:09 +00:00
4d7d55ec14
This name is more fitting to the new purpose of this method. Change-Id: I48f5e9a3ae737a104270699742a96923c92e12e8
295 lines
10 KiB
JavaScript
295 lines
10 KiB
JavaScript
( function ( $, mw ) {
|
|
var schemaPopups = mw.popups.schemaPopups;
|
|
|
|
/**
|
|
* Simulates a test run of several events.
|
|
*
|
|
* @param {Array} actions list of event actions
|
|
* @param {Object} [additionalData] to log
|
|
* @return {Array|false} the result of the last event to be run.
|
|
*/
|
|
function runEventSequence( actions, additionalData ) {
|
|
var previousEvent;
|
|
|
|
$.each( actions, function ( i, action ) {
|
|
previousEvent = schemaPopups.processHovercardEvent( $.extend( {
|
|
action: action
|
|
}, additionalData || {} ), previousEvent );
|
|
} );
|
|
return previousEvent;
|
|
}
|
|
|
|
QUnit.module( 'ext.popups.schemaPopups.utils', {
|
|
setup: function () {
|
|
var ts = 1477422540409;
|
|
this.sandbox.stub( mw.popups, 'getPreviewCountBucket' ).returns(
|
|
'5-20 previews'
|
|
);
|
|
this.sandbox.stub( mw, 'now' )
|
|
.onFirstCall().returns( ts ) // hover
|
|
.onSecondCall().returns( ts + 5000 )
|
|
.onThirdCall().returns( ts + 15000 ) // sometimes second hover if dwelled but abandoned is end of first sequence
|
|
.onCall( 3 ).returns( ts + 15000 + 200 ) // second hover
|
|
.onCall( 4 ).returns( ts + 15000 + 200 + 500 )
|
|
.onCall( 5 ).returns( ts + 15000 + 200 + 700 );
|
|
}
|
|
} );
|
|
|
|
QUnit.test( 'getSamplingRate', function ( assert ) {
|
|
var configStub = this.sandbox.stub( mw.config, 'get' )
|
|
.withArgs( 'wgPopupsSchemaPopupsSamplingRate' ),
|
|
isFunctionStub = this.sandbox.stub( $, 'isFunction' )
|
|
.withArgs( navigator.sendBeacon ),
|
|
mwUserSessionIdStub = this.sandbox.stub( mw.user, 'sessionId' );
|
|
|
|
QUnit.expect( 9 );
|
|
|
|
isFunctionStub.returns( false );
|
|
assert.equal( schemaPopups.getSamplingRate(), 0,
|
|
'Sampling rate is 0 when `navigator.sendBeacon` is unavailable.' );
|
|
|
|
isFunctionStub.returns( true );
|
|
|
|
configStub.returns( null );
|
|
mwUserSessionIdStub.returns( 'abc' );
|
|
assert.equal( schemaPopups.getSamplingRate(), 0,
|
|
'Sampling rate is 0 when the `wgPopupsSchemaPopupsSamplingRate`' +
|
|
' config variable is undefined and' +
|
|
' `mw.user.sessionId() = ' + mw.user.sessionId() + '`.' );
|
|
|
|
configStub.returns( null );
|
|
mwUserSessionIdStub.returns( 'def' );
|
|
assert.equal( schemaPopups.getSamplingRate(), 0,
|
|
'Sampling rate is 0 when the `wgPopupsSchemaPopupsSamplingRate`' +
|
|
' config variable is undefined and' +
|
|
' `mw.user.sessionId() = ' + mw.user.sessionId() + '`.' );
|
|
|
|
configStub.returns( 0 );
|
|
mwUserSessionIdStub.returns( 'abc' );
|
|
assert.equal( schemaPopups.getSamplingRate(), 0,
|
|
'Sampling rate is 0 when `wgPopupsSchemaPopupsSamplingRate = 0`' +
|
|
' `mw.user.sessionId() = ' + mw.user.sessionId() + '`.' );
|
|
|
|
configStub.returns( 0 );
|
|
mwUserSessionIdStub.returns( 'def' );
|
|
assert.equal( schemaPopups.getSamplingRate(), 0,
|
|
'Sampling rate is 0 when `wgPopupsSchemaPopupsSamplingRate = 0`' +
|
|
' `mw.user.sessionId() = ' + mw.user.sessionId() + '`.' );
|
|
|
|
configStub.returns( 1 );
|
|
mwUserSessionIdStub.returns( 'abc' );
|
|
assert.equal( schemaPopups.getSamplingRate(), 1,
|
|
'Sampling rate is 1 when `wgPopupsSchemaPopupsSamplingRate = 1`' +
|
|
' `mw.user.sessionId() = ' + mw.user.sessionId() + '`.' );
|
|
|
|
configStub.returns( 1 );
|
|
mwUserSessionIdStub.returns( 'def' );
|
|
assert.equal( schemaPopups.getSamplingRate(), 1,
|
|
'Sampling rate is 1 when `wgPopupsSchemaPopupsSamplingRate = 1`' +
|
|
' `mw.user.sessionId() = ' + mw.user.sessionId() + '`.' );
|
|
|
|
configStub.returns( 0.5 );
|
|
mwUserSessionIdStub.returns( 'abc' );
|
|
assert.equal( schemaPopups.getSamplingRate(), 1,
|
|
'Sampling rate is 1 when `wgPopupsSchemaPopupsSamplingRate = 0.5` and' +
|
|
' `mw.user.sessionId() = ' + mw.user.sessionId() + '`.' );
|
|
|
|
configStub.returns( 0.5 );
|
|
mwUserSessionIdStub.returns( 'def' );
|
|
assert.equal( schemaPopups.getSamplingRate(), 0,
|
|
'Sampling rate is 0 when `wgPopupsSchemaPopupsSamplingRate = 0.5` and' +
|
|
' `mw.user.sessionId() = ' + mw.user.sessionId() + '`.' );
|
|
} );
|
|
|
|
QUnit.test( 'getEditCountBucket', function ( assert ) {
|
|
var i, bucket, editCount,
|
|
cases = [
|
|
[ 0, '0 edits' ],
|
|
[ 1, '1-4 edits' ],
|
|
[ 2, '1-4 edits' ],
|
|
[ 4, '1-4 edits' ],
|
|
[ 5, '5-99 edits' ],
|
|
[ 25, '5-99 edits' ],
|
|
[ 50, '5-99 edits' ],
|
|
[ 99, '5-99 edits' ],
|
|
[ 100, '100-999 edits' ],
|
|
[ 101, '100-999 edits' ],
|
|
[ 500, '100-999 edits' ],
|
|
[ 999, '100-999 edits' ],
|
|
[ 1000, '1000+ edits' ],
|
|
[ 1500, '1000+ edits' ]
|
|
];
|
|
|
|
QUnit.expect( cases.length );
|
|
|
|
for ( i = 0; i < cases.length; i++ ) {
|
|
editCount = cases[ i ][ 0 ];
|
|
bucket = schemaPopups.getEditCountBucket( editCount );
|
|
assert.equal(
|
|
bucket,
|
|
cases[ i ][ 1 ],
|
|
'Edit count bucket is "' + bucket + '" when edit count is ' +
|
|
editCount + '.'
|
|
);
|
|
}
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - dwell start time gets deleted', 2, function ( assert ) {
|
|
var newData,
|
|
initialData = {};
|
|
|
|
newData = schemaPopups.processHovercardEvent( initialData );
|
|
assert.equal( newData.previewCountBucket, '5-20 previews' );
|
|
assert.ok( newData.dwellStartTime === undefined );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - namespaceIdHover is added', 1, function ( assert ) {
|
|
var newData,
|
|
initialData = {
|
|
pageTitleHover: 'Talk:Foo'
|
|
};
|
|
|
|
newData = schemaPopups.processHovercardEvent( initialData );
|
|
assert.ok( newData.namespaceIdHover === 1, 'namespace is added based on title' );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - returns false if the data should not be logged due to being a duplicate', 3, function ( assert ) {
|
|
var
|
|
thisEvent = {
|
|
action: 'myevent',
|
|
dwellStartTime: 1,
|
|
linkInteractionToken: 't'
|
|
},
|
|
previousEvent = {
|
|
action: 'myevent',
|
|
linkInteractionToken: 't'
|
|
},
|
|
settingsEvent = {
|
|
action: 'disabled',
|
|
linkInteractionToken: 't'
|
|
};
|
|
|
|
assert.ok( schemaPopups.processHovercardEvent( thisEvent, previousEvent ) === false, 'duplicate events are ignored...' );
|
|
assert.ok( schemaPopups.processHovercardEvent( settingsEvent, thisEvent ) !== false, '... unless disabled event' );
|
|
assert.ok( thisEvent.dwellStartTime === 1, 'and no side effects' );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - returns false for hover and display events', 2, function ( assert ) {
|
|
assert.ok( runEventSequence( [ 'hover' ] ) === false );
|
|
assert.ok( runEventSequence( [ 'display' ] ) === false );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - check calculations of opened in new window', 1, function ( assert ) {
|
|
var logData = runEventSequence( [ 'hover', 'display', 'opened in new window' ] );
|
|
|
|
assert.ok( logData.totalInteractionTime === 15000 );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - check calculations of dwelledButAbandoned event', 2, function ( assert ) {
|
|
var logData = runEventSequence( [ 'hover', 'dwelledButAbandoned' ] );
|
|
assert.ok( logData.perceivedWait === undefined );
|
|
assert.ok( logData.totalInteractionTime === 5000 );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - dwelledButAbandoned without hover', 1, function ( assert ) {
|
|
var logData = runEventSequence( [ 'hover', 'dwelledButAbandoned', 'dwelledButAbandoned' ],
|
|
{ linkInteractionToken: 'a' } );
|
|
|
|
assert.ok( logData === false, 'if no interaction time reject it' );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - interaction time is reset on hover', 2, function ( assert ) {
|
|
var logData = runEventSequence( [
|
|
'hover', 'dwelledButAbandoned',
|
|
'hover', 'display', 'opened in new window'
|
|
] );
|
|
|
|
assert.ok( logData.perceivedWait !== undefined );
|
|
assert.ok( logData.totalInteractionTime === 700 );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - multiple dwelledButAbandoned ignored', 1, function ( assert ) {
|
|
var logData = runEventSequence( [
|
|
'hover', 'dwelledButAbandoned', 'dwelledButAbandoned'
|
|
], {
|
|
linkInteractionToken: 'a'
|
|
} );
|
|
|
|
assert.ok( logData === false, 'duplicate dwelledButAbandoned ignored' );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - no display event (opened in same tab)', 2, function ( assert ) {
|
|
var logData = runEventSequence( [
|
|
'hover', 'opened in same tab'
|
|
] );
|
|
|
|
assert.ok( logData.perceivedWait === undefined,
|
|
'if no display event no perceived wait can be calculated' );
|
|
assert.ok( logData.totalInteractionTime === 5000,
|
|
'but totalInteractionTime can be calculated' );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - dwelledButAbandoned triggered if no link interaction token', 1, function ( assert ) {
|
|
var logData = runEventSequence( [
|
|
'hover', 'dwelledButAbandoned', 'dwelledButAbandoned'
|
|
] );
|
|
|
|
assert.ok( logData.totalInteractionTime === undefined,
|
|
// is this correct behaviour? We may want to revisit this.
|
|
'if no link interaction time the duplicate event is generated but has no total interaction time' );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - opened in same tab without a hover', 2, function ( assert ) {
|
|
var logDataSequence = runEventSequence( [
|
|
'opened in same tab'
|
|
], {
|
|
linkInteractionToken: 'a'
|
|
} ),
|
|
logDataSequenceTwo = runEventSequence( [
|
|
'opened in same tab'
|
|
] );
|
|
|
|
assert.ok( logDataSequence.totalInteractionTime === undefined,
|
|
'If a end lifecycle event occurs without a hover event occuring beforehand it generates an invalid event' );
|
|
assert.ok( logDataSequenceTwo.totalInteractionTime === undefined,
|
|
'If a end lifecycle event occurs without a hover event occuring beforehand it generates an invalid event' );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - dwell start time gets reset on dismissed events', 4, function ( assert ) {
|
|
var logDataSequence = runEventSequence( [
|
|
'hover', 'display', 'dismissed'
|
|
], {
|
|
linkInteractionToken: 'a'
|
|
} ),
|
|
logDataSequenceTwo = runEventSequence( [
|
|
'hover', 'display', 'dismissed'
|
|
], {
|
|
linkInteractionToken: 'b'
|
|
} );
|
|
|
|
assert.ok( logDataSequence.totalInteractionTime === 15000 );
|
|
assert.ok( logDataSequence.perceivedWait !== undefined );
|
|
assert.ok( logDataSequenceTwo.totalInteractionTime === 700,
|
|
'The first interaction leads to the rest of the timer.' );
|
|
assert.ok( logDataSequenceTwo.perceivedWait !== undefined );
|
|
} );
|
|
|
|
QUnit.test( 'processHovercardEvent - perceivedWait should be set for "opened in" events', 2, function ( assert ) {
|
|
var data = runEventSequence( [
|
|
'hover',
|
|
'display',
|
|
'opened in same tab'
|
|
] );
|
|
|
|
assert.ok( data.perceivedWait !== undefined );
|
|
|
|
data = runEventSequence( [
|
|
'hover',
|
|
'display',
|
|
'opened in new tab'
|
|
] );
|
|
|
|
assert.ok( data.perceivedWait !== undefined );
|
|
} );
|
|
} )( jQuery, mediaWiki );
|