mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Popups
synced 2024-11-27 17:00:37 +00:00
Merge "Hygiene: Use factory functions instead of classes" into mpga
This commit is contained in:
commit
d7b5f56665
|
@ -17,9 +17,9 @@
|
|||
*/
|
||||
function createGateway( config ) {
|
||||
if ( config.get( 'wgPopupsAPIUseRESTBase' ) ) {
|
||||
return new mw.popups.RESTBaseGateway( $ );
|
||||
return mw.popups.createRESTBaseGateway( $.ajax );
|
||||
}
|
||||
return new mw.popups.MediaWikiApiGateway( new mw.Api() );
|
||||
return mw.popups.createMediaWikiApiGateway( new mw.Api() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,16 +10,13 @@
|
|||
/**
|
||||
* Interface for API gateway that fetches page summary
|
||||
*
|
||||
* @interface Gateway
|
||||
* @function
|
||||
* @param {mw.Api|jQuery}
|
||||
* @interface ext.popups.Gateway
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get page summary
|
||||
*
|
||||
* Returns a preview model fetched from the api
|
||||
* @function
|
||||
* @name Gateway#getPageSummary
|
||||
* @name ext.popups.Gateway#getPageSummary
|
||||
* @param {String} title Page title we're querying
|
||||
* @returns {jQuery.Promise} that resolves with {ext.popups.PreviewModel}
|
||||
* if the request is successful and the response is not empty; otherwise
|
||||
|
@ -27,147 +24,163 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* MediaWiki API gateway
|
||||
* MediaWiki API gateway factory
|
||||
*
|
||||
* @class
|
||||
* @param {mw.Api} api
|
||||
* @implements {ext.popups.Gateway}
|
||||
* @returns {ext.popups.Gateway}
|
||||
*/
|
||||
function MediaWikiApiGateway( api ) {
|
||||
this.api = api;
|
||||
}
|
||||
function createMediaWikiApiGateway( api ) {
|
||||
|
||||
/**
|
||||
* Fetch page data from the API
|
||||
*
|
||||
* @private
|
||||
* @param {String} title
|
||||
* @return {jQuery.Promise}
|
||||
*/
|
||||
MediaWikiApiGateway.prototype.fetch = function ( title ) {
|
||||
return this.api.get( {
|
||||
action: 'query',
|
||||
prop: 'info|extracts|pageimages|revisions|info',
|
||||
formatversion: 2,
|
||||
redirects: true,
|
||||
exintro: true,
|
||||
exchars: EXTRACT_LENGTH,
|
||||
/**
|
||||
* Fetch page data from the API
|
||||
*
|
||||
* @param {String} title
|
||||
* @return {jQuery.Promise}
|
||||
*/
|
||||
function fetch( title ) {
|
||||
return api.get( {
|
||||
action: 'query',
|
||||
prop: 'info|extracts|pageimages|revisions|info',
|
||||
formatversion: 2,
|
||||
redirects: true,
|
||||
exintro: true,
|
||||
exchars: EXTRACT_LENGTH,
|
||||
|
||||
// There is an added geometric limit on .mwe-popups-extract
|
||||
// so that text does not overflow from the card.
|
||||
explaintext: true,
|
||||
// There is an added geometric limit on .mwe-popups-extract
|
||||
// so that text does not overflow from the card.
|
||||
explaintext: true,
|
||||
|
||||
piprop: 'thumbnail',
|
||||
pithumbsize: THUMBNAIL_SIZE,
|
||||
rvprop: 'timestamp',
|
||||
inprop: 'url',
|
||||
titles: title,
|
||||
smaxage: CACHE_LIFETIME,
|
||||
maxage: CACHE_LIFETIME,
|
||||
uselang: 'content'
|
||||
}, {
|
||||
headers: {
|
||||
'X-Analytics': 'preview=1'
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract page data from the response
|
||||
*
|
||||
* @private
|
||||
* @param {Object} data API response data
|
||||
* @throws {Error} Throw an error if page data cannot be extracted,
|
||||
* i.e. if the response is empty,
|
||||
* @returns {Object}
|
||||
*/
|
||||
MediaWikiApiGateway.prototype.extractPageFromResponse = function( data ) {
|
||||
if (
|
||||
data.query &&
|
||||
data.query.pages &&
|
||||
data.query.pages.length
|
||||
) {
|
||||
return data.query.pages[ 0 ];
|
||||
piprop: 'thumbnail',
|
||||
pithumbsize: THUMBNAIL_SIZE,
|
||||
rvprop: 'timestamp',
|
||||
inprop: 'url',
|
||||
titles: title,
|
||||
smaxage: CACHE_LIFETIME,
|
||||
maxage: CACHE_LIFETIME,
|
||||
uselang: 'content'
|
||||
}, {
|
||||
headers: {
|
||||
'X-Analytics': 'preview=1'
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
throw new Error( 'API response `query.pages` is empty.' );
|
||||
};
|
||||
/**
|
||||
* Extract page data from the response
|
||||
*
|
||||
* @param {Object} data API response data
|
||||
* @throws {Error} Throw an error if page data cannot be extracted,
|
||||
* i.e. if the response is empty,
|
||||
* @returns {Object}
|
||||
*/
|
||||
function extractPageFromResponse( data ) {
|
||||
if (
|
||||
data.query &&
|
||||
data.query.pages &&
|
||||
data.query.pages.length
|
||||
) {
|
||||
return data.query.pages[ 0 ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the API response to a preview model
|
||||
*
|
||||
* @private
|
||||
* @param {Object} page
|
||||
* @returns {ext.popups.PreviewModel}
|
||||
*/
|
||||
MediaWikiApiGateway.prototype.convertPageToModel = function( page ) {
|
||||
return mw.popups.preview.createModel(
|
||||
page.title,
|
||||
page.canonicalurl,
|
||||
page.pagelanguagehtmlcode,
|
||||
page.pagelanguagedir,
|
||||
page.extract,
|
||||
page.thumbnail
|
||||
);
|
||||
};
|
||||
throw new Error( 'API response `query.pages` is empty.' );
|
||||
}
|
||||
|
||||
MediaWikiApiGateway.prototype.getPageSummary = function( title ) {
|
||||
return this.fetch( title )
|
||||
.then( this.extractPageFromResponse )
|
||||
.then( this.convertPageToModel );
|
||||
};
|
||||
/**
|
||||
* Transform the API response to a preview model
|
||||
*
|
||||
* @param {Object} page
|
||||
* @returns {ext.popups.PreviewModel}
|
||||
*/
|
||||
function convertPageToModel( page ) {
|
||||
return mw.popups.preview.createModel(
|
||||
page.title,
|
||||
page.canonicalurl,
|
||||
page.pagelanguagehtmlcode,
|
||||
page.pagelanguagedir,
|
||||
page.extract,
|
||||
page.thumbnail
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* RESTBase gateway
|
||||
*
|
||||
* @class
|
||||
* @param {jQuery} api
|
||||
* @implements {ext.popups.Gateway}
|
||||
*/
|
||||
function RESTBaseGateway( api ) {
|
||||
this.api = api;
|
||||
/**
|
||||
* Get the page summary from the api and transform the data
|
||||
*
|
||||
* @param {String} title
|
||||
* @returns {jQuery.Promise<ext.popups.PreviewModel>}
|
||||
*/
|
||||
function getPageSummary( title ) {
|
||||
return fetch( title )
|
||||
.then( extractPageFromResponse )
|
||||
.then( convertPageToModel );
|
||||
}
|
||||
|
||||
return {
|
||||
fetch: fetch,
|
||||
extractPageFromResponse: extractPageFromResponse,
|
||||
convertPageToModel: convertPageToModel,
|
||||
getPageSummary: getPageSummary
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch page data from the API
|
||||
* RESTBase gateway factory
|
||||
*
|
||||
* @private
|
||||
* @param {String} title
|
||||
* @return {jQuery.Promise}
|
||||
* @param {Function} ajax function from jQuery for example
|
||||
* @returns {ext.popups.Gateway}
|
||||
*/
|
||||
RESTBaseGateway.prototype.fetch = function ( title ) {
|
||||
return this.api.ajax( {
|
||||
url: RESTBASE_ENDPOINT + encodeURIComponent( title ),
|
||||
headers: {
|
||||
Accept: 'application/json; charset=utf-8' +
|
||||
'profile="' + RESTBASE_PROFILE + '"'
|
||||
}
|
||||
} );
|
||||
};
|
||||
function createRESTBaseGateway( ajax ) {
|
||||
|
||||
/**
|
||||
* Transform the API response to a preview model
|
||||
*
|
||||
* @private
|
||||
* @param {Object} page
|
||||
* @returns {ext.popups.PreviewModel}
|
||||
*/
|
||||
RESTBaseGateway.prototype.convertPageToModel = function( page ) {
|
||||
return mw.popups.preview.createModel(
|
||||
page.title,
|
||||
new mw.Title( page.title ).getUrl(),
|
||||
page.lang,
|
||||
page.dir,
|
||||
page.extract,
|
||||
page.thumbnail
|
||||
);
|
||||
};
|
||||
/**
|
||||
* Fetch page data from the API
|
||||
*
|
||||
* @param {String} title
|
||||
* @return {jQuery.Promise}
|
||||
*/
|
||||
function fetch( title ) {
|
||||
return ajax( {
|
||||
url: RESTBASE_ENDPOINT + encodeURIComponent( title ),
|
||||
headers: {
|
||||
Accept: 'application/json; charset=utf-8' +
|
||||
'profile="' + RESTBASE_PROFILE + '"'
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
RESTBaseGateway.prototype.getPageSummary = function( title ) {
|
||||
return this.fetch( title )
|
||||
.then( this.convertPageToModel );
|
||||
};
|
||||
/**
|
||||
* Transform the API response to a preview model
|
||||
*
|
||||
* @param {Object} page
|
||||
* @returns {ext.popups.PreviewModel}
|
||||
*/
|
||||
function convertPageToModel( page ) {
|
||||
return mw.popups.preview.createModel(
|
||||
page.title,
|
||||
new mw.Title( page.title ).getUrl(),
|
||||
page.lang,
|
||||
page.dir,
|
||||
page.extract,
|
||||
page.thumbnail
|
||||
);
|
||||
}
|
||||
|
||||
mw.popups.MediaWikiApiGateway = MediaWikiApiGateway;
|
||||
mw.popups.RESTBaseGateway = RESTBaseGateway;
|
||||
/**
|
||||
* Get the page summary from the api and transform the data
|
||||
*
|
||||
* @param {String} title
|
||||
* @returns {jQuery.Promise<ext.popups.PreviewModel>}
|
||||
*/
|
||||
function getPageSummary( title ) {
|
||||
return fetch( title )
|
||||
.then( convertPageToModel );
|
||||
}
|
||||
|
||||
return {
|
||||
fetch: fetch,
|
||||
convertPageToModel: convertPageToModel,
|
||||
getPageSummary: getPageSummary
|
||||
};
|
||||
}
|
||||
|
||||
mw.popups.createMediaWikiApiGateway = createMediaWikiApiGateway;
|
||||
mw.popups.createRESTBaseGateway = createRESTBaseGateway;
|
||||
}( mediaWiki, jQuery ) );
|
||||
|
|
|
@ -302,7 +302,6 @@
|
|||
QUnit.test(
|
||||
'it shouldn\'t delay dispatching the FETCH_END action if the API request is over the target',
|
||||
function ( assert ) {
|
||||
var that = this;
|
||||
|
||||
this.fetch();
|
||||
|
||||
|
@ -358,8 +357,8 @@
|
|||
that.waitPromise.then( function () {
|
||||
assert.ok(
|
||||
dispatch.calledWith( {
|
||||
type: 'ABANDON_END',
|
||||
token: token
|
||||
type: 'ABANDON_END',
|
||||
token: token
|
||||
} ),
|
||||
'ABANDON_* share the same token.'
|
||||
);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
( function ( mw, $ ) {
|
||||
|
||||
var createModel = mw.popups.preview.createModel,
|
||||
MediaWikiApiGateway = mw.popups.MediaWikiApiGateway,
|
||||
RESTBaseGateway = mw.popups.RESTBaseGateway,
|
||||
createMediaWikiApiGateway = mw.popups.createMediaWikiApiGateway,
|
||||
createRESTBaseGateway = mw.popups.createRESTBaseGateway,
|
||||
MEDIAWIKI_API_RESPONSE = {
|
||||
query: {
|
||||
pages: [
|
||||
|
@ -74,11 +74,11 @@
|
|||
QUnit.module( 'ext.popups/gateway' );
|
||||
|
||||
QUnit.test( 'MediaWiki API gateway is called with correct arguments', function ( assert ) {
|
||||
var getSpy = this.sandbox.spy(),
|
||||
var spy = this.sandbox.spy(),
|
||||
api = {
|
||||
get: getSpy
|
||||
get: spy
|
||||
},
|
||||
gateway = new MediaWikiApiGateway( api ),
|
||||
gateway = createMediaWikiApiGateway( api ),
|
||||
expectedOptions = {
|
||||
action: 'query',
|
||||
prop: 'info|extracts|pageimages|revisions|info',
|
||||
|
@ -104,12 +104,15 @@
|
|||
|
||||
gateway.fetch( 'Test Title' );
|
||||
|
||||
assert.deepEqual( getSpy.getCall( 0 ).args[ 0 ], expectedOptions, 'options' );
|
||||
assert.deepEqual( getSpy.getCall( 0 ).args[ 1 ], expectedHeaders, 'headers' );
|
||||
assert.deepEqual( spy.getCall( 0 ).args[ 0 ], expectedOptions, 'options' );
|
||||
assert.deepEqual( spy.getCall( 0 ).args[ 1 ], expectedHeaders, 'headers' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'MediaWiki API gateway is correctly extracting the page data from the response ', function ( assert ) {
|
||||
var gateway = new MediaWikiApiGateway(),
|
||||
var api = {
|
||||
get: this.sandbox.stub()
|
||||
},
|
||||
gateway = createMediaWikiApiGateway( api ),
|
||||
errorCases = [
|
||||
{},
|
||||
{
|
||||
|
@ -151,7 +154,7 @@
|
|||
} );
|
||||
|
||||
QUnit.test( 'MediaWiki API gateway is correctly converting the page data to a model ', function ( assert ) {
|
||||
var gateway = new MediaWikiApiGateway(),
|
||||
var gateway = createMediaWikiApiGateway(),
|
||||
page = gateway.extractPageFromResponse( MEDIAWIKI_API_RESPONSE );
|
||||
|
||||
assert.deepEqual(
|
||||
|
@ -165,7 +168,7 @@
|
|||
api = {
|
||||
get: this.sandbox.stub().returns( deferred.promise() )
|
||||
},
|
||||
gateway = new MediaWikiApiGateway( api ),
|
||||
gateway = createMediaWikiApiGateway( api ),
|
||||
done = assert.async( 1 );
|
||||
|
||||
gateway.getPageSummary( 'Test Title' ).fail( function () {
|
||||
|
@ -182,7 +185,7 @@
|
|||
$.Deferred().resolve( MEDIAWIKI_API_RESPONSE ).promise()
|
||||
)
|
||||
},
|
||||
gateway = new MediaWikiApiGateway( api ),
|
||||
gateway = createMediaWikiApiGateway( api ),
|
||||
done = assert.async( 1 );
|
||||
|
||||
gateway.getPageSummary( 'Test Title' ).done( function ( result ) {
|
||||
|
@ -221,7 +224,7 @@
|
|||
$.Deferred().resolve( response ).promise()
|
||||
)
|
||||
},
|
||||
gateway = new MediaWikiApiGateway( api ),
|
||||
gateway = createMediaWikiApiGateway( api ),
|
||||
done = assert.async( 1 );
|
||||
|
||||
gateway.getPageSummary( 'Test Title' ).done( function ( result ) {
|
||||
|
@ -233,10 +236,7 @@
|
|||
|
||||
QUnit.test( 'RESTBase gateway is called with correct arguments', function ( assert ) {
|
||||
var getSpy = this.sandbox.spy(),
|
||||
api = {
|
||||
ajax: getSpy
|
||||
},
|
||||
gateway = new RESTBaseGateway( api ),
|
||||
gateway = createRESTBaseGateway( getSpy ),
|
||||
expectedOptions = {
|
||||
url: '/api/rest_v1/page/summary/' + encodeURIComponent( 'Test Title' ),
|
||||
headers: {
|
||||
|
@ -251,7 +251,7 @@
|
|||
} );
|
||||
|
||||
QUnit.test( 'RESTBase gateway is correctly converting the page data to a model ', function ( assert ) {
|
||||
var gateway = new RESTBaseGateway();
|
||||
var gateway = createRESTBaseGateway();
|
||||
|
||||
assert.deepEqual(
|
||||
gateway.convertPageToModel( RESTBASE_RESPONSE ),
|
||||
|
@ -261,10 +261,8 @@
|
|||
|
||||
QUnit.test( 'RESTBase gateway handles the API failure', function ( assert ) {
|
||||
var deferred = $.Deferred(),
|
||||
api = {
|
||||
ajax: this.sandbox.stub().returns( deferred.promise() )
|
||||
},
|
||||
gateway = new RESTBaseGateway( api ),
|
||||
api = this.sandbox.stub().returns( deferred.promise() ),
|
||||
gateway = createRESTBaseGateway( api ),
|
||||
done = assert.async( 1 );
|
||||
|
||||
gateway.getPageSummary( 'Test Title' ).fail( function () {
|
||||
|
@ -276,12 +274,10 @@
|
|||
} );
|
||||
|
||||
QUnit.test( 'RESTBase gateway returns the correct data ', function ( assert ) {
|
||||
var api = {
|
||||
ajax: this.sandbox.stub().returns(
|
||||
$.Deferred().resolve( RESTBASE_RESPONSE ).promise()
|
||||
)
|
||||
},
|
||||
gateway = new RESTBaseGateway( api ),
|
||||
var api = this.sandbox.stub().returns(
|
||||
$.Deferred().resolve( RESTBASE_RESPONSE ).promise()
|
||||
),
|
||||
gateway = createRESTBaseGateway( api ),
|
||||
done = assert.async( 1 );
|
||||
|
||||
gateway.getPageSummary( 'Test Title' ).done( function ( result ) {
|
||||
|
@ -298,12 +294,10 @@
|
|||
detail: 'Page or revision not found.',
|
||||
uri: '/en.wikipedia.org/v1/page/summary/Missing_page'
|
||||
},
|
||||
api = {
|
||||
ajax: this.sandbox.stub().returns(
|
||||
$.Deferred().rejectWith( response ).promise()
|
||||
)
|
||||
},
|
||||
gateway = new RESTBaseGateway( api ),
|
||||
api = this.sandbox.stub().returns(
|
||||
$.Deferred().rejectWith( response ).promise()
|
||||
),
|
||||
gateway = createRESTBaseGateway( api ),
|
||||
done = assert.async( 1 );
|
||||
|
||||
gateway.getPageSummary( 'Missing Page' ).fail( function () {
|
||||
|
|
Loading…
Reference in a new issue