Don't reset interaction info when dwelling back to a link

When dwelling back to a link, previously a new LINK_DWELL action would
be sent and the reducer would reset the interaction as if it was a new
one.

This shouldn't happen, since dwelling back to the active link (from
the preview, for example) is not a new interaction, and should not
create a new interaction or hide and show the preview.

With this change, the preview reducer has the notion of new or repeat
interactions, and only resets state on new ones, and only sets
isUserDwelling when dwelling on a the link of the current interaction.

Also when the interaction is repeat, we guard on the action creator and
don't trigger the wait or the fetch request.

Change-Id: I71cde81cbfe50b6f955e562e7e5b57d0f920fdb9
This commit is contained in:
joakin 2017-01-10 15:23:40 -08:00
parent 36518b1215
commit e49103061e
4 changed files with 87 additions and 16 deletions

View file

@ -178,13 +178,22 @@
token: token
} );
// Has the new generated token been accepted?
function isNewInteraction() {
return getState().preview.activeToken === token;
}
dispatch( action );
if ( !isNewInteraction() ) {
return;
}
mw.popups.wait( FETCH_START_DELAY )
.then( function () {
var previewState = getState().preview;
if ( previewState.enabled && previewState.activeToken === token ) {
if ( previewState.enabled && isNewInteraction() ) {
dispatch( actions.fetch( gateway, el, action.timestamp ) );
}
} );

View file

@ -30,20 +30,29 @@
enabled: action.enabled
} );
case popups.actionTypes.LINK_DWELL:
return nextState( state, {
activeLink: action.el,
activeEvent: action.event,
activeToken: action.token,
// New interaction
if ( action.el !== state.activeLink ) {
return nextState( state, {
activeLink: action.el,
activeEvent: action.event,
activeToken: action.token,
// When the user dwells on a link with their keyboard, a preview is
// renderered, and then dwells on another link, the LINK_ABANDON_END
// action will be ignored.
//
// Ensure that all the preview is hidden.
shouldShow: false,
// When the user dwells on a link with their keyboard, a preview is
// renderered, and then dwells on another link, the LINK_ABANDON_END
// action will be ignored.
//
// Ensure that all the preview is hidden.
shouldShow: false,
isUserDwelling: true
} );
} else {
// Dwelling back into the same link
return nextState( state, {
isUserDwelling: true
} );
}
isUserDwelling: true
} );
case popups.actionTypes.LINK_ABANDON_END:
if ( action.el !== state.activeLink ) {
return state;

View file

@ -86,7 +86,9 @@
setup: function () {
var that = this;
this.state = {};
this.state = {
preview: {}
};
this.getState = function () {
return that.state;
};
@ -104,12 +106,17 @@
this.sandbox.stub( mw, 'now' ).returns( new Date() );
this.sandbox.stub( mw.popups.actions, 'fetch' );
// Set the state for when dispatch is called. New token is accepted
this.state.preview = {
activeToken: generateToken()
};
mw.popups.actions.linkDwell( this.el, event, /* gateway = */ null, generateToken )(
dispatch,
this.getState
);
assert.deepEqual( dispatch.getCall( 0 ).args[0], {
assert.deepEqual( dispatch.getCall( 0 ).args[ 0 ], {
type: 'LINK_DWELL',
el: this.el,
event: event,
@ -195,6 +202,30 @@
this.waitDeferred.resolve();
} );
QUnit.test( '#linkDwell doesn\'t continue if the interaction is the same one', function ( assert ) {
var done = assert.async(),
event = {},
dispatch = this.sandbox.spy();
this.state.preview = {
activeToken: '0123456789'
};
mw.popups.actions.linkDwell( this.el, event, /* gateway = */ null, generateToken )(
dispatch,
this.getState
);
this.waitPromise.then( function () {
assert.strictEqual( dispatch.callCount, 1 );
done();
} );
// After 500 ms...
this.waitDeferred.resolve();
} );
QUnit.module( 'ext.popups/actions#fetch', {
setup: function () {
var that = this;

View file

@ -58,7 +58,7 @@
);
} );
QUnit.test( 'LINK_DWELL', function ( assert ) {
QUnit.test( 'LINK_DWELL initializes the state for a new link', function ( assert ) {
var action = {
type: 'LINK_DWELL',
el: this.el,
@ -79,6 +79,28 @@
);
} );
QUnit.test( 'LINK_DWELL on an active link only updates dwell state', function ( assert ) {
var action = {
type: 'LINK_DWELL',
el: this.el,
event: {},
token: '1234567890'
},
state = {
activeLink: this.el,
isUserDwelling: false
};
assert.deepEqual(
mw.popups.reducers.preview( state, action ),
{
activeLink: this.el,
isUserDwelling: true
},
'It should only set isUserDwelling to true'
);
} );
QUnit.test( 'LINK_ABANDON_END', function ( assert ) {
var action = {
type: 'LINK_ABANDON_END',