mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Popups
synced 2024-11-30 18:34:40 +00:00
Improve & fix action and integration tests
This change fixes some issues with assertions not running, removes unnecessary promise dances, and improves legibility and some code patterns in the action and integration node tests mainly. Detailed changes: * actions.js * Fully migrate out of jQuery 1 promises (no done/fail) * Fix linkDwell action not returning the fetch action promise * actions.test.js * Simplify setupWait for the tests * It always autoresolves immediately the wait call to ensure speedy tests * No waitDeferreds or waitPromises array coordination, rely on action returned promises instead * Get rid of that = this in favor of arrow functions * Rename generic "p" promises to meaningful names * Add assert.expect for more solid tests (so that we don't skip assertions in the future if we change them) * Fix some assertions that weren't being run because of the incorrect promise being returned (p.then, and then just returning p) * Get rid of $.when stubbing in favor of waiting for the promise returned from the action * Get rid of hacky setTimeout(..., 0) to run assertions after the promises * integration.test.js * Get rid of wait(0) calls to hack around asynchronous actions * Use the action returned promises instead of the waitPromises/Deferreds * Remove unused "el" parameter being passed to this.abandon in several tests * Remove unnecessary test helper this.abandonPreview (it was the same as this.abandon) * Clarify a bit the last and more complex test with some comments and variable name changes * Get rid of that=this in favor of arrow functions * container.test.js * Get rid of that=this in favor of arrow functions * previewBehavior.test.js * Get rid of that=this in favor of arrow functions * Get rid of $.each in favor of .forEach Bug: T170807 Change-Id: I06fafd92a1712f143018e2ddff24fadf1a6882b3
This commit is contained in:
parent
2df22ef2b2
commit
1fff0d2ea7
BIN
resources/dist/index.js
vendored
BIN
resources/dist/index.js
vendored
Binary file not shown.
BIN
resources/dist/index.js.json
vendored
BIN
resources/dist/index.js.json
vendored
Binary file not shown.
|
@ -142,7 +142,7 @@ export function fetch( gateway, title, el, token ) {
|
||||||
token: token
|
token: token
|
||||||
} );
|
} );
|
||||||
} )
|
} )
|
||||||
.fail( function ( data, result ) {
|
.catch( function ( data, result ) {
|
||||||
// All failures, except those due to being offline or network error,
|
// All failures, except those due to being offline or network error,
|
||||||
// should present "There was an issue displaying this preview".
|
// should present "There was an issue displaying this preview".
|
||||||
// e.g.:
|
// e.g.:
|
||||||
|
@ -213,7 +213,7 @@ export function linkDwell( title, el, event, gateway, generateToken ) {
|
||||||
var previewState = getState().preview;
|
var previewState = getState().preview;
|
||||||
|
|
||||||
if ( previewState.enabled && isNewInteraction() ) {
|
if ( previewState.enabled && isNewInteraction() ) {
|
||||||
dispatch( fetch( gateway, title, el, token ) );
|
return dispatch( fetch( gateway, title, el, token ) );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,19 +67,10 @@ QUnit.test( '#boot', function ( assert ) {
|
||||||
* @param {Object} module
|
* @param {Object} module
|
||||||
*/
|
*/
|
||||||
function setupWait( module ) {
|
function setupWait( module ) {
|
||||||
module.waitDeferreds = [];
|
module.waitPromise = $.Deferred().resolve().promise();
|
||||||
module.waitPromises = [];
|
module.wait = module.sandbox.stub( WaitModule, 'default' ).callsFake( function () {
|
||||||
|
return module.waitPromise;
|
||||||
module.wait = module.sandbox.spy( function () {
|
|
||||||
var deferred = $.Deferred(),
|
|
||||||
promise = deferred.promise();
|
|
||||||
|
|
||||||
module.waitDeferreds.push( deferred );
|
|
||||||
module.waitPromises.push( promise );
|
|
||||||
return promise;
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
module.sandbox.stub( WaitModule, 'default' ).callsFake( module.wait );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,14 +86,10 @@ function setupEl( module ) {
|
||||||
|
|
||||||
QUnit.module( 'ext.popups/actions#linkDwell @integration', {
|
QUnit.module( 'ext.popups/actions#linkDwell @integration', {
|
||||||
beforeEach: function () {
|
beforeEach: function () {
|
||||||
var that = this;
|
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
preview: {}
|
preview: {}
|
||||||
};
|
};
|
||||||
this.getState = function () {
|
this.getState = () => this.state;
|
||||||
return that.state;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The worst-case implementation of mw.now.
|
// The worst-case implementation of mw.now.
|
||||||
mw.now = function () { return Date.now(); };
|
mw.now = function () { return Date.now(); };
|
||||||
|
@ -112,10 +99,12 @@ QUnit.module( 'ext.popups/actions#linkDwell @integration', {
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( '#linkDwell', function ( assert ) {
|
QUnit.test( '#linkDwell', function ( assert ) {
|
||||||
var p,
|
var linkDwelled,
|
||||||
event = {},
|
event = {},
|
||||||
dispatch = this.sandbox.spy();
|
dispatch = this.sandbox.spy();
|
||||||
|
|
||||||
|
assert.expect( 2 );
|
||||||
|
|
||||||
this.sandbox.stub( mw, 'now' ).returns( new Date() );
|
this.sandbox.stub( mw, 'now' ).returns( new Date() );
|
||||||
this.sandbox.stub( actions, 'fetch' );
|
this.sandbox.stub( actions, 'fetch' );
|
||||||
|
|
||||||
|
@ -124,7 +113,7 @@ QUnit.test( '#linkDwell', function ( assert ) {
|
||||||
activeToken: generateToken()
|
activeToken: generateToken()
|
||||||
};
|
};
|
||||||
|
|
||||||
p = actions.linkDwell(
|
linkDwelled = actions.linkDwell(
|
||||||
this.title, this.el, event, /* gateway = */ null, generateToken
|
this.title, this.el, event, /* gateway = */ null, generateToken
|
||||||
)(
|
)(
|
||||||
dispatch,
|
dispatch,
|
||||||
|
@ -150,21 +139,22 @@ QUnit.test( '#linkDwell', function ( assert ) {
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
p.then( function () {
|
return linkDwelled.then( function () {
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
dispatch.callCount,
|
dispatch.callCount,
|
||||||
2,
|
2,
|
||||||
'The fetch action is dispatched after FETCH_COMPLETE milliseconds.'
|
'The fetch action is dispatched after FETCH_COMPLETE milliseconds.'
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
return p;
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( '#linkDwell doesn\'t continue when previews are disabled', function ( assert ) {
|
QUnit.test( '#linkDwell doesn\'t continue when previews are disabled', function ( assert ) {
|
||||||
var p,
|
var linkDwelled,
|
||||||
event = {},
|
event = {},
|
||||||
dispatch = this.sandbox.spy();
|
dispatch = this.sandbox.spy();
|
||||||
|
|
||||||
|
assert.expect( 2 );
|
||||||
|
|
||||||
// Stub the state tree being updated by the LINK_DWELL action.
|
// Stub the state tree being updated by the LINK_DWELL action.
|
||||||
this.state.preview = {
|
this.state.preview = {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
@ -172,7 +162,7 @@ QUnit.test( '#linkDwell doesn\'t continue when previews are disabled', function
|
||||||
activeToken: generateToken()
|
activeToken: generateToken()
|
||||||
};
|
};
|
||||||
|
|
||||||
p = actions.linkDwell(
|
linkDwelled = actions.linkDwell(
|
||||||
this.title, this.el, event, /* gateway = */ null, generateToken
|
this.title, this.el, event, /* gateway = */ null, generateToken
|
||||||
)(
|
)(
|
||||||
dispatch,
|
dispatch,
|
||||||
|
@ -181,18 +171,18 @@ QUnit.test( '#linkDwell doesn\'t continue when previews are disabled', function
|
||||||
|
|
||||||
assert.strictEqual( dispatch.callCount, 1 );
|
assert.strictEqual( dispatch.callCount, 1 );
|
||||||
|
|
||||||
p.then( function () {
|
return linkDwelled.then( function () {
|
||||||
assert.strictEqual( dispatch.callCount, 1 );
|
assert.strictEqual( dispatch.callCount, 1 );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
return p;
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( '#linkDwell doesn\'t continue if the token has changed', function ( assert ) {
|
QUnit.test( '#linkDwell doesn\'t continue if the token has changed', function ( assert ) {
|
||||||
var p,
|
var linkDwelled,
|
||||||
event = {},
|
event = {},
|
||||||
dispatch = this.sandbox.spy();
|
dispatch = this.sandbox.spy();
|
||||||
|
|
||||||
|
assert.expect( 1 );
|
||||||
|
|
||||||
// Stub the state tree being updated by a LINK_DWELL action.
|
// Stub the state tree being updated by a LINK_DWELL action.
|
||||||
this.state.preview = {
|
this.state.preview = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -200,7 +190,7 @@ QUnit.test( '#linkDwell doesn\'t continue if the token has changed', function (
|
||||||
activeToken: generateToken()
|
activeToken: generateToken()
|
||||||
};
|
};
|
||||||
|
|
||||||
p = actions.linkDwell(
|
linkDwelled = actions.linkDwell(
|
||||||
this.title, this.el, event, /* gateway = */ null, generateToken
|
this.title, this.el, event, /* gateway = */ null, generateToken
|
||||||
)(
|
)(
|
||||||
dispatch,
|
dispatch,
|
||||||
|
@ -219,24 +209,23 @@ QUnit.test( '#linkDwell doesn\'t continue if the token has changed', function (
|
||||||
activeToken: 'banana'
|
activeToken: 'banana'
|
||||||
};
|
};
|
||||||
|
|
||||||
p.then( function () {
|
return linkDwelled.then( function () {
|
||||||
assert.strictEqual( dispatch.callCount, 1 );
|
assert.strictEqual( dispatch.callCount, 1 );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
return p;
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( '#linkDwell dispatches the fetch action', function ( assert ) {
|
QUnit.test( '#linkDwell dispatches the fetch action', function ( assert ) {
|
||||||
var p,
|
var event = {},
|
||||||
event = {},
|
|
||||||
dispatch = this.sandbox.spy();
|
dispatch = this.sandbox.spy();
|
||||||
|
|
||||||
|
assert.expect( 1 );
|
||||||
|
|
||||||
this.state.preview = {
|
this.state.preview = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
activeToken: generateToken()
|
activeToken: generateToken()
|
||||||
};
|
};
|
||||||
|
|
||||||
p = actions.linkDwell(
|
return actions.linkDwell(
|
||||||
this.title, this.el, event, /* gateway = */ null, generateToken
|
this.title, this.el, event, /* gateway = */ null, generateToken
|
||||||
)(
|
)(
|
||||||
dispatch,
|
dispatch,
|
||||||
|
@ -244,28 +233,22 @@ QUnit.test( '#linkDwell dispatches the fetch action', function ( assert ) {
|
||||||
).then( function () {
|
).then( function () {
|
||||||
assert.strictEqual( dispatch.callCount, 2 );
|
assert.strictEqual( dispatch.callCount, 2 );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
return p;
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.module( 'ext.popups/actions#fetch', {
|
QUnit.module( 'ext.popups/actions#fetch', {
|
||||||
beforeEach: function () {
|
beforeEach: function () {
|
||||||
var that = this;
|
|
||||||
|
|
||||||
// Setup the mw.now stub before actions is re-required in setupWait
|
|
||||||
this.now = 0;
|
this.now = 0;
|
||||||
|
|
||||||
this.sandbox.stub( mw, 'now' ).callsFake( function () {
|
this.sandbox.stub( mw, 'now' ).callsFake( () => this.now );
|
||||||
return that.now;
|
|
||||||
} );
|
|
||||||
|
|
||||||
setupWait( this );
|
setupWait( this );
|
||||||
setupEl( this );
|
setupEl( this );
|
||||||
|
|
||||||
this.gatewayDeferred = $.Deferred();
|
this.gatewayDeferred = $.Deferred();
|
||||||
this.gatewayPromise = this.gatewayDeferred.promise();
|
|
||||||
this.gateway = {
|
this.gateway = {
|
||||||
getPageSummary: this.sandbox.stub().returns( this.gatewayPromise )
|
getPageSummary: this.sandbox.stub().returns(
|
||||||
|
this.gatewayDeferred.promise()
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.dispatch = this.sandbox.spy();
|
this.dispatch = this.sandbox.spy();
|
||||||
|
@ -273,15 +256,17 @@ QUnit.module( 'ext.popups/actions#fetch', {
|
||||||
this.token = '1234567890';
|
this.token = '1234567890';
|
||||||
|
|
||||||
// Sugar.
|
// Sugar.
|
||||||
this.fetch = function () {
|
this.fetch = () => {
|
||||||
return actions.fetch(
|
return actions.fetch(
|
||||||
that.gateway, that.title, that.el, that.token
|
this.gateway, this.title, this.el, this.token
|
||||||
)( that.dispatch );
|
)( this.dispatch );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'it should fetch data from the gateway immediately', function ( assert ) {
|
QUnit.test( 'it should fetch data from the gateway immediately', function ( assert ) {
|
||||||
|
assert.expect( 3 );
|
||||||
|
|
||||||
this.fetch();
|
this.fetch();
|
||||||
|
|
||||||
assert.ok( this.gateway.getPageSummary.calledWith( 'Foo' ) );
|
assert.ok( this.gateway.getPageSummary.calledWith( 'Foo' ) );
|
||||||
|
@ -301,19 +286,21 @@ QUnit.test( 'it should fetch data from the gateway immediately', function ( asse
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'it should dispatch the FETCH_END action when the API request ends', function ( assert ) {
|
QUnit.test( 'it should dispatch the FETCH_END action when the API request ends', function ( assert ) {
|
||||||
var that = this;
|
var fetched;
|
||||||
|
|
||||||
this.fetch();
|
assert.expect( 1 );
|
||||||
|
|
||||||
|
fetched = this.fetch();
|
||||||
|
|
||||||
this.now += 115;
|
this.now += 115;
|
||||||
this.gatewayDeferred.resolve( {} );
|
this.gatewayDeferred.resolve( {} );
|
||||||
|
|
||||||
return this.gatewayPromise.then( function () {
|
return fetched.then( () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
that.dispatch.getCall( 1 ).args[ 0 ],
|
this.dispatch.getCall( 1 ).args[ 0 ],
|
||||||
{
|
{
|
||||||
type: 'FETCH_END',
|
type: 'FETCH_END',
|
||||||
el: that.el,
|
el: this.el,
|
||||||
timestamp: 115
|
timestamp: 115
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -321,112 +308,82 @@ QUnit.test( 'it should dispatch the FETCH_END action when the API request ends',
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'it should delay dispatching the FETCH_COMPLETE action', function ( assert ) {
|
QUnit.test( 'it should delay dispatching the FETCH_COMPLETE action', function ( assert ) {
|
||||||
var whenDeferred = $.Deferred(),
|
var result = {},
|
||||||
whenSpy,
|
fetched = this.fetch();
|
||||||
args,
|
|
||||||
result = {},
|
|
||||||
that = this;
|
|
||||||
|
|
||||||
whenSpy = this.sandbox.stub( $, 'when' )
|
assert.expect( 2 );
|
||||||
.returns( whenDeferred.promise() );
|
|
||||||
|
|
||||||
this.fetch();
|
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
this.wait.getCall( 0 ).args[ 0 ],
|
this.wait.getCall( 0 ).args[ 0 ],
|
||||||
350,
|
350,
|
||||||
'It waits for FETCH_COMPLETE_TARGET_DELAY - FETCH_START_DELAY milliseconds.'
|
'It waits for FETCH_COMPLETE_TARGET_DELAY - FETCH_START_DELAY milliseconds.'
|
||||||
);
|
);
|
||||||
|
this.gatewayDeferred.resolve( result );
|
||||||
|
|
||||||
// ---
|
return fetched.then( () => {
|
||||||
args = whenSpy.getCall( 0 ).args;
|
assert.deepEqual(
|
||||||
|
this.dispatch.getCall( 2 ).args[ 0 ],
|
||||||
// This assertion is disabled due to $.Promise#then and #fail returning a new
|
{
|
||||||
// instance of $.Promise.
|
type: 'FETCH_COMPLETE',
|
||||||
// assert.strictEqual( args[ 0 ], this.gatewayPromise );
|
el: this.el,
|
||||||
|
result: result,
|
||||||
assert.strictEqual( args[ 1 ], this.waitPromises[ 0 ] );
|
token: this.token
|
||||||
|
}
|
||||||
// ---
|
);
|
||||||
whenDeferred.resolve( result );
|
|
||||||
|
|
||||||
return whenDeferred.then( function () {
|
|
||||||
|
|
||||||
// Ensure the following assertions are made after all callbacks have been
|
|
||||||
// executed. Use setTimeout( _, 0 ) since it's not critical that these
|
|
||||||
// assertions are run before I/O is processed, i.e. we don't require
|
|
||||||
// process.nextTick.
|
|
||||||
setTimeout( function () {
|
|
||||||
assert.deepEqual(
|
|
||||||
that.dispatch.getCall( 1 ).args[ 0 ],
|
|
||||||
{
|
|
||||||
type: 'FETCH_COMPLETE',
|
|
||||||
el: that.el,
|
|
||||||
result: result,
|
|
||||||
token: that.token
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}, 0 );
|
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'it should dispatch the FETCH_FAILED action when the request fails', function ( assert ) {
|
QUnit.test( 'it should dispatch the FETCH_FAILED action when the request fails', function ( assert ) {
|
||||||
var that = this;
|
var fetched = this.fetch();
|
||||||
|
|
||||||
assert.expect( 2 );
|
assert.expect( 2 );
|
||||||
|
|
||||||
this.gatewayDeferred.reject( new Error( 'API req failed' ) );
|
this.gatewayDeferred.reject( new Error( 'API req failed' ) );
|
||||||
|
|
||||||
const fetch = this.fetch().catch( function () {
|
this.now += 115;
|
||||||
|
|
||||||
|
return fetched.then( () => {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
that.dispatch.callCount, 3,
|
this.dispatch.callCount, 3,
|
||||||
'dispatch called thrice, START, FAILED, and COMPLETE'
|
'dispatch called thrice, START, FAILED, and COMPLETE'
|
||||||
);
|
);
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
that.dispatch.getCall( 1 ).args[ 0 ],
|
this.dispatch.getCall( 1 ).args[ 0 ],
|
||||||
{
|
{
|
||||||
type: 'FETCH_FAILED',
|
type: 'FETCH_FAILED',
|
||||||
el: that.el
|
el: this.el
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
this.now += 115;
|
|
||||||
|
|
||||||
return fetch;
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'it should dispatch the FETCH_FAILED action when the request fails even after the wait timeout', function ( assert ) {
|
QUnit.test( 'it should dispatch the FETCH_FAILED action when the request fails even after the wait timeout', function ( assert ) {
|
||||||
var that = this;
|
var fetched = this.fetch();
|
||||||
|
|
||||||
assert.expect( 2 );
|
assert.expect( 2 );
|
||||||
|
|
||||||
const fetch = this.fetch().catch( function () {
|
// After the wait interval happens, resolve the gateway request
|
||||||
|
return this.waitPromise.then( () => {
|
||||||
|
this.gatewayDeferred.reject( new Error( 'API req failed' ) );
|
||||||
|
return fetched;
|
||||||
|
} ).then( () => {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
that.dispatch.callCount, 3,
|
this.dispatch.callCount, 3,
|
||||||
'dispatch called thrice, START, FAILED, and COMPLETE'
|
'dispatch called thrice, START, FAILED, and COMPLETE'
|
||||||
);
|
);
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
that.dispatch.getCall( 1 ).args[ 0 ],
|
this.dispatch.getCall( 1 ).args[ 0 ],
|
||||||
{
|
{
|
||||||
type: 'FETCH_FAILED',
|
type: 'FETCH_FAILED',
|
||||||
el: that.el
|
el: this.el
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// After the wait interval happens, resolve the gateway request
|
|
||||||
this.waitPromises[ 0 ].then( function () {
|
|
||||||
that.gatewayDeferred.reject( new Error( 'API req failed' ) );
|
|
||||||
} );
|
|
||||||
|
|
||||||
this.waitDeferreds[ 0 ].resolve();
|
|
||||||
|
|
||||||
return fetch;
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.module( 'ext.popups/actions#abandon', {
|
QUnit.module( 'ext.popups/actions#abandon', {
|
||||||
beforeEach: function () {
|
beforeEach: function () {
|
||||||
|
setupWait( this );
|
||||||
setupEl( this );
|
setupEl( this );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
@ -440,13 +397,13 @@ QUnit.test( 'it should dispatch start and end actions', function ( assert ) {
|
||||||
activeToken: token
|
activeToken: token
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, p;
|
}, abandoned;
|
||||||
|
|
||||||
|
assert.expect( 3 );
|
||||||
|
|
||||||
this.sandbox.stub( mw, 'now' ).returns( new Date() );
|
this.sandbox.stub( mw, 'now' ).returns( new Date() );
|
||||||
|
|
||||||
setupWait( this );
|
abandoned = actions.abandon( this.el )( dispatch, getState );
|
||||||
|
|
||||||
actions.abandon( this.el )( dispatch, getState );
|
|
||||||
|
|
||||||
assert.ok( dispatch.calledWith( {
|
assert.ok( dispatch.calledWith( {
|
||||||
type: 'ABANDON_START',
|
type: 'ABANDON_START',
|
||||||
|
@ -461,7 +418,7 @@ QUnit.test( 'it should dispatch start and end actions', function ( assert ) {
|
||||||
'Have you spoken with #Design about changing this value?'
|
'Have you spoken with #Design about changing this value?'
|
||||||
);
|
);
|
||||||
|
|
||||||
p = this.waitPromises[ 0 ].then( function () {
|
return abandoned.then( function () {
|
||||||
assert.ok(
|
assert.ok(
|
||||||
dispatch.calledWith( {
|
dispatch.calledWith( {
|
||||||
type: 'ABANDON_END',
|
type: 'ABANDON_END',
|
||||||
|
@ -470,10 +427,6 @@ QUnit.test( 'it should dispatch start and end actions', function ( assert ) {
|
||||||
'ABANDON_* share the same token.'
|
'ABANDON_* share the same token.'
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// After ABANDON_END_DELAY milliseconds...
|
|
||||||
this.waitDeferreds[ 0 ].resolve();
|
|
||||||
return p;
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'it shouldn\'t dispatch under certain conditions', function ( assert ) {
|
QUnit.test( 'it shouldn\'t dispatch under certain conditions', function ( assert ) {
|
||||||
|
|
|
@ -14,8 +14,7 @@ QUnit.test( '#has', function ( assert ) {
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( '#get', function ( assert ) {
|
QUnit.test( '#get', function ( assert ) {
|
||||||
var service = {},
|
var service = {};
|
||||||
that = this;
|
|
||||||
|
|
||||||
this.factory.returns( service );
|
this.factory.returns( service );
|
||||||
|
|
||||||
|
@ -39,9 +38,7 @@ QUnit.test( '#get', function ( assert ) {
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
assert.throws(
|
assert.throws(
|
||||||
function () {
|
() => { this.container.get( 'bar' ); },
|
||||||
that.container.get( 'bar' );
|
|
||||||
},
|
|
||||||
/The service "bar" hasn't been defined./
|
/The service "bar" hasn't been defined./
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -8,9 +8,6 @@ import registerChangeListener from '../../src/changeListener';
|
||||||
|
|
||||||
var mw = mediaWiki,
|
var mw = mediaWiki,
|
||||||
$ = jQuery,
|
$ = jQuery,
|
||||||
// Store the real wait to be actually used in tests
|
|
||||||
wait = WaitModule.default,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether Gateway#getPageSummary is resolved or rejected.
|
* Whether Gateway#getPageSummary is resolved or rejected.
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
|
@ -56,15 +53,13 @@ function constant( x ) { return function () { return x; }; }
|
||||||
|
|
||||||
QUnit.module( 'ext.popups preview @integration', {
|
QUnit.module( 'ext.popups preview @integration', {
|
||||||
beforeEach: function () {
|
beforeEach: function () {
|
||||||
var that = this;
|
|
||||||
|
|
||||||
// The worst-case implementation of mw.now.
|
// The worst-case implementation of mw.now.
|
||||||
mw.now = function () { return Date.now(); };
|
mw.now = function () { return Date.now(); };
|
||||||
|
|
||||||
this.resetWait = function () {
|
this.resetWait = () => {
|
||||||
that.waitDeferred = $.Deferred();
|
this.waitDeferred = $.Deferred();
|
||||||
that.waitPromise = that.waitDeferred.promise();
|
this.waitPromise = this.waitDeferred.promise();
|
||||||
that.wait.returns( that.waitPromise );
|
this.wait.returns( this.waitPromise );
|
||||||
};
|
};
|
||||||
|
|
||||||
this.wait = this.sandbox.stub( WaitModule, 'default' );
|
this.wait = this.sandbox.stub( WaitModule, 'default' );
|
||||||
|
@ -80,8 +75,8 @@ QUnit.module( 'ext.popups preview @integration', {
|
||||||
this.store.dispatch
|
this.store.dispatch
|
||||||
);
|
);
|
||||||
|
|
||||||
this.registerChangeListener = function ( fn ) {
|
this.registerChangeListener = ( fn ) => {
|
||||||
return registerChangeListener( that.store, fn );
|
return registerChangeListener( this.store, fn );
|
||||||
};
|
};
|
||||||
|
|
||||||
this.title = stubs.createStubTitle( 1, 'Foo' );
|
this.title = stubs.createStubTitle( 1, 'Foo' );
|
||||||
|
@ -102,71 +97,55 @@ QUnit.module( 'ext.popups preview @integration', {
|
||||||
{ get: identity }
|
{ get: identity }
|
||||||
);
|
);
|
||||||
|
|
||||||
this.dwell = function (
|
this.dwell = (
|
||||||
title, el, ev, fetchResponse, resolution = FETCH_RESOLUTION.RESOLVE
|
title, el, ev, fetchResponse, resolution = FETCH_RESOLUTION.RESOLVE
|
||||||
) {
|
) => {
|
||||||
that.resetWait();
|
this.resetWait();
|
||||||
that.actions.linkDwell( title, el, ev, {
|
return this.actions.linkDwell( title, el, ev, {
|
||||||
getPageSummary: function () {
|
getPageSummary: function () {
|
||||||
var method = resolution === FETCH_RESOLUTION.RESOLVE ?
|
var method = resolution === FETCH_RESOLUTION.RESOLVE ?
|
||||||
'resolve' : 'reject';
|
'resolve' : 'reject';
|
||||||
return $.Deferred()[ method ]( fetchResponse ).promise();
|
return $.Deferred()[ method ]( fetchResponse ).promise();
|
||||||
}
|
}
|
||||||
}, function () { return 'pagetoken'; } );
|
}, function () { return 'pagetoken'; } );
|
||||||
return that.waitPromise;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.dwellAndShowPreview = function (
|
this.dwellAndShowPreview = (
|
||||||
title, el, ev, fetchResponse, reject = FETCH_RESOLUTION.RESOLVE
|
title, el, ev, fetchResponse, reject = FETCH_RESOLUTION.RESOLVE
|
||||||
) {
|
) => {
|
||||||
that.dwell( title, el, ev, fetchResponse, reject );
|
var dwelled = this.dwell( title, el, ev, fetchResponse, reject );
|
||||||
that.waitDeferred.resolve();
|
// Resolve the wait timeout for the linkDwell and the fetch action
|
||||||
|
this.waitDeferred.resolve();
|
||||||
// Wait for the next tick to resolve pending callbacks. N.B. that the
|
return dwelled;
|
||||||
// fetch action invokes wait twice.
|
|
||||||
return wait( 0 )
|
|
||||||
.then( function () {
|
|
||||||
that.waitDeferred.resolve();
|
|
||||||
|
|
||||||
return that.waitPromise;
|
|
||||||
} );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.abandon = function () {
|
this.abandon = () => {
|
||||||
that.resetWait();
|
this.resetWait();
|
||||||
that.actions.abandon();
|
return this.actions.abandon();
|
||||||
return that.waitPromise;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.abandonAndWait = function () {
|
this.abandonAndWait = () => {
|
||||||
that.abandon();
|
var abandoned = this.abandon();
|
||||||
that.waitDeferred.resolve();
|
this.waitDeferred.resolve();
|
||||||
return wait( 0 ); // Wait for next tick to resolve pending callbacks
|
return abandoned;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.dwellAndPreviewDwell = function ( title, el, ev, res ) {
|
this.dwellAndPreviewDwell = ( title, el, ev, res ) => {
|
||||||
return that.dwellAndShowPreview( title, el, ev, res ).then( function () {
|
return this.dwellAndShowPreview( title, el, ev, res ).then( () => {
|
||||||
|
|
||||||
// Get out of the link, and before the delay ends...
|
// Get out of the link, and before the delay ends...
|
||||||
var abandonPromise = that.abandon( el ),
|
var abandonPromise = this.abandon(),
|
||||||
abandonDeferred = that.waitDeferred;
|
abandonWaitDeferred = this.waitDeferred;
|
||||||
|
|
||||||
// Dwell over the preview
|
// Dwell over the preview
|
||||||
that.actions.previewDwell( el );
|
this.actions.previewDwell( el );
|
||||||
|
|
||||||
// Then the abandon delay finishes
|
// Then the abandon delay finishes
|
||||||
abandonDeferred.resolve();
|
abandonWaitDeferred.resolve();
|
||||||
|
|
||||||
return abandonPromise;
|
return abandonPromise;
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
this.abandonPreview = function () {
|
|
||||||
that.resetWait();
|
|
||||||
that.actions.abandon();
|
|
||||||
|
|
||||||
return that.waitPromise;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -224,56 +203,54 @@ QUnit.test( 'in ACTIVE state, fetch fail switches it to DATA', function ( assert
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'in ACTIVE state, abandon start, and then end, switch it to INACTIVE', function ( assert ) {
|
QUnit.test( 'in ACTIVE state, abandon start, and then end, switch it to INACTIVE', function ( assert ) {
|
||||||
var that = this,
|
var el = this.el;
|
||||||
el = this.el;
|
|
||||||
|
|
||||||
return this.dwellAndShowPreview( this.title, el, 'event', 42 )
|
return this.dwellAndShowPreview( this.title, el, 'event', 42 )
|
||||||
.then( function () {
|
.then( () => {
|
||||||
return that.abandonAndWait( el );
|
return this.abandonAndWait( el );
|
||||||
} ).then( function () {
|
} ).then( () => {
|
||||||
var state = that.store.getState();
|
var state = this.store.getState();
|
||||||
assert.equal( state.preview.activeLink, undefined,
|
assert.equal( state.preview.activeLink, undefined,
|
||||||
'After abandoning, preview is back to INACTIVE' );
|
'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 ) {
|
QUnit.test( 'in ACTIVE state, abandon link, and then dwell preview, should keep it active after all delays', function ( assert ) {
|
||||||
var that = this,
|
var el = this.el;
|
||||||
el = this.el;
|
|
||||||
|
|
||||||
return this.dwellAndPreviewDwell( this.title, el, 'event', 42 )
|
return this.dwellAndPreviewDwell( this.title, el, 'event', 42 )
|
||||||
.then( function () {
|
.then( () => {
|
||||||
var state = that.store.getState();
|
var state = this.store.getState();
|
||||||
assert.equal( state.preview.activeLink, el );
|
assert.equal( state.preview.activeLink, el );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'in ACTIVE state, abandon link, hover preview, back to link, should keep it active after all delays', function ( assert ) {
|
QUnit.test( 'in ACTIVE state, abandon link, hover preview, back to link, should keep it active after all delays', function ( assert ) {
|
||||||
var that = this,
|
var el = this.el;
|
||||||
el = this.el;
|
|
||||||
|
|
||||||
|
// Dwell link, abandon it & hover preview
|
||||||
return this.dwellAndPreviewDwell( this.title, el, 'event', 42 )
|
return this.dwellAndPreviewDwell( this.title, el, 'event', 42 )
|
||||||
.then( function () {
|
.then( () => {
|
||||||
var abandonPreviewDeferred, dwellPromise, dwellDeferred;
|
var abandonedPreview, abandonWaitDeferred, dwelled, dwellWaitDeferred;
|
||||||
|
|
||||||
// Start abandoning the preview
|
// Start abandoning the preview
|
||||||
that.abandonPreview( el );
|
abandonedPreview = this.abandon();
|
||||||
|
abandonWaitDeferred = this.waitDeferred;
|
||||||
|
|
||||||
abandonPreviewDeferred = that.waitDeferred;
|
// Dwell back into the link, new event ('event2') is triggered
|
||||||
// Dwell back into the link, new event is triggered
|
dwelled = this.dwell( this.title, el, 'event2', 42 );
|
||||||
dwellPromise = that.dwell( that.title, el, 'event2', 42 );
|
dwellWaitDeferred = this.waitDeferred;
|
||||||
dwellDeferred = that.waitDeferred;
|
|
||||||
|
|
||||||
// Preview abandon happens next, before the fetch
|
// Preview abandon happens next, before the fetch
|
||||||
abandonPreviewDeferred.resolve();
|
abandonWaitDeferred.resolve();
|
||||||
|
|
||||||
// Then fetch happens
|
// Then dwell wait & fetch happens
|
||||||
dwellDeferred.resolve();
|
dwellWaitDeferred.resolve();
|
||||||
|
|
||||||
return dwellPromise;
|
return $.when( abandonedPreview, dwelled );
|
||||||
} )
|
} )
|
||||||
.then( function () {
|
.then( () => {
|
||||||
var state = that.store.getState();
|
var state = this.store.getState();
|
||||||
assert.equal( state.preview.activeLink, el );
|
assert.equal( state.preview.activeLink, el );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -16,8 +16,7 @@ QUnit.module( 'ext.popups.preview.settingsBehavior', {
|
||||||
} );
|
} );
|
||||||
|
|
||||||
QUnit.test( 'it should set the settingsUrl on wgPopupsBetaFeature', function ( assert ) {
|
QUnit.test( 'it should set the settingsUrl on wgPopupsBetaFeature', function ( assert ) {
|
||||||
var that = this,
|
var user = createStubUser( /* isAnon = */ false ),
|
||||||
user = createStubUser( /* isAnon = */ false ),
|
|
||||||
actions = {},
|
actions = {},
|
||||||
cases;
|
cases;
|
||||||
|
|
||||||
|
@ -26,12 +25,12 @@ QUnit.test( 'it should set the settingsUrl on wgPopupsBetaFeature', function ( a
|
||||||
[ false, 'Special:Preferences#mw-prefsection-rendering' ]
|
[ false, 'Special:Preferences#mw-prefsection-rendering' ]
|
||||||
];
|
];
|
||||||
|
|
||||||
$.each( cases, function ( i, testCase ) {
|
cases.forEach( ( testCase ) => {
|
||||||
var behavior;
|
var behavior;
|
||||||
|
|
||||||
that.config.set( 'wgPopupsBetaFeature', testCase[ 0 ] );
|
this.config.set( 'wgPopupsBetaFeature', testCase[ 0 ] );
|
||||||
|
|
||||||
behavior = createPreviewBehavior( that.config, user, actions );
|
behavior = createPreviewBehavior( this.config, user, actions );
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
behavior.settingsUrl,
|
behavior.settingsUrl,
|
||||||
|
|
Loading…
Reference in a new issue